I have the next problem, I'm creating a list view a custom adapter, I am downloading the data for the adapter from a JSON url (text and image urls) using an async task, then I set the adapter to the list, I download the images using picasso library, now my app works fine, it doesn't crashes but when I start another activity i get this:
E/JavaBinder﹕ !!! FAILED BINDER TRANSACTION !!!
I get the error even if the new activity is empty, I'm using a moto G. I have analyzed the heap with DDMS and Eclipse MAT and I haven't find if my code is causing memory leaks. Changing from one activity to another multiple times I get this in the logcat:
09-04 10:37:54.827 30603-30603/mx.f403.whimlike E/JavaBinder﹕ !!! FAILED BINDER TRANSACTION !!!
09-04 10:38:01.793 30603-30603/mx.f403.whimlike D/dalvikvm﹕ GC_FOR_ALLOC freed 1178K, 24% free 13642K/17876K, paused 21ms, total 21ms
09-04 10:38:02.939 30603-30603/mx.f403.whimlike E/JavaBinder﹕ !!! FAILED BINDER TRANSACTION !!!
09-04 10:38:07.235 30603-30603/mx.f403.whimlike D/dalvikvm﹕ GC_FOR_ALLOC freed 1008K, 24% free 13657K/17876K, paused 20ms, total 20ms
09-04 10:38:14.484 30603-30603/mx.f403.whimlike E/JavaBinder﹕ !!! FAILED BINDER TRANSACTION !!!
09-04 10:38:15.497 30603-30603/mx.f403.whimlike D/dalvikvm﹕ GC_FOR_ALLOC freed 1065K, 24% free 13656K/17876K, paused 18ms, total 18ms
09-04 10:38:16.371 30603-30603/mx.f403.whimlike E/JavaBinder﹕ !!! FAILED BINDER TRANSACTION !!!
09-04 10:38:16.688 30603-30603/mx.f403.whimlike D/dalvikvm﹕ GC_FOR_ALLOC freed 1007K, 24% free 13628K/17876K, paused 19ms, total 19ms
09-04 10:38:17.491 30603-30603/mx.f403.whimlike E/JavaBinder﹕ !!! FAILED BINDER TRANSACTION !!!
09-04 10:38:17.781 30603-30603/mx.f403.whimlike D/dalvikvm﹕ GC_FOR_ALLOC freed 1020K, 24% free 13653K/17876K, paused 27ms, total 27ms
As you can see the memory heap doesn't increase, but I get the error the same way.
I don't think the problem is in the bitmaps I'm downloading for the first activity because I commented all the lines of code where the bitmaps are involved, I also commented the asynctasks and the problem continues arising, anyway I'm going to let the adapter here:
class ClientListAdapter extends BaseAdapter {
private Context context;
private ClientList clients;
private ClientList arrayList;
public ClientListAdapter(Context context, ClientList clients) {
this.context = context;
this.clients = clients;
this.arrayList = new ClientList();
this.arrayList.addAll(clients);
}
@Override
public View getView(int position, View convertView, ViewGroup parent) {
Client client = clients.get(position);
ClientHolder clientHolder = new ClientHolder();
if(convertView == null){
LayoutInflater inflater = ((Activity)context).getLayoutInflater();
convertView = inflater.inflate(R.layout.client_list_item,parent,false);
clientHolder.clientName = (TextView) convertView.findViewById(R.id.client_name);
clientHolder.clientImage = (ImageView) convertView.findViewById(R.id.client_image);
convertView.setTag(clientHolder);
}
else{
clientHolder = (ClientHolder) convertView.getTag();
}
if (client != null) {
clientHolder.clientImage.setImageResource(R.drawable.ic_launcher);
Picasso.with(context).load(client.getClientImageUrl()).into(clientHolder.clientImage);
clientHolder.clientName.setText(client.getName());
}
return convertView;
}
static class ClientHolder{
TextView clientName;
ImageView clientImage;
}
I downloaded the Eclipse MAT and it shows the leak possible causes, but I don't understand very well what that means, this is the result of the Eclipse MAT:
**Problem Suspect 1**
The class "android.content.res.Resources", loaded by "<system class loader>", occupies 2,968,072 (14.65%) bytes. The memory is accumulated in one instance of "android.util.LongSparseArray[]" loaded by "<system class loader>".
Keywords
android.util.LongSparseArray[]
android.content.res.Resources
**Problem Suspect 2**
16 instances of "byte[]", loaded by "<system class loader>" occupy 5,860,824 (28.92%) bytes.
Biggest instances:
•byte[1705600] @ 0x432a2f28 ..........................................y...x...v...v...v...u...t...t...t...t...t...t...t...t...s...s...s...s...r...r...q...q...n...n...n...n...m...m...l...l...l...l...l...l...k...k...j...j...[...[...\...[...\...Y...\...Z...[...Z...\...Z...Z...Y...Z...Z.... - 1,705,616 (8.42%) bytes.
•byte[1536000] @ 0x42715a48 ................................................................................................................................................................................................................................................................... - 1,536,016 (7.58%) bytes.
•byte[1500000] @ 0x43751fd0 ..w...x...{...|...|...{...y...x...t...v...s...t...l...h...`...^...J...H...F...F...H...J...I...H...F...F...E...D...C...A...A...@...E...E...E...E...E...E...E...E...F...F...F...E...E...D...D...D...;...;...;...;...;...;...;...;...;...9..~8...9...;...<...;...9.... - 1,500,016 (7.40%) bytes.
•byte[788544] @ 0x42ab6ab8 ................................................................................................................................................................................................................................................................... - 788,560 (3.89%) bytes.
•byte[293304] @ 0x426c7e78 ....LLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLL... - 293,320 (1.45%) bytes.
Keywords
byte[]
**Problem Suspect 3**
20 instances of "android.graphics.Bitmap", loaded by "<system class loader>" occupy 3,213,736 (15.86%) bytes.
Biggest instances:
•android.graphics.Bitmap @ 0x4227b8f0 - 1,127,584 (5.56%) bytes.
•android.graphics.Bitmap @ 0x42998158 - 640,064 (3.16%) bytes.
•android.graphics.Bitmap @ 0x42cbf0a8 - 367,296 (1.81%) bytes.
•android.graphics.Bitmap @ 0x42d21008 - 360,064 (1.78%) bytes.
•android.graphics.Bitmap @ 0x428e01f8 - 293,368 (1.45%) bytes.
Keywords
android.graphics.Bitmap
**Problem Suspect 4**
168 instances of "android.graphics.NinePatch", loaded by "<system class loader>" occupy 2,170,152 (10.71%) bytes. These instances are referenced from one instance of "java.lang.Object[]", loaded by "<system class loader>"
Keywords
java.lang.Object[]
android.graphics.NinePatch
**Hint 1**
The problem suspects 1 and 4 may be related, because the reference chains to them have a common beginning.
In some blogs I've read that you shouldn't hold references to activities, maybe could be that but I don't know in which part of my code applies and how to solve it, Here is my Main Activity and the fragment where I think the problem is:
public class MainActivity extends ActionBarActivity implements LoggedInFragment.SetUserInfoInterface{
// Constant keys for passing data between Activities
public static final String CLIENTLINK = "ClientLink";
public static final String CLIENTID = "ClientId";
public static final String DEBATEFLAG = "DebateFlag";
public static final String USERID = "UserId";
public static final String SHOW_EMAIL_ASSIGN_DIALOG_ADVICE = "Show email assign dialog advice";
// Constant id's for showing logged in and logged out fragments
private static final int LOGGED_OUT = 0;
private static final int LOGGED_IN = 1;
private static final int SETTINGS = 2;
private static final int FRAGMENT_COUNT = SETTINGS + 1;
private Fragment[] fragments = new Fragment[FRAGMENT_COUNT];
// Flag to know if a fragment is resumed
private boolean isResumed = false;
public String userId;
// Creates a UiHelper to get a call when a session changes
private UiLifecycleHelper uiHelper;
// Creates a callback that does shows a fragment depending of the state of the session, this
// callback calls the function onSessionStateChange.
private Session.StatusCallback callback =
new Session.StatusCallback() {
@Override
public void call(Session session,
SessionState state, Exception exception) {
onSessionStateChange(session, state, exception);
}
};
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// Set uiHelper to get the callback created previously
uiHelper = new UiLifecycleHelper(this, callback);
uiHelper.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
FragmentManager fm = getSupportFragmentManager();
fragments[LOGGED_OUT] = fm.findFragmentById(R.id.loggedOutFragment);
fragments[LOGGED_IN] = fm.findFragmentById(R.id.loggedInFragment);
fragments[SETTINGS] = fm.findFragmentById(R.id.customSettingsFragment);
FragmentTransaction transaction = fm.beginTransaction();
for(Fragment fragment : fragments){
transaction.hide(fragment);
}
transaction.commit();
}
public boolean isOnline() {
ConnectivityManager cm = (ConnectivityManager) getSystemService(Context.CONNECTIVITY_SERVICE);
NetworkInfo netInfo = cm.getActiveNetworkInfo();
return (netInfo != null && netInfo.isConnected());
}
private void showFragment(int fragmentIndex, boolean addToBackStack) {
FragmentManager fm = getSupportFragmentManager();
FragmentTransaction transaction = fm.beginTransaction();
for (int i = 0; i < fragments.length; i++) {
if (i == fragmentIndex) {
transaction.show(fragments[i]);
} else {
transaction.hide(fragments[i]);
}
}
if (addToBackStack) {
transaction.addToBackStack(null);
}
transaction.commit();
}
private void onSessionStateChange(Session session, SessionState state, Exception exception) {
// Only make changes if the activity is visible
if (isResumed) {
FragmentManager manager = getSupportFragmentManager();
// Get the number of entries in the back stack
int backStackSize = manager.getBackStackEntryCount();
// Clear the back stack
for (int i = 0; i < backStackSize; i++) {
manager.popBackStack();
}
if (state.isOpened()) {
// If the session state is open:
// Show the authenticated fragment
showFragment(LOGGED_IN, false);
} else if (state.isClosed()) {
// If the session state is closed:
// Show the login fragment
showFragment(LOGGED_OUT, false);
}
}
}
@Override
protected void onResumeFragments() {
super.onResumeFragments();
Session session = Session.getActiveSession();
if (session != null && session.isOpened()) {
// if the session is already open,
// try to show the LoggedInFragment
showFragment(LOGGED_IN, false);
} else {
// otherwise present the LoggedOutFragment
// and ask the person to login.
showFragment(LOGGED_OUT, false);
}
}
public void closeSession(){
Session session = Session.getActiveSession();
session.close();
}
@Override
public void onResume() {
super.onResume();
uiHelper.onResume();
isResumed = true;
}
@Override
public void onPause() {
super.onPause();
uiHelper.onPause();
isResumed = false;
}
@Override
public void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
uiHelper.onActivityResult(requestCode, resultCode, data);
}
@Override
public void onDestroy() {
super.onDestroy();
uiHelper.onDestroy();
}
public void showPromptNoInternet() {
AlertDialog.Builder builder = new AlertDialog.Builder(this);
builder.setPositiveButton(R.string.button_accept, new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
}
});
builder.setTitle(getString(R.string.no_internet_dialog_title));
builder.setMessage(getString(R.string.no_internet_dialog_message));
AlertDialog dlg = builder.create();
dlg.show();
}
public void showSortDialog(){
FragmentManager fm = getSupportFragmentManager();
final LoggedInFragment loggedInFragment = (LoggedInFragment)fm.findFragmentById(R.id.loggedInFragment);
ArrayAdapter<String> sorting_forms = new ArrayAdapter<String>(this,android.R.layout.simple_list_item_1);
sorting_forms.add(getString(R.string.sort_ascending_order));
sorting_forms.add(getString(R.string.sort_descending_order));
AlertDialog.Builder builder = new AlertDialog.Builder(this);
builder.setTitle("Ordenar")
.setAdapter(sorting_forms, new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int which) {
switch (which){
case 0:
loggedInFragment.sortClientList("ascend");
break;
case 1:
loggedInFragment.sortClientList("descend");
break;
}
}
});
AlertDialog dlg = builder.create();
dlg.show();
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu items for use in the action bar
MenuInflater inflater = getMenuInflater();
inflater.inflate(R.menu.settings, menu);
return super.onCreateOptionsMenu(menu);
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
FragmentManager fm = getSupportFragmentManager();
FragmentTransaction transaction = fm.beginTransaction();
switch(item.getItemId()) {
case R.id.settings:
transaction.show(fragments[SETTINGS]);
transaction.hide(fragments[LOGGED_IN]);
transaction.addToBackStack(null);
transaction.commit();
return true;
case R.id.action_my_coupons:
Intent i = new Intent(this, CouponListActivity.class);
i.putExtra(USERID, userId);
startActivity(i);
return true;
case R.id.view_recent_promotions:
Intent recentPromoListActivityIntent = new Intent(this, RecentPromotionListActivity.class);
recentPromoListActivityIntent.putExtra(USERID, userId);
recentPromoListActivityIntent.putExtra(MainActivity.DEBATEFLAG,false);
startActivity(recentPromoListActivityIntent);
return true;
case R.id.action_sort:
showSortDialog();
return true;
default:
super.onOptionsItemSelected(item);
}
return false;
}
@Override
public void setUserId(String userId) {
this.userId = userId;
}
}
And the fragment:
public class LoggedInFragment extends Fragment implements LoadClientsAsyncTask.ClientAsyncResponse, View.OnClickListener{
public String userId;
private ClientList clients;
private ClientListAdapter adapter;
private ListView clientList;
private UiLifecycleHelper uiHelper;
private Session.StatusCallback callback = new Session.StatusCallback() {
@Override
public void call(Session session, SessionState state, Exception exception) {
onSessionStateChange(session, state, exception);
}
};
public SetUserInfoInterface mCallback = null;
public interface SetUserInfoInterface {
public void setUserId(String userId);
}
@Override
public void onAttach(Activity activity) {
super.onAttach(activity);
// This makes sure that the container activity has implemented
// the callback interface. If not, it throws an exception
try {
mCallback = (SetUserInfoInterface) activity;
} catch (ClassCastException e) {
throw new ClassCastException(activity.toString()
+ " must implement OnHeadlineSelectedListener");
}
}
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
uiHelper = new UiLifecycleHelper(getActivity(),callback);
uiHelper.onCreate(savedInstanceState);
Session session = Session.getActiveSession();
if(session != null){
makeMeRequest(session);
}
Log.d("panda", "Logged in Creado");
}
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
final View view = (inflater.inflate(R.layout.logged_in, container, false));
LinearLayout debateLayout = (LinearLayout) view.findViewById(R.id.debate_layout);
debateLayout.setOnClickListener(this);
return view;
}
@Override
public void onClick(View v) {
Intent debatePromoListActivityIntent = new Intent(getActivity(), RecentPromotionListActivity.class);
debatePromoListActivityIntent.putExtra(MainActivity.USERID, userId);
debatePromoListActivityIntent.putExtra(MainActivity.DEBATEFLAG,true);
startActivity(debatePromoListActivityIntent);
}
private void onSessionStateChange(Session session, SessionState state, Exception exception){
// If the session is opened and is not null
if (session != null && session.isOpened() && ((MainActivity)getActivity()).isOnline()) {
// Get the user's data
makeMeRequest(session);
}
}
private void makeMeRequest(final Session session){
final Request request = Request.newMeRequest(session, new Request.GraphUserCallback() {
@Override
public void onCompleted(GraphUser user, Response response) {
if (session == Session.getActiveSession()) {
if (user != null) {
userId = user.getId();
String userName = user.getName();
String userEmail = user.getProperty("email").toString();
mCallback.setUserId(userId);
postData(userId, userName, userEmail);
}
}
}
});
request.executeAsync();
}
private void setListListener(ClientList clients) {
if (ApplicationCheckActivityVisibility.isActivityVisible()) {
adapter = new ClientListAdapter(getActivity(),R.layout.client_list_item,clients);
View view = getView();
clientList = (ListView) view.findViewById(R.id.clients_list);
clientList.setAdapter(adapter);
clientList.setOnItemClickListener(new AdapterView.OnItemClickListener() {
@Override
public void onItemClick(AdapterView<?> adapter, View view, int position, long id) {
Client chosenClient = (Client) clientList.getItemAtPosition(position);
String clientLink = chosenClient.getLink();
String clientId = chosenClient.getId();
Intent i = new Intent(getActivity(), PromoListActivity.class);
i.putExtra(MainActivity.CLIENTLINK, clientLink);
i.putExtra(MainActivity.CLIENTID, clientId);
i.putExtra(MainActivity.USERID, userId);
startActivity(i);
}
});
}
}
public void sortClientList(String form){
if(form.matches("ascend")){
Collections.sort(clients, ClientAscComparator);
}
else if(form.matches("descend")){
Collections.sort(clients, ClientDescComparator);
}
adapter.notifyDataSetChanged();
}
public Comparator<Client> ClientAscComparator = new Comparator<Client>() {
public int compare(Client client1, Client client2) {
String clientName1 = client1.getName();
String clientName2 = client2.getName();
return clientName1.compareTo(clientName2);
}
};
public Comparator<Client> ClientDescComparator = new Comparator<Client>() {
public int compare(Client client1, Client client2) {
String clientName1 = client1.getName();
String clientName2 = client2.getName();
return clientName2.compareTo(clientName1);
}
};
@Override
public void processFinish(ClientList clients) {
View view = getView();
if(view != null) {
RelativeLayout loadingPanel = (RelativeLayout) view.findViewById(R.id.loading_panel);
loadingPanel.setVisibility(View.GONE);
}
if(clients != null){
this.clients = clients;
setListListener(clients);
}
else{
Toast.makeText(getActivity(), R.string.no_restaurants_right_now, Toast.LENGTH_SHORT).show();
}
}
public void postData(String userId,String userName,String userEmail){
if(((MainActivity)getActivity()).isOnline()) {
HttpPostAsyncTask httpPostAsyncTask = new HttpPostAsyncTask(userId, userName, userEmail, getFragmentManager());
httpPostAsyncTask.execute();
}
else
{
((MainActivity)getActivity()).showPromptNoInternet();
}
}
@Override
public void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
uiHelper.onActivityResult(requestCode, resultCode, data);
}
@Override
public void onResume() {
super.onResume();
ApplicationCheckActivityVisibility.activityResumed();
if(((MainActivity)getActivity()).isOnline()) {
LoadClientsAsyncTask asyncTask = new LoadClientsAsyncTask();
asyncTask.delegate = this;
asyncTask.execute();
}
else
{
((MainActivity)getActivity()).showPromptNoInternet();
}
uiHelper.onResume();
}
@Override
public void onSaveInstanceState(Bundle bundle) {
super.onSaveInstanceState(bundle);
uiHelper.onSaveInstanceState(bundle);
}
@Override
public void onPause() {
super.onPause();
ApplicationCheckActivityVisibility.activityPaused();
uiHelper.onPause();
}
@Override
public void onDestroy() {
super.onDestroy();
uiHelper.onDestroy();
}
}
The error arises when the app calls an intent and gets in the other activities, so I think that I am not finishing cleaning the memory of the first activity correctly and the heap acumulates in the two of them causing the error. But as you saw in the logcat, the memory heap is stable and doesn't increase when I change from one activity to another. Sometimes I get this too:
I/dalvikvm﹕ threadid=3: reacting to signal 3
UPDATE: Another thing I observed is that I run the code in a samsung ACE, a Moto Razr Z3 and a Galaxy Tab 2 and the error doesn't appear even these devices have less memory than the Moto g, could this be an error or bug on the moto g?
Binder is an Android-specific interprocess communication mechanism, and remote method invocation system. That is, one Android process can call a routine in another Android process, using binder to indentify the method to invoke and pass the arguments between processes.
There are some limitations as to how much data a bundle can contain. If your bundle or intent extras are too large you can get this error. Are you passing data into a bundle at all?
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With