失败的Binder事务正在破坏整个小部件

时间:2013-11-03 17:42:01

标签: java android android-listview bitmap

在我的小部件中,我不断收到此错误:

11-02 09:35:10.613: D/D&D(1557): onCreate called
11-02 09:35:10.933: E/JavaBinder(1557): !!! FAILED BINDER TRANSACTION !!!
11-02 09:35:10.933: D/AppInfoAdapter(1557): top

无论我做什么(我已经尝试减少位图大小,使位图静态,注释掉我的编码部分以查看错误的位置(顺便说一下,这根本没有帮助)),我总是得到这个错误。这个错误造成的是它使我的用户安装的应用程序的listView在滑动抽屉中根本不显示(它只是空白)。我的所有链接和其他类都可以正常工作。 (但我的listView是我整个小部件的中心部分和主要功能。)

我现在感到很茫然所以我只是要发布我已经得出结论的三个可疑课程(因为所有其他课程都工作正常)。

请注意,某些代码已被注释掉(例如编码拖放功能,因为我的真实设备不支持蜂窝。我会在listView重新开始工作时实现该代码)

AppInfoAdapter.java:

package com.example.awesomefilebuilderwidget;

import java.io.ByteArrayOutputStream;
import java.util.ArrayList;
import java.util.List;

import android.content.Context;
import android.content.Intent;
import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
import android.content.pm.PackageManager.NameNotFoundException;
import android.graphics.Bitmap;
import android.graphics.drawable.BitmapDrawable;
import android.graphics.drawable.Drawable;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.BaseAdapter;
import android.widget.CheckBox;
import android.widget.Filter;
import android.widget.Filterable;
import android.widget.ImageView;
import android.widget.TextView;

public class AppInfoAdapter extends BaseAdapter implements Filterable {
private Context mContext;
private List<PackageInfo> mListAppInfo;
private PackageManager mPackManager;
private List<PackageInfo> originalListAppInfo;
private Filter filter;

public AppInfoAdapter(Context c, List<PackageInfo> listApp,
        PackageManager pm) {
    mContext = c;
    this.originalListAppInfo = this.mListAppInfo = listApp;
    mPackManager = pm;
    Log.d("AppInfoAdapter", "top");
}

@Override
public int getCount() {
    Log.d("AppInfoAdapter", "getCount()");
    return mListAppInfo.size();
}

@Override
public Object getItem(int position) {
    Log.d("AppInfoAdapter", "getItem");
    return mListAppInfo.get(position);
}

@Override
public long getItemId(int position) {
    Log.d("AppInfoAdapter", "getItemId");
    return position;
}

public static Bitmap scaleDownBitmap(Bitmap default_b, int newHeight, Context c) {

    final float densityMultiplier = c.getResources().getDisplayMetrics().density;

    int h= (int) (100*densityMultiplier);
    int w= (int) (h * default_b.getWidth()/((double) default_b.getHeight()));

    default_b=Bitmap.createScaledBitmap(default_b, w, h, true);
    // TO SOLVE LOOK AT HERE:https://stackoverflow.com/questions/15517176/passing-bitmap-to-other-activity-getting-message-on-logcat-failed-binder-transac
    return default_b;
}

@Override
public View getView(final int position, View convertView, ViewGroup parent) {
    // get the selected entry
    final PackageInfo entry = (PackageInfo) mListAppInfo.get(position);

    // reference to convertView
    View v = convertView;

    // inflate new layout if null
    if (v == null) {
        LayoutInflater inflater = LayoutInflater.from(mContext);
        v = inflater.inflate(R.layout.layout_appinfo, null);
        Log.d("AppInfoAdapter", "New layout inflated");
    }

    // load controls from layout resources
    ImageView ivAppIcon = (ImageView) v.findViewById(R.id.ivIcon);
    TextView tvAppName = (TextView) v.findViewById(R.id.tvName);
    TextView tvPkgName = (TextView) v.findViewById(R.id.tvPack);
    final CheckBox addCheckbox = (CheckBox) v
            .findViewById(R.id.addCheckbox);
    Log.d("AppInfoAdapter", "Controls from layout Resources Loaded");

    // set data to display
    ivAppIcon.setImageDrawable(entry.applicationInfo.loadIcon(mPackManager));
    tvAppName.setText(entry.applicationInfo.loadLabel(mPackManager));
    tvPkgName.setText(entry.packageName);
    Log.d("AppInfoAdapter", "Data Set To Display");
    addCheckbox
            .setOnClickListener(new View.OnClickListener() {

                @Override
                public void onClick(View v) {
                    if (addCheckbox.isChecked()) {
                        System.out.println("Checked");
                        PackageManager pm = mContext.getPackageManager();
                        Drawable icon = null;
                        try {
                            icon = pm
                                    .getApplicationIcon(entry.packageName);
                        } catch (NameNotFoundException e) {
                            // TODO Auto-generated catch block
                            e.printStackTrace();
                        }
                        Drawable default_icon = pm.getDefaultActivityIcon();
                        if (icon instanceof BitmapDrawable
                                && default_icon instanceof BitmapDrawable) {
                            BitmapDrawable icon_bd = (BitmapDrawable) icon;
                            Bitmap icon_b = icon_bd.getBitmap();
                            BitmapDrawable default_bd = (BitmapDrawable) pm
                                    .getDefaultActivityIcon();
                            Bitmap default_b = default_bd.getBitmap();
                            if (icon_b == default_b) {
                                // It's the default icon
                                scaleDownBitmap(default_b, 100, v.getContext());
                                Log.d("AppInfoAdapter", "Scale Bitmap Chosen");

                                ByteArrayOutputStream stream = new ByteArrayOutputStream();
                                default_b.compress(Bitmap.CompressFormat.PNG, 100, stream);
                                byte[] byteArray = stream.toByteArray();
                                Log.d("AppInfoAdapter", "Scale Bitmap to Array");

                                Intent intent = new Intent(v.getContext(), GridView.class);
                                intent.putExtra("picture", byteArray);
                                v.getContext().startActivity(intent);
                                Log.d("AppInfoAdapter", "Intent started to send Bitmap");
                            }
                        }
                    } else {
                        System.out.println("Un-Checked");
                    }

                }
            });

    // return view
    return v;
}

@Override
public Filter getFilter() {
    if (filter == null) {
        filter = new Filter() {
            @Override
            protected FilterResults performFiltering(CharSequence constraint) {
                FilterResults results = new FilterResults();
                List<PackageInfo> myFilteredAppList = new ArrayList<PackageInfo>();
                constraint = constraint.toString().toLowerCase();

                if (constraint.length() == 0) {
                    myFilteredAppList.addAll(originalListAppInfo);

                }

                for (PackageInfo appInfo : originalListAppInfo) {
                    String somefield = appInfo.packageName;
                    String name = appInfo.packageName;
                    if (somefield.toLowerCase().contains(
                            constraint.toString().toLowerCase().toString())
                            || (name != null && name.toLowerCase()
                                    .contains(
                                            constraint.toString()
                                                    .toLowerCase()
                                                    .toString()))) {
                        myFilteredAppList.add(appInfo);
                    }
                }
                results.count = myFilteredAppList.size();
                results.values = myFilteredAppList;
                return results;
            }

            @Override
            protected void publishResults(CharSequence constraint,
                    FilterResults results) {

                if (results.values != null) {
                    mListAppInfo = (List<PackageInfo>) results.values;
                    notifyDataSetChanged();
                }
            }
        };
    }
    return filter;
}

}

Drag_and_Drop_App(摘录):

public class Drag_and_Drop_App extends Activity {
private static final int SET_BACKGROUND = 10;

private ListView mListAppInfo;
// Search EditText
EditText inputSearch;
public AppInfoAdapter adapter;
final SwipeDetector swipeDetector = new SwipeDetector();

@Override
public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);

    // set layout for the main screen
    setContentView(R.layout.drag_and_drop_app);

    // import buttons
    Button btnLinkToPersonalize = (Button) findViewById(R.id.btnLinkToPersonalize);
    Log.d("D&D", "onCreate called");

    // create new adapter
    adapter = new AppInfoAdapter(this, (List<PackageInfo>) Utilities.getInstalledApplications(this), getPackageManager());
    // load list application
   mListAppInfo = (ListView)findViewById(R.id.lvApps);
    // set adapter to list view
    mListAppInfo.setAdapter(adapter);
    // search bar
    inputSearch = (EditText) findViewById(R.id.inputSearch);

    inputSearch.addTextChangedListener(new TextWatcher() {

        @Override
        public void onTextChanged(CharSequence cs, int arg1, int arg2, int arg3) {
            // When user changed the Text
            // Drag_and_Drop_App.this.adapter.getFilter().filter(cs);  
             if (Drag_and_Drop_App.this.adapter == null){
                 // some print statement saying it is null
                 Log.d ("msg_error", "adapter_is_null");
             }
                Drag_and_Drop_App.this.adapter.getFilter().filter(cs);

            }

        @Override
        public void beforeTextChanged(CharSequence arg0, int arg1, int arg2,
                int arg3) {
            // TODO Auto-generated method stub

        }

        @Override
        public void afterTextChanged(Editable arg0) {
            // TODO Auto-generated method stub                          
        }
        });


    // implement event when an item on list view is selected
    mListAppInfo.setOnItemClickListener(new OnItemClickListener() {

        @Override
        public void onItemClick(AdapterView<?> parent, View view, int pos, long id) {
            // get the list adapter
            AppInfoAdapter appInfoAdapter = (AppInfoAdapter)parent.getAdapter();
            // get selected item on the list
            PackageInfo appInfo = (PackageInfo)appInfoAdapter.getItem(pos);
            // launch the selected application
            Utilities.launchApp(parent.getContext(), getPackageManager(), appInfo.packageName);
        }

    });

    // implement event when an item on list view is selected via long-click 
    mListAppInfo.setOnItemLongClickListener(new OnItemLongClickListener(){

        @Override
        public boolean onItemLongClick(AdapterView<?> parent, View view,int pos, long id) {
            if (swipeDetector.swipeDetected()){
                // do the onSwipe action 
            } else {
                // do the onItemLongClick action
                // get the list adapter
                AppInfoAdapter appInfoAdapter = (AppInfoAdapter)parent.getAdapter();
                // get selected item on the list
                PackageInfo appInfo = (PackageInfo)appInfoAdapter.getItem(pos);
                // launch the selected application
                Utilities.launchApp(parent.getContext(), getPackageManager(), appInfo.packageName);
                Log.d("D&D", "App launched");

            }
            return true;
        }
    });

    // implement slide event to open up plus button
    mListAppInfo.setOnTouchListener(swipeDetector);
    mListAppInfo.setOnItemClickListener(new OnItemClickListener() {
        public void onItemClick(AdapterView<?> parent, View view, int pos, long id) {
                if (swipeDetector.swipeDetected()){
                    // do the onSwipe action 
                    // TEST TO MAKE SURE SWIPE WORKS
                    AppInfoAdapter appInfoAdapter = (AppInfoAdapter)parent.getAdapter();
                    // get selected item on the list
                    PackageInfo appInfo = (PackageInfo)appInfoAdapter.getItem(pos);
                    // launch the selected application
                    Utilities.launchApp(parent.getContext(), getPackageManager(), appInfo.packageName);
                } else {
                    // do the onItemClick action
                    // get the list adapter
                    AppInfoAdapter appInfoAdapter = (AppInfoAdapter)parent.getAdapter();
                    // get selected item on the list
                    PackageInfo appInfo = (PackageInfo)appInfoAdapter.getItem(pos);
                    // launch the selected application
                    Utilities.launchApp(parent.getContext(), getPackageManager(), appInfo.packageName);
                }
            }
    });

最后是GridView.java:

package com.example.awesomefilebuilderwidget;

import java.util.ArrayList;

import android.app.Activity;
import android.content.ClipData;
import android.content.ClipDescription;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.os.Bundle;
import android.os.Handler;
import android.util.Log;
import android.view.DragEvent;
import android.view.View;
import android.view.View.OnDragListener;
import android.view.ViewGroup;
import android.widget.AdapterView;
import android.widget.AdapterView.OnItemLongClickListener;
import android.widget.BaseAdapter;
import android.widget.ImageView;

public class GridView extends Activity { // implements OnItemLongClickListener, OnDragListener{

ArrayList<Integer> drawables = new ArrayList<Integer>();

private BaseAdapter adapter;
private int draggedIndex = -1;

@Override
public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.drag_and_drop_app);
    Log.d("GridView", "onCreate called");
    drawables = new ArrayList<Integer>();
    drawables.add(R.drawable.pattern1);
    drawables.add(R.drawable.pattern2);
    android.widget.GridView gridView = (android.widget.GridView) findViewById(R.id.grid_view);
    // gridView.setOnItemLongClickListener(this);
    gridView.setAdapter(adapter = new BaseAdapter() {

        @Override
        // Get a View that displays the data at the specified position in
        // the data set.
        public View getView(int position, View convertView,
                ViewGroup gridView) {
            // try to reuse the views.
            ImageView view = (ImageView) convertView;
            // if convert view is null then create a new instance else reuse
            // it
            if (view == null) {
                view = new ImageView(GridView.this);
            }
            Bundle extras = getIntent().getExtras();
            byte[] byteArray = extras.getByteArray("picture");

            Bitmap default_b = BitmapFactory.decodeByteArray(byteArray, 0, byteArray.length);

            view.setImageBitmap(default_b);
            view.setImageResource(drawables.get(position));
            view.setScaleType(ImageView.ScaleType.CENTER_CROP);
            view.setLayoutParams(new android.widget.GridView.LayoutParams(70, 70));
            view.setTag(String.valueOf(position));
            return view;
        }

        @Override
        // Get the row id associated with the specified position in the
        // list.
        public long getItemId(int position) {
            return position;
        }

        @Override
        // Get the data item associated with the specified position in the
        // data set.
        public Object getItem(int position) {
            return drawables.get(position);
        }

        @Override
        // How many items are in the data set represented by this Adapter.
        public int getCount() {
            return drawables.size();
        }
    });
}

/*@Override
public boolean onItemLongClick(AdapterView<?> gridView, View view,
        int position, long row) {
    ClipData.Item item = new ClipData.Item((String) view.getTag());
    ClipData clipData = new ClipData((CharSequence) view.getTag(),
            new String[] { ClipDescription.MIMETYPE_TEXT_PLAIN }, item);
    view.startDrag(clipData, new View.DragShadowBuilder(view), null, 0);
    View trashCan = findViewById(R.id.trash_can);
    trashCan.setVisibility(View.VISIBLE);
    trashCan.setOnDragListener(GridView.this);
    trashCan.setOnDragListener(GridView.this);
    draggedIndex = position;
    return true;
}

@Override
public boolean onDrag(View view, DragEvent dragEvent) {
    switch (dragEvent.getAction()) {
    case DragEvent.ACTION_DRAG_STARTED:
        // Drag has started
        // If called for trash resize the view and return true
        if (view.getId() == R.id.trash_can) {
            view.animate().scaleX(1.0f);
            view.animate().scaleY(1.0f);
            return true;
        } else // else check the mime type and set the view visibility
        if (dragEvent.getClipDescription().hasMimeType(
                ClipDescription.MIMETYPE_TEXT_PLAIN)) {
            view.setVisibility(View.GONE);
            return true;

        } else {
            return false;
        }
    case DragEvent.ACTION_DRAG_ENTERED:
        // Drag has entered view bounds
        // If called for trash can then scale it.
        if (view.getId() == R.id.trash_can) {
            view.animate().scaleX(1.5f);
            view.animate().scaleY(1.5f);
        }
        return true;
    case DragEvent.ACTION_DRAG_EXITED:
        // Drag exited view bounds
        // If called for trash can then reset it.
        if (view.getId() == R.id.trash_can) {
            view.animate().scaleX(1.0f);
            view.animate().scaleY(1.0f);
        }
        view.invalidate();
        return true;
    case DragEvent.ACTION_DRAG_LOCATION:
        // Ignore this event
        return true;
    case DragEvent.ACTION_DROP:
        // Dropped inside view bounds
        // If called for trash can then delete the item and reload the grid
        // view
        if (view.getId() == R.id.trash_can) {
            drawables.remove(draggedIndex);
            draggedIndex = -1;
        }
        adapter.notifyDataSetChanged();
    case DragEvent.ACTION_DRAG_ENDED:
        // Hide the trash can
        new Handler().postDelayed(new Runnable() {

            @Override
            public void run() {
                findViewById(R.id.trash_can).setVisibility(View.GONE);
            }
        }, 1000l);
        if (view.getId() == R.id.trash_can) {
            view.animate().scaleX(1.0f);
            view.animate().scaleY(1.0f);
        } else {
            view.setVisibility(View.VISIBLE);
        }
        // remove drag listeners
        view.setOnDragListener(null);
        return true;

    }
    return false;
}*/



}

如果您发现任何看似不对或错的事,请发表评论。我一直试图修复此错误几天,并尝试了stackoverflow链接hereherehere以及其他人。

请帮我解决这个我不断得到的错误。我现在真的不知所措......

(感谢您阅读所有这些,我知道这很多)

这是我的Utilities类:

package com.example.awesomefilebuilderwidget;

import java.util.List;

import android.content.Context;
import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;


public class Utilities {

/*
 * Get all installed application on mobile and return a list
 * @param   c   Context of application
 * @return  list of installed applications
 */
public static List<PackageInfo> getInstalledApplications(Context c) {
    return c.getPackageManager().getInstalledPackages(PackageManager.GET_ACTIVITIES);
}

2 个答案:

答案 0 :(得分:3)

如果返回的信息总和大于1MB,

PackageManager方法(如getInstalledPackages())可能会导致活页夹事务错误。

缓解此问题的一种方法是不传入任何标志(例如,跳过PackageManager.GET_ACTIVITIES)以减少第一次调用中的数据量。然后,对于需要其他详细信息的软件包,请致电getPackageInfo()以获取特定软件包的详细信息。虽然这确实涉及多次IPC往返,因此速度较慢,但​​它有助于防止您超出每个事务1MB的限制。

答案 1 :(得分:1)

事实证明,当我获得已安装的应用程序列表时,我从packageManager收到了太多信息,即

Utilities.getInstalledApplications(this)

在我的Utilities课程中。那么我认为我不应该获得所有已安装的应用程序,而应该让用户安装应用程序(不包括那些对我来说毫无意义的系统应用程序)。这是更新的课程:

public class Utilities {

/*
 * Get all installed application on mobile and return a list
 * @param   c   Context of application
 * @return  list of installed applications
 */
public static List<ResolveInfo> getInstalledApplications(Context c) {
    Intent intent = new Intent(Intent.ACTION_MAIN);
    intent.addCategory(Intent.CATEGORY_LAUNCHER);
    return c.getPackageManager().queryIntentActivities(intent, PackageManager.GET_ACTIVITIES);
}

然后当然任何列表

<PackageInfo> 

必须改为

<ResolveInfo> 

但它就像一个魅力!