I am developing an app for Google glass using using a Immersion Pattern.
I am using start activity to switch between different tiles using below code.
Intent showImageDetails = new Intent(MainActivity.this, CapturedImageActivity.class);
showImageDetails.putExtra("IMAGE_DATA", data);
startActivity(showImageDetails);
data variable holds byte array for captured image.
Few time device is not able to start the activity and it exits the application and goes back to OK Glass tile.
Have anyone observed this issue?
I have used charades as an example which comes with API example.
Based on your comment, my wild guess is your image is too big to be sent with intent. Have you noticed the JAVA BINDER FAILURE error in the log or TransactionTooLargeException:
The Binder transaction buffer has a limited fixed size, currently 1Mb, which is shared by all transactions in progress for the process. Consequently this exception can be thrown when there are many transactions in progress even when most of the individual transactions are of moderate size.
Also see Passing data of a non-primitive type between activities in android:
What you do not want to do is pass big stuff via extras. For example, if you are creating an application that grabs pictures off the camera, you do not want to pass those in extras -- use a static data member (icky as that sounds). Intents are designed to work cross-process, which means there is some amount of data copying that goes on, which you want to avoid when it is not necessary for big stuff.
I think if your image is large, it is better to pass the URI or ResourceID of the image but not the image itself. Hope this helps.
Related
Suppose we have a list of complex objects (primitives and other objects inside) requested from a server to show them inside a RecycleView. In adapter we need only some data from each object, let's say 70%.
I get from server list with full data objects, and each object implements Parcelable so when I select a item I pass object via intent to MyDetailsActivity like so:
Intent intent = new Intent(context, MyDetailsActivity.class);
intent.putExtra("foo", myComplexObject);
startActivity(intent);
This is working as expected but on some low memory devices I get out of memory errors. So my question is how to achieve this type of data flow?
One possible solution is to implement get/set for MyObj in Applicattion class, and pass it like so but I'n not sure if it's stable.
And of course I can pass just an id from MyObject and do another request call inside DetailsActivity's onCreate(), but this requires user to wait some more seconds to load data.
Any advices or references are apreciated
As you have experienced, sending data through the bundle/intent extras has its memory limits.
Your options are to either keep those objects in memory and access them via some static/singleton instance or to do the data query from your server in the desired activity that will show them in your list.
Another viable options is to store the data in a database for ex and read it once its required but this ofcourse depends on your current architecture... you can checkout Realm, Room, GreenDao database options etc...
Second approach is more suitable for mobile applications since you only load data in list via API which is visible inside the recycler view, you can pass that data to activity and then in activity load the remaining data from another call for that specific item.
I'm assuming that each object of the data coming from the server is not of same size, leading to out of memory on some but not all the objects. So the better approach is to also modify server apt (if possible) to send only info which is required for the list in your call's response and have separate resource url to access full information for that object.
This may result in a minimal delay but it will not cause unexpected out of memory errors which is a big let down for the end user.
You can actually use Application class for this purpose, to make it even better
Set the data in Application class when you intend to pass
Retrieve the data at destination into Local variable from Application
After retrieving data into local variable, set object in Application to null
Using above approach will make sure your objects memory is released as soon you consumed it without holding it all the time throughout Application Lifecycle
I know how to do this converting it to a bitmap, but I want an Image (android.media) on the receiver side.
Thanks in advance.
If you want to pass only one bitmap at a time, I suggest creating a static variable in a class. and assign the bitmap object to it, and use it in the receiver class.
But if this is very big bitmap, it may cause OutOfMemory issue.
You probably don't want to do this. Even if you create a Serializable or Parcelable object that includes your data like this:
http://www.javacodegeeks.com/2014/01/android-tutorial-two-methods-of-passing-object-by-intent-serializableparcelable.html
which you may be able to do, by creatively encoding your image.
But an Intent has a limitation in size. See this post here:
Maximum length of Intent putExtra method? (Force close)
It says 1MB, but in my experience it might be as high as 4MB, depending on the platform (I may have that wrong, I don't have a specific reference to Android documentation to support it, but I see errors that appear to support it).
I'm sure you can move a lot of images within this restriction, but for any that fall outside of it, you will need a "work around" - which you should then probably make the "standard" and avoid the issue altogether.
I m actually facing a problem with the intent extras size. In fact I need to get a nested object containing ~2000 objects.
So, when trying to transmit this intent, I got errors telling me that the size of the object is too big.
My question is : what is the best way to manage it, without using the ugly method, corresponding to store every object in a class using the static way.
What is the best way to transmit big informations between activities.
Thanks for advance
I will start this by saying that on iOS this algorithm takes, on average, <2 seconds to complete and given a simpler, more specific input that is the same between how I test it on iOS vs. Android it takes 0.09 seconds and 2.5 seconds respectively, and the Android version simply quits on me, no idea if that would be significantly longer. (The test data gives the sorting algorithm a relatively simple task)
More specifically, I have a HashMap (Using an NSMutableDictionary on iOS) that maps a unique key(Its a string of only integers called its course. For example: "12345") used to get specific sections under a course title. The hash map knows what course a specific section falls under because each section has a value "Course". Once they are retrieved these section objects are compared, to see if they can fit into a schedule together based on user input and their "timeBegin", "timeEnd", and "days" values.
For Example: If I asked for schedules with only the Course ABC1234(There are 50 different time slots or "sections" under that course title) and DEF5678(50 sections) it will iterate through the Hashmap to find every section that falls under those two courses. Then it will sort them into schedules of two classes each(one ABC1234 and one DEF5678) If no two courses have a conflict then a total of 2500(50*50) schedules are possible.
These "schedules" (Stored in ArrayLists since the number of user inputs varies from 1-8 and possible number of results varies from 1-100,000. The group of all schedules is a double ArrayList that looks like this ArrayList>. On iOS I use NSMutableArray) are then fed into the intent that is the next Activity. This Activity (Fragment techincally?) will be a pager that allows the user to scroll through the different combinations.
I copied the method of search and sort exactly as it is in iOS(This may not be the right thing to do since the languages and data structures may be fundamentally different) and it works correctly with small output but when it gets too large it can't handle it.
So is multithreading the answer? Should I use something other than a HashMap? Something other than ArrayLists? I only assume multithreading because the errors indicate that too much is being done on the main thread. I've also read that there is a limit to the size of data passed using Intents but I have no idea.
If I was unclear on anything feel free to ask for clarification. Also, I've been doing Android for ~2 weeks so I may completely off track but hopefully not, this is a fully functional and complete app in the iTunes Store already so I don't think I'm that far off. Thanks!
1) I think you should go with AsynTask of Android .The way it handle the View into `UI
threadandBackground threadfor operations (Like Sorting` ) is sufficient enough to help
you to get the Data Processed into Background thread And on Processing you can get the
Content on UI Thread.
Follow This ShorHand Example for This:
Example to Use Asyntask
2) Example(How to Proceed):
a) define your view into onPreExecute()
b) Do your Background Operation into doInBackground()
c) Get the Result into onPostExceute() and call the content for New Activty
Hope this could help...
I think it's better for you to use TreeMap instead of HashMap, which sorts data automatically everytime you mutate it. Therefore you won't have to sort your data before start another activity, you just pass it and that's all.
Also for using it you have to implement Comparable interface in your class which represents value of Map.
You can also read about TreeMap class there:
http://docs.oracle.com/javase/7/docs/api/java/util/TreeMap.html
I am working on an Android app, where media(audio/video/images) could be stored either internally/externally. I would be facing the following scenarios
Case I
Setting dynamically images from the random value broadcasted by the app.
Right now, I am managing it as
if(rowData.strName.equals("football")){
imageView.setImageResource(R.drawable.football);
}else if(rowData.strName.equals("chess")){
imageView.setImageResource(R.drawable.chess);
Problem As of now, I am having few records so managing else if loop in not big headache, but later it could turn out to be one.
Case II
Downloading a media from internet, saving it in external storage and loading it on an imageview as an when required
Problem Incase, the image has already been downloaded(app keeps track of downloaded image), the user ejects the card, then I plan to use
try{
}catch(FileNotFoundException e){
imageView.setImageResource(R.drawable.no_media);//media from the app
}
Case III
I will be having a listView of a category.Each Category contains certain sub-category names,their images(inbuilt & to be downloaded externally) & their description.Each sub-category has sub records with each record having its own one or image(inbuilt & to be downloaded externally),description and media files(both audio and video).
I am confused on what Collection class shall I use for this case and how to begin with? For data that is to be retrieved from the server(online), I plan to use XMLParsing. Please suggest me the best way to achieve the problem.
Wow! This is really three questions. If only I could get three times the rep :)
Case I
Use a Map to store and retrieve stuff. Saves you writing lots of if/else statements.
Map<String,Integer> drawableMap = new HashMap<String,Integer>();
drawableMap.put("football", R.drawable.football);
// Then later to retrieve...
imageView.setImageResource(drawableMap.get("football"));
Case II
OK, this seems fine. Though for most of my image loading I use existing libraries like Universal Image Loader or Volley. These may do what you need, I'm not sure.
Case III
I would take an OO approach and model the data appropriately. You don't have to choose "a" Collection class to use. Create a Category class. Create a SubCategory class. Have the Category class "have" SubCategories, etc. Take it from there.
XML parsing is fine, I'm not sure what you're expecting to be suggested. You may also like to consider JSON, a popular data format.