BlackBerry - Downloaded images are corrupted on wifi with HttpConnection - image

In my app I need to download several images from a server. I use this code to get a byte array :
HttpConnection connection = null;
InputStream inputStream = null;
byte[] data = null;
try
{
//connection = (HttpConnection)Connector.open(url);
connection = (HttpConnection)Connector.open(url, Connector.READ_WRITE, true);
int responseCode = connection.getResponseCode();
if(responseCode == HttpConnection.HTTP_OK)
{
inputStream = connection.openInputStream();
data = IOUtilities.streamToBytes(inputStream);
inputStream.close();
}
connection.close();
return data;
}
catch(IOException e)
{
return null;
}
The url are formed with the suffix ";deviceSide=false;ConnectionType=MDS - public" (without spaces) and it is working perfectly well.
The problem is that with phones that do not have a sim card, we can't connect to the internet via the MDS server. So we changed to use the connection factory and let BB choose whatever he wants :
ConnectionFactory connFact = new ConnectionFactory();
ConnectionDescriptor connDesc;
connDesc = connFact.getConnection(url);
if (connDesc != null)
{
final HttpConnection httpConn;
httpConn = (HttpConnection)connDesc.getConnection();
try
{
httpConn.setRequestMethod(HttpConnection.GET);
final int iResponseCode = httpConn.getResponseCode();
if(iResponseCode == HttpConnection.HTTP_OK)
{
InputStream inputStream = null;
try{
inputStream = httpConn.openInputStream();
byte[] data = IOUtilities.streamToBytes(inputStream);
return data;
}
catch(Exception e)
{
e.printStackTrace();
return null;
}
finally{
try
{
inputStream.close();
} catch (IOException e)
{
e.printStackTrace();
return null;
}
}
}
}
catch (IOException e)
{
System.err.println("Caught IOException: " + e.getMessage());
}
}
return null;
The connection works because it select the good prefix (interface=wifi in our case), but this create another problem.
Some images are not well downloaded, some of them (not the sames at each try) are corrupted, but only when the phone use a wifi connection to get these images.
How can I avoid this problem ? What method to get a connection do I have to use ? Is it possible to check if the user have a sim card in orderto use MDS - public ?
Here is an example of a corrupted image :
error image http://nsa30.casimages.com/img/2012/06/28/120628033716123822.png

try this:
public static String buildURL(String url) {
String connParams = "";
if (WLANInfo.getWLANState() == WLANInfo.WLAN_STATE_CONNECTED) {
connParams = ";interface=wifi"; //Connected to a WiFi access point.
} else {
int coverageStatus = CoverageInfo.getCoverageStatus();
//
if ((coverageStatus & CoverageInfo.COVERAGE_BIS_B) == CoverageInfo.COVERAGE_BIS_B) {
connParams = ";deviceside=false;ConnectionType=mds-public";
} else if ((coverageStatus & CoverageInfo.COVERAGE_DIRECT) == CoverageInfo.COVERAGE_DIRECT) {
// Have network coverage and a WAP 2.0 service book record
ServiceRecord record = getWAP2ServiceRecord();
//
if (record != null) {
connParams = ";deviceside=true;ConnectionUID=" + record.getUid();
} else {
connParams = ";deviceside=true";
}
} else if ((coverageStatus & CoverageInfo.COVERAGE_MDS) == CoverageInfo.COVERAGE_MDS) {
// Have an MDS service book and network coverage
connParams = ";deviceside=false";
}
}
Log.d("connection param"+url+connParams);
//
return url+connParams;
}
private static ServiceRecord getWAP2ServiceRecord() {
String cid;
String uid;
ServiceBook sb = ServiceBook.getSB();
ServiceRecord[] records = sb.getRecords();
//
for (int i = records.length -1; i >= 0; i--) {
cid = records[i].getCid().toLowerCase();
uid = records[i].getUid().toLowerCase();
//
if (cid.indexOf("wptcp") != -1
&& records[i].getUid().toLowerCase().indexOf("wap2") !=-1
&& uid.indexOf("wifi") == -1
&& uid.indexOf("mms") == -1) {
return records[i];
}
}
//
return null;
}

What happens when you append interface=wifi? Can you run the network diagnostic tool attached to below kb article and run all tests with SIM removed
http://supportforums.blackberry.com/t5/Java-Development/What-Is-Network-API-alternative-for-legacy-OS/ta-p/614822
Please also note that when download large files over BES/MDS there are limits imposed by MDS. Please ensure you review the below kb article
http://supportforums.blackberry.com/t5/Java-Development/Download-large-files-using-the-BlackBerry-Mobile-Data-System/ta-p/44585

You can check to see if coverage is sufficient for BIS_B (MDS public) but that won't help you if you are trying to support SIM-less users. I wonder if the problem is in an incomparability between the connection on Wi-Fi and IOUtilities.streamToBytes(). Try coding as recommended in the API documents.

Related

is it possible to read the content of the file present in the ftp server? [duplicate]

This is re-worded from a previous question (which was probably a bit unclear).
I want to download a text file via FTP from a remote server, read the contents of the text file into a string and then discard the file. I don't need to actually save the file.
I am using the Apache Commons library so I have:
import org.apache.commons.net.ftp.FTPClient;
Can anyone help please, without simply redirecting me to a page with lots of possible answers on?
Not going to do the work for you, but once you have your connection established, you can call retrieveFile and pass it an OutputStream. You can google around and find the rest...
FTPClient ftp = new FTPClient();
...
ByteArrayOutputStream myVar = new ByteArrayOutputStream();
ftp.retrieveFile("remoteFileName.txt", myVar);
ByteArrayOutputStream
retrieveFile
Normally I'd leave a comment asking 'What have you tried?'. But now I'm feeling more generous :-)
Here you go:
private void ftpDownload() {
FTPClient ftp = null;
try {
ftp = new FTPClient();
ftp.connect(mServer);
try {
int reply = ftp.getReplyCode();
if (!FTPReply.isPositiveCompletion(reply)) {
throw new Exception("Connect failed: " + ftp.getReplyString());
}
if (!ftp.login(mUser, mPassword)) {
throw new Exception("Login failed: " + ftp.getReplyString());
}
try {
ftp.enterLocalPassiveMode();
if (!ftp.setFileType(FTP.BINARY_FILE_TYPE)) {
Log.e(TAG, "Setting binary file type failed.");
}
transferFile(ftp);
} catch(Exception e) {
handleThrowable(e);
} finally {
if (!ftp.logout()) {
Log.e(TAG, "Logout failed.");
}
}
} catch(Exception e) {
handleThrowable(e);
} finally {
ftp.disconnect();
}
} catch(Exception e) {
handleThrowable(e);
}
}
private void transferFile(FTPClient ftp) throws Exception {
long fileSize = getFileSize(ftp, mFilePath);
InputStream is = retrieveFileStream(ftp, mFilePath);
downloadFile(is, buffer, fileSize);
is.close();
if (!ftp.completePendingCommand()) {
throw new Exception("Pending command failed: " + ftp.getReplyString());
}
}
private InputStream retrieveFileStream(FTPClient ftp, String filePath)
throws Exception {
InputStream is = ftp.retrieveFileStream(filePath);
int reply = ftp.getReplyCode();
if (is == null
|| (!FTPReply.isPositivePreliminary(reply)
&& !FTPReply.isPositiveCompletion(reply))) {
throw new Exception(ftp.getReplyString());
}
return is;
}
private byte[] downloadFile(InputStream is, long fileSize)
throws Exception {
byte[] buffer = new byte[fileSize];
if (is.read(buffer, 0, buffer.length)) == -1) {
return null;
}
return buffer; // <-- Here is your file's contents !!!
}
private long getFileSize(FTPClient ftp, String filePath) throws Exception {
long fileSize = 0;
FTPFile[] files = ftp.listFiles(filePath);
if (files.length == 1 && files[0].isFile()) {
fileSize = files[0].getSize();
}
Log.i(TAG, "File size = " + fileSize);
return fileSize;
}
You can just skip the download to local filesystem part and do:
FTPClient ftpClient = new FTPClient();
try {
ftpClient.connect(server, port);
ftpClient.login(user, pass);
ftpClient.enterLocalPassiveMode();
ftpClient.setFileType(FTP.BINARY_FILE_TYPE);
InputStream inputStream = ftpClient.retrieveFileStream("/folder/file.dat");
BufferedReader reader = new BufferedReader(new InputStreamReader(inputStream, "Cp1252"));
while(reader.ready()) {
System.out.println(reader.readLine()); // Or whatever
}
inputStream.close();
} catch (IOException ex) {
ex.printStackTrace();
} finally {
try {
if (ftpClient.isConnected()) {
ftpClient.logout();
ftpClient.disconnect();
}
} catch (IOException ex) {
ex.printStackTrace();
}
}

Can't execute custom logic in finally block in try-with-resource block

Java 8
Here classic try-catch block.
FileOutputStream out = null;
try {
out = new FileOutputStream(file);
byte[] bytes = new byte[1024];
int read = 0;
int totalRead = 0;
while ((read = iStream.read(bytes)) > 0) {
// some code here
}
return totalRead;
} catch (Exception e) {
throw new IOException(fileName + " failed, got: " + e.toString(), e);
} finally {
if (out != null) {
out.getFD().sync();
out.close();
}
}
As you can see I do some custom logic in the finally block
out.getFD().sync();
Nice. It's work fine.
Now I want to replace it by try-with-resources block. I try this
try (FileOutputStream out = new FileOutputStream(file)) {
byte[] bytes = new byte[1024];
int read = 0;
int totalRead = 0;
while ((read = iStream.read(bytes)) > 0) {
// som ecode here
}
return totalRead;
} catch (Exception e) {
throw new IOException(fileName + " failed, got: " + e.toString(), e);
} finally {
if (out != null) {
out.getFD().sync();
out.close();
}
}
but get compile error in finally block:
cannot find symbol
symbol: variable out
The whole point of try-with-resources is that you do not need to call close() as the compiler ensures that it has been called. Since this happens before the finally block is executed, you can’t perform other actions on the resource in finally, like the sync call.
You can easily verify this
try(Closeable c = () -> System.out.println("close")) {
throw new IOException("stop here");
}
finally {
System.out.println("In finally block");
}
will print
close
In finally block
Exception in thread "main" java.io.IOException: stop here
If you really need to perform a sync operation at the end (in most cases: you don’t), you still don’t have to do it manually
try(OutputStream out = Files.newOutputStream(file.toPath(), StandardOpenOption.SYNC,
StandardOpenOption.CREATE, StandardOpenOption.TRUNCATE_EXISTING)) {
byte[] bytes = new byte[1024];
int read = 0;
int totalRead = 0;
while ((read = iStream.read(bytes)) > 0) {
// some code here
}
return totalRead;
}
I hope, your “some code” is not just a plain copying which you could simply do with Files.copy(Path, Path, …) or Files.copy(InputStream, Path, …).
You should also consider using long for totalRead…

Twitter ping inside proxy failed but when open from browser it open

I have a problem: when I open twitter.com, it opens, but when use Tweetinvi it doesn’t work.
Therefore, I made this code:
var result = ping.Send("twitter.com");
if (result.Status != System.Net.NetworkInformation.IPStatus.Success)
{
insertlogwithFilename("test ping : 000X" );
}
I setup proxy configuration, but the ping does not work.
TweetinviConfig.CurrentThreadSettings.HttpRequestTimeout = 5000000;
TweetinviConfig.CurrentThreadSettings.UploadTimeout = 9000000;
if (noproxy == "0")
{
TweetinviConfig.CurrentThreadSettings.ProxyURL = "http://" + proxyIP + ":" + proxyPort;
}
try
{
Auth.SetUserCredentials(cuskey, secret, accesstoken, useraccessse);
}
catch (Exception exp)
{
insertlogwithFilename("error in authentication :" + exp.Message);
}
try
{
var authenticatedUser = User.GetAuthenticatedUser();
}
catch (Exception exp)
{
insertlogwithFilename("error in user authentication :" + exp.Message);
}
I test if connection to twitter is connected :
public static void testconn()
{
try
{
using (var client = new WebClient())
{
using (var stream = client.OpenRead("https://www.twitter.com"))
{
insertlogwithFilename("test stream : 8666");
}
}
}
catch
{
insertlogwithFilename("test stream : 8766");
}
}
this block of code return true
public static void testconnping()
{
var ping = new System.Net.NetworkInformation.Ping();
var result = ping.Send("twitter.com");
if (result.Status != System.Net.NetworkInformation.IPStatus.Success)
{
insertlogwithFilename("test ping : 8766" );
//return false;
}
else
{
insertlogwithFilename("test ping : 8666");
//return true;
}
}
this block return false
When you set up TweetinviConfig.CurrentThreadSettings.ProxyURL it does not mean that ping.Send will use this proxy. It means that Tweetinvi will use this proxy.
If you want to check if Tweetinvi is actually accessing the data, you will need to run the GetAuthenticatedUser method as explained in the documentation.
TweetinviConfig.CurrentThreadSettings.ProxyURL = "http://...";
ExceptionHandler.SwallowWebExceptions = false;
Auth.SetUserCredentials("CONSUMER_KEY", "CONSUMER_SECRET", "ACCESS_TOKEN", "ACCESS_TOKEN_SECRET");
var authenticatedUser = User.GetAuthenticatedUser();

Transferring assets : Error code 4005 ASSET_UNAVAILABLE

This is driving me crazy. I wrote a code quite a while ago that was working, and opened it again and it happens that I am not able to transfer my assets from the mobile to the wearable device.
public Bitmap loadBitmapFromAsset(Asset asset) {
if (asset == null) {
throw new IllegalArgumentException("Asset must be non-null");
}
// convert asset into a file descriptor and block until it's ready
Log.d(TAG, "api client" + mApiClient);
DataApi.GetFdForAssetResult result = Wearable.DataApi.getFdForAsset(mApiClient, asset).await();
if (result == null) {
Log.w(TAG, "getFdForAsset returned null");
return null;
}
if (result.getStatus().isSuccess()) {
Log.d(TAG, "success");
} else {
Log.d(TAG, result.getStatus().getStatusCode() + ":" + result.getStatus().getStatusMessage());
}
InputStream assetInputStream = result.getInputStream();
if (assetInputStream == null) {
Log.w(TAG, "Requested an unknown Asset.");
return null;
}
// decode the stream into a bitmap
return BitmapFactory.decodeStream(assetInputStream);
}
And this is the code from which I call the loadBitmapFrom Asset method.
DataMap dataMap = DataMapItem.fromDataItem(event.getDataItem()).getDataMap();
ArrayList<DataMap> dataMaps = dataMap.getDataMapArrayList("dataMaps");
ArrayList<String> names = new ArrayList<>();
ArrayList<String> permalinks = new ArrayList<>();
ArrayList<Asset> images = new ArrayList<>();
for (int i = 0 ; i < dataMaps.size() ; i++) {
Log.d(TAG, dataMaps.get(i).getString("name"));
names.add(dataMaps.get(i).getString("name"));
permalinks.add(dataMaps.get(i).getString("permalink"));
images.add(dataMaps.get(i).getAsset("image"));
}
editor.putInt("my_selection_size", names.size());
for (int i=0; i <names.size() ; i++) {
editor.putString("my_selection_name_" + i, names.get(i));
editor.putString("my_selection_permalink_" + i, permalinks.get(i));
Log.d(TAG, "asset number " + i + " " + images.get(i));
Bitmap bitmap = loadBitmapFromAsset(images.get(i));
ByteArrayOutputStream stream = new ByteArrayOutputStream();
bitmap.compress(Bitmap.CompressFormat.PNG, 100, stream);
byte[] byteArray = stream.toByteArray();
String encoded = Base64.encodeToString(byteArray, Base64.DEFAULT);
editor.putString("my_selection_image_" + i, encoded);
}
And on the mobile side :
private void sendData(PutDataMapRequest dataMap) {
PutDataRequest request = dataMap.asPutDataRequest();
request.setUrgent();
com.google.android.gms.common.api.PendingResult<DataApi.DataItemResult> pendingResult = Wearable.DataApi.putDataItem(mApiClient, request);
pendingResult.setResultCallback(new ResultCallback<DataApi.DataItemResult>() {
#Override
public void onResult(DataApi.DataItemResult dataItemResult) {
com.orange.radio.horizon.tools.Log.d(TAG, "api client : " + mApiClient);
if (dataItemResult.getStatus().isSuccess()) {
com.orange.radio.horizon.tools.Log.d(TAG, "message successfully sent");
} else if (dataItemResult.getStatus().isInterrupted()) {
com.orange.radio.horizon.tools.Log.e(TAG, "couldn't send data to watch (interrupted)");
} else if (dataItemResult.getStatus().isCanceled()) {
com.orange.radio.horizon.tools.Log.e(TAG, "couldn't send data to watch (canceled)");
}
}
});
Log.d(TAG, "Sending data to android wear");
}
class ConfigTask extends AsyncTask<String, Void, String> {
ArrayList<WatchData> mitems;
int mType;
public ConfigTask(ArrayList<WatchData> items, int type)
{
mitems = items;
mType = type;
}
protected String doInBackground(String... str)
{
DataMap dataMap;
ArrayList<DataMap> dataMaps = new ArrayList<>();
Bitmap bitmap = null;
for (int i = 0 ; i < mitems.size() ; i++) {
dataMap = new DataMap();
URL url = null;
try {
url = new URL(mitems.get(i).mUrlSmallLogo);
Log.d(TAG, "url : " + url);
} catch (MalformedURLException e) {
e.printStackTrace();
}
try {
bitmap = BitmapFactory.decodeStream(url.openConnection().getInputStream());
} catch (IOException e) {
e.printStackTrace();
}
Asset asset = createAssetFromBitmap(bitmap);
dataMap.putAsset("image", asset);
dataMap.putString("name", mitems.get(i).mName);
dataMap.putString("permalink", mitems.get(i).mPermalink);
dataMaps.add(dataMap);
}
PutDataMapRequest request = null;
switch (mType) {
case 0 :
request = PutDataMapRequest.create(SELECTION_PATH);
break;
case 1 :
request = PutDataMapRequest.create(RADIOS_PATH);
break;
case 2 :
request = PutDataMapRequest.create(PODCASTS_PATH);
break;
}
request.getDataMap().putDataMapArrayList("dataMaps", dataMaps);
request.getDataMap().putString("", "" + System.currentTimeMillis()); //random data to refresh
Log.d(TAG, "last bitmap : " + bitmap);
Log.d(TAG, "===============================SENDING THE DATAMAP ARRAYLIST==================================");
sendData(request);
return "h";
}
protected void onPostExecute(String name)
{
}
}
When executing that code, I see the following error happening :
02-02 14:47:59.586 7585-7601/? D/WearMessageListenerService﹕ 4005:ASSET_UNAVAILABLE
I saw that related thread Why does Wearable.DataApi.getFdForAsset produce a result with status 4005 (Asset Unavailable)? but it didn't really help me
I recently had the same problem... I solved it by updating the Google play service, and adding the same signing configuration to both the app and the wearable module. If it doesn't work on the first build go to "invalidate caches / restart" in files and it should work.

Android Asynctask return problems

I am facing a problem in value 'return' in Asynctask class in doInBackground method. I am getting an error, about 'missing return statement in below code.
`public class ForecastNetwork extends AsyncTask {
public final String TAG = ForecastNetwork.class.getSimpleName();
#Override
protected Void doInBackground(Void... params) {
HttpURLConnection urlConnection = null;
BufferedReader reader = null;
// Will contain the raw JSON response as a string.
String forecastJsonStr = null;
try {
// Construct the URL for the OpenWeatherMap query
// Possible parameters are avaiable at OWM's forecast API page, at
// http://openweathermap.org/API#forecast
URL url = new URL("http://api.openweathermap.org/data/2.5/forecast/daily?q=94043&mode=json&units=metric&cnt=7");
// Create the request to OpenWeatherMap, and open the connection
urlConnection = (HttpURLConnection) url.openConnection();
urlConnection.setRequestMethod("GET");
urlConnection.connect();
// Read the input stream into a String
InputStream inputStream = urlConnection.getInputStream();
StringBuffer buffer = new StringBuffer();
if (inputStream == null) {
// Nothing to do.
return null;
}
reader = new BufferedReader(new InputStreamReader(inputStream));
String line;
while ((line = reader.readLine()) != null) {
// Since it's JSON, adding a newline isn't necessary (it won't affect parsing)
// But it does make debugging a *lot* easier if you print out the completed
// buffer for debugging.
buffer.append(line + "\n");
}
if (buffer.length() == 0) {
// Stream was empty. No point in parsing.
return null;
}
forecastJsonStr = buffer.toString();
} catch (IOException e) {
Log.e(TAG, "Error ", e);
// If the code didn't successfully get the weather data, there's no point in attemping
// to parse it.
return null;
} finally {
if (urlConnection != null) {
urlConnection.disconnect();
}
if (reader != null) {
try {
reader.close();
} catch (final IOException e) {
Log.e(TAG, "Error closing stream", e);
}
}
}
}`
What Should I return at the end?
I assume that you forgot to return the processing result
forecastJsonStr = buffer.toString();
return forecastJsonStr;

Resources