Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Android java binder FAILED BINDER TRANSACTION

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?

like image 927
Gzuz07 Avatar asked Aug 26 '14 18:08

Gzuz07


People also ask

What is BINDER TRANSACTION?

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.


1 Answers

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?

like image 110
athor Avatar answered Oct 05 '22 07:10

athor