I have a big problem with parsing some json data which I get as response from a web server. The thing that I'm doing is I get the response via POST and than convert the response as string and parse it. But in some devices I get OutOfMemoryError , which I'm trying to fix. Here is how I'm converting the response to string :
public static String convertStreamToString(InputStream is) throws Exception {
ByteArrayOutputStream into = new ByteArrayOutputStream();
byte[] buf = new byte[4096];
for (int n; 0 < (n = is.read(buf));) {
into.write(buf, 0, n);
}
into.close();
return new String(into.toByteArray(), "UTF-8");
}
and here is how I'm using this piece of code :
InputStream response = new BufferedInputStream(connection.getInputStream());
try {
String responsee = convertStreamToString(response);
jsonParser(responsee);
} catch (Exception e) {
e.printStackTrace();
cancelDialog("Error occurred! Please try again later.");
}
Any suggestions how can I fix that problem so don't happen in all devices?
Thanks in advance for any kind of help or advices.
The mobile has limited internal memory.
I have also face same issue. The solution that we found is that download only the necessary information. So you please confirm your requirement how much data you want to inside the mobile. If you filter the unnecessary data then the problem will get resolved.
Before testing the program on extreme condition first check whether simple download happening if it is happening then check the limit of your data means up to how extent it will not give out of memory error. and accordingly that rework your requirement.
Related
Whenever i am trying to encode or decode a string using UTF - 8 it is showing me Unhandled Exception: UnsupportedEncodingException.
So Android Studio is giving me two solution, which are
1) Use throws UnsupportedEncodingException
2) put that piece of code between try catch with UnsupportedEncodingException as catch argument..
So which one is good practice to use and why ?
public static String getEncodedString(String strOriginal) throws UnsupportedEncodingException {
byte[] dataFirstName = strOriginal.getBytes("UTF-8");
return Base64.encodeToString(dataFirstName, Base64.DEFAULT);
}
OR
public static String getEncodedString(String strOriginal) {
byte[] dataFirstName = new byte[0];
try {
dataFirstName = strOriginal.getBytes("UTF-8");
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
}
return Base64.encodeToString(dataFirstName, Base64.DEFAULT);
}
I would go for the second snippet, UTF-8 is one of the standard character encodings supported by every platform so the exception can actually never happen. It does not make sense to propagate it further.
If you are developing for API 19 or later, you can also use
strOriginal.getBytes(StandardCharsets.UTF_8)
which does not throw an exception.
I've written a simple app the uses the Android Wear Messaging API. I followed a number of guides that all use a similar style of code for sending the message with some data which should be in byte[] form.
The code sending the message is
Wearable.MessageApi.sendMessage(client, nodeId, message, "test".getBytes());
and the receiving code is
final String messageData = new String(messageEvent.getData());
This seems to fit with a number of different guides and some of the official documentation - however the variable messageData ends up containing [B#4b0ad22 rather than test which is the data that was sent.
I've also tried explicit encoding/decoding with
String messageData = new String(messageEvent.getData(), "UTF-8");
but that throws a java.io.UnsupportedEncodingException
What's going wrong with the encoding or decoding?
You have to define the encoding/decoding but also wrap it in a try/catch block so the receiving code looks like this,
String messageData = "";
try {
messageData = new String(messageEvent.getData(), "UTF-8");
}
catch(Exception e)
{
Log.e("DecodingError", e.toString());
}
The sending code looks like this;
try {
Wearable.MessageApi.sendMessage(client, nodeId, message, "test".getBytes("UTF-8"));
}
catch(Exception e)
{
Log.e("EncodingError", e.toString());
}
Previously I've asked some questions regarding what method I should use to save some data from my app to retrieve at a later time after it's been closed/stopped. I got the answers I was looking for, I think. But since then, my efforts to implement such a feature has fallen way short. I've researched various questions I've had, for which I thought I found answers. But it seems that the answers, while maybe correct, are not a match necessarily for each other. What I mean, is they might work separately, but coming from various sources, they don't work together as a whole, and for me they don't work at all. I'm led to believe I want to use SharedPreferences. That may or may not be the case, but that has been the direction of my efforts lately.
So I'll ask this multi-part question.
How would you go about saving an array of integers(or boolean values)?
Before loading that saved array, how would I check if it exists?
How would I load the array to use its values again?
Those are the basis of my issues right now. Even at this point, as frustrated as I may be, I don't mind doing more research if someone can point me in the right direction, but everywhere I've looked seems to be missing information and I'm unable to really understand/see how to code what I want to do.
If you REALLY want to see some code, I can show you all my broken pieces at the moment (what I haven't deleted), but I don't see it doing you any good. That said, I'll answer any questions you may need to help me out.
Thanks in advance.
EDIT: The array will change very little from app version to version. It should be about 500-2000 integers or boolean values (either/or will work the same for me). The array is basically a set of flags that tells the app to do one thing or another depending on the value. The size will only change if I add or remove items between versions. For this reason, after checking if the file/array exists, I'll compare the saved array with one in the app and act accordingly.
I've had similar issues with data that has to be preserved through a reboot. I found two ways to do it.
1) Data is seldom accessed.
Store data in .../files in some format that can be easily saved/retrieved. I used JSONArrays to hold the data. mContext.getFilesDir() will get you the path, and you can simply see if your file.exists() to determine if the data exists.
You will need to create an object that will:
1) convert your data to the stored format
for(int i = 0; i < mArray.size(); i++ )
{
JSONObject jo = new JSONObject();
jo.put("THINGY", mArray[i]);
ja.put(jo);
}
2) retrieve your data from the store
String js = readFromFile(fileName);
if( !js.isEmpty() )
ja = new JSONArray( js );
for( int i = 0; i < ja.length(); i++
{
// CONVERT THIS ARRAY TO YOUR INT...
}
3) read/write files like this:
private void writeToFile(String fileName, String data)
{
try
{
FileOutputStream fOut = openFileOutput( fileName, MODE_PRIVATE );
OutputStreamWriter osw = new OutputStreamWriter(fOut);
// Log.d(TAG, "Writing output log...");
osw.write(data);
osw.flush();
osw.close();
}
catch( Exception e )
{
Log.e(TAG, "Cannot create " + fileName );
}
}
private String readFromFile(String fileName)
{
String ret = "";
try
{
InputStream inputStream = openFileInput(fileName);
if ( inputStream != null )
{
InputStreamReader inputStreamReader = new InputStreamReader(inputStream);
BufferedReader bufferedReader = new BufferedReader(inputStreamReader);
String receiveString = "";
StringBuilder stringBuilder = new StringBuilder();
while ( (receiveString = bufferedReader.readLine()) != null )
{
stringBuilder.append(receiveString);
}
inputStream.close();
ret = stringBuilder.toString();
}
}
catch (FileNotFoundException e)
{
Log.e(TAG, "File not found: " + e.toString());
}
catch (IOException e)
{
Log.e(TAG, "Can not read file: " + e.toString());
}
return ret;
}
JSON works well in this case because there are easy methods to convert to/from strings.
2) Frequent Access
I used SQLiteDatabase. I use a Singlton and DBHelper.getInstance() to get access to it. This seems like overkill, but it is a good solution if the amount of data you are saving is increasing beyond a simple array of Integers.
A really basic (but sound) place to start is: http://www.vogella.com/tutorials/AndroidSQLite/article.html. Note his page was written for 4.3.
HTH.
there is a image gallery app which download images online. I want to know what will happen if phone memory/SD card get full; If an error will appear then what should I do?
This catches an OutofMemory error, but should check for other exceptions, too
URL aURL = null;
Bitmap bm = null;
try {
final String imageUrl = CMSServer + url;
aURL = new URL(imageUrl);
URLConnection conn = aURL.openConnection();
InputStream is = new BufferedInputStream(conn.getInputStream());
is = new BufferedInputStream(conn.getInputStream());
bm = BitmapFactory.decodeStream(is, null, options);
is.close();
} catch (OutOfMemory oom) {
// do something
}
}
return bm;
}
The analogy can be made what if a class cannot adjust more students ?
So according to me :-
1. you can follow "Precaution is better than cure"
first of all you will check the sdcard itself and if its say >1MB then you will get the image.
Even if the error comes you can prompt user to delete older images to allow new images like we used to have older phones where msg memory was limited and it will ask to remove older messages to allow new messages.
Still if you get the error then perhaps i cannot exactly figure out what to do except showing the "Out of memory exception" to user.
Thanks and hope it helps.... :)
It will through IOException if no memory is left in sdcard. But if you know the size of file which you are downloading then you can check for sufficient memory and thus can avoid IOException.
Edit: Catch Exception
try
{
//your code here
}
catch(IOException ex)
{
//do stuff when exception caused.
}
if you don't know how to use/catch exception. Please google it.
I started developing an android app that have to interact with MMS attachements, in particular, get attachements such as text, bitmaps, audio, video etc. and store them on the phone in a specific folder.
So i started reading some books and some post on the web but it isn't a very common argument, and i didn't find an official way to do what i want to do.
I found a fairly good article here on stack-overflow here: How to Read MMS Data in Android?... it works very well for me, but there are 2 problems:
The article shows you how to get MMS data by querying over the "hidden" SMS-MMS content provider, and as far as i know, Google doesn't guarantee that they'll keep the current structure in every android's future relase.
The article only explains how to get Text data and Bitmap data from MMS...what about video/audio? I tried to get a video/audio stream from an InputStream such as the example did with Bitmaps, unfortunately with no luck...
I'm very disappointed about the absence of official tutorial or "How-To" over this argument because SMS and MMS management is a very common need in mobile developement.
I hope someone can help me....
Thanks in advance!!
I found a fairly simple way to read Video/Audio data from MMS, so i decided to publish this part of my class that provides MMS attachements, for all users that need this.
private static final int RAW_DATA_BLOCK_SIZE = 16384; //Set the block size used to write a ByteArrayOutputStream to byte[]
public static final int ERROR_IO_EXCEPTION = 1;
public static final int ERROR_FILE_NOT_FOUND = 2;
public static byte[] LoadRaw(Context context, Uri uri, int Error){
InputStream inputStream = null;
byte[] ret = new byte[0];
//Open inputStream from the specified URI
try {
inputStream = context.getContentResolver().openInputStream(uri);
//Try read from the InputStream
if(inputStream!=null)
ret = InputStreamToByteArray(inputStream);
}
catch (FileNotFoundException e1) {
Error = ERROR_FILE_NOT_FOUND;
}
catch (IOException e) {
Error = ERROR_IO_EXCEPTION;
}
finally{
if (inputStream != null) {
try {
inputStream.close();
}
catch (IOException e) {
//Problem on closing stream.
//The return state does not change.
Error = ERROR_IO_EXCEPTION;
}
}
}
//Return
return ret;
}
//Create a byte array from an open inputStream. Read blocks of RAW_DATA_BLOCK_SIZE byte
private static byte[] InputStreamToByteArray(InputStream inputStream) throws IOException{
ByteArrayOutputStream buffer = new ByteArrayOutputStream();
int nRead;
byte[] data = new byte[RAW_DATA_BLOCK_SIZE];
while ((nRead = inputStream.read(data, 0, data.length)) != -1) {
buffer.write(data, 0, nRead);
}
buffer.flush();
return buffer.toByteArray();
}
In this way you can extract "Raw" data such as Audio/Video/Images from MMS by passing:
the context where you need to use this function
the URI of the MMS part that contains data you want to extract (for ex. "content://mms/part/2")
the byref param that returns an eventual error code thrown by the procedure.
Once you have your byte[], you can create an empty File and then use a FileOutputStream to write the byte[] into it. If the file path\extension is correct and if your app has all the right
permissions, you'll be able to store your data.
PS. This procedure has been tested a few times and it worked, but i don't exclude can be some unmanaged exception cases that may produce error states. IMHO it can be improoved too...