在 recyclerView 中通过 PackageManager 获取应用程序包的问题
Problems with getting application packages via PackageManager in a recyclerView
我正在尝试创建一个带有通过 recyclerview 实现的应用程序抽屉的 andorid 启动器 - 基本上我只想列出设备上所有已安装的应用程序。
目前,当我 运行 activity 它崩溃时,我不太清楚为什么。我认为问题是我没有从 phone 中正确提取应用程序包,因此 onBindViewHolder 崩溃了,因为我给了它空对象引用,但我不确定包的问题到底在哪里经理是。
这是持有recyclerview的activity,AppDrawer.java:
public class AppDrawer extends AppCompatActivity {
RecyclerView recyclerView;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.app_drawer);
recyclerView = findViewById(R.id.appsList);
// add this
recyclerView.setLayoutManager(new LinearLayoutManager(this));
AppAdapter adapter = new AppAdapter(this);
// replace this line by this two. (you should not call adapter method directly).
// adapter.onCreateViewHolder(recyclerView, 0);
recyclerView.setAdapter(adapter);
// notify the adapter that the data has changed
//recyclerView.notifyDataSetChanged();
}
}
这是AppAdapter.java:
public class AppAdapter extends RecyclerView.Adapter<AppAdapter.ViewHolder> {
private List<AppObject> appsList;
public class ViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener {
public TextView textView;
public ImageView img;
//This is the subclass ViewHolder which simply
//'holds the views' for us to show on each row
public ViewHolder(View itemView) {
super(itemView);
//Finds the views from our row.xml
textView = (TextView) itemView.findViewById(R.id.text);
img = (ImageView) itemView.findViewById(R.id.image);
itemView.setOnClickListener(this);
}
@Override
public void onClick (View v) {
int pos = getAdapterPosition();
Context context = v.getContext();
Intent launchIntent = context.getPackageManager().getLaunchIntentForPackage(appsList.get(pos).getName());
context.startActivity(launchIntent);
Toast.makeText(v.getContext(), appsList.get(pos).getName(), Toast.LENGTH_LONG).show();
}
}
public AppAdapter(Context c) {
//This is where we build our list of app details, using the app
//object we created to store the label, package name and icon
PackageManager pm = c.getPackageManager();
appsList = new ArrayList<AppObject>();
Intent i = new Intent(Intent.ACTION_MAIN, null);
i.addCategory(Intent.CATEGORY_LAUNCHER);
List<ResolveInfo> allApps = pm.queryIntentActivities(i, 0);
for(ResolveInfo ri:allApps) {
AppObject app = new AppObject(ri.loadLabel(pm).toString(), ri.activityInfo.packageName, ri.activityInfo.loadIcon(pm), false);
// app.getName() = ri.loadLabel(pm);
// app.getPackageName() = ri.activityInfo.packageName;
// app.getImage() = ri.activityInfo.loadIcon(pm);
appsList.add(app);
}
}
@Override
public void onBindViewHolder(AppAdapter.ViewHolder viewHolder, int i) {
//Here we use the information in the list we created to define the views
String appLabel = appsList.get(i).getName();
String appPackage = appsList.get(i).getPackageName();
Drawable appIcon = appsList.get(i).getImage();
TextView textView = viewHolder.textView;
textView.setText(appLabel);
ImageView imageView = viewHolder.img;
imageView.setImageDrawable(appIcon);
}
@Override
public int getItemCount() {
//This method needs to be overridden so that Androids knows how many items
//will be making it into the list
return appsList.size();
}
@Override
public AppAdapter.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
//This is what adds the code we've written in here to our target view
LayoutInflater inflater = LayoutInflater.from(parent.getContext());
View view = inflater.inflate(R.layout.app_drawer_item, parent, false);
ViewHolder viewHolder = new ViewHolder(view);
return viewHolder;
}
}
AppObject.java:
public class AppObject {
private String name,
packageName;
private Drawable image;
private Boolean isAppInDrawer;
public AppObject(String packageName, String name, Drawable image, Boolean isAppInDrawer) {
this.name = name;
this.image = image;
this.packageName = packageName;
this.isAppInDrawer = isAppInDrawer;
}
public String getPackageName() {
return packageName;
}
public String getName() {
return name;
}
public Drawable getImage() {
return image;
}
public Boolean getIsAppInDrawer() {return isAppInDrawer;}
public void setPackageName(String packageName) {
this.packageName = packageName;
}
public void setName(String name) {
this.name = name;
}
public void setImage(Drawable image) {
this.image = image;
}
public void setIsAppInDrawer(Boolean appInDrawer) {
this.isAppInDrawer = appInDrawer;
}
}
这是我尝试 运行 代码时收到的错误消息:
I/Surface: opservice is null false
W/ActivityThread: handleWindowVisibility: no activity for token android.os.BinderProxy@365f0dd
E/OpApplicationPackageManagerInjector: Application package com.oneplus.iconpack.square not found
E/OpApplicationPackageManagerInjector: Application package com.oneplus.iconpack.square not found
I/chatty: uid=10302(com.example.launcherapplication) identical 36 lines
E/OpApplicationPackageManagerInjector: Application package com.oneplus.iconpack.square not found
W/cherapplicatio: resources.arsc in APK '/data/app/com.oneplus.gallery-u0eFcDkuFtHGko86_UqHPA==/base.apk' is compressed.
E/OpApplicationPackageManagerInjector: Application package com.oneplus.iconpack.square not found
I/chatty: uid=10302(com.example.launcherapplication) identical 24 lines
E/OpApplicationPackageManagerInjector: Application package com.oneplus.iconpack.square not found
W/cherapplicatio: resources.arsc in APK '/data/app/com.facebook.orca-omRvfq_ufIlgi54ffkzO9g==/base.apk' is compressed.
E/OpApplicationPackageManagerInjector: Application package com.oneplus.iconpack.square not found
I/chatty: uid=10302(com.example.launcherapplication) identical 58 lines
E/OpApplicationPackageManagerInjector: Application package com.oneplus.iconpack.square not found
V/ViewRootImpl: The specified message queue synchronization barrier token has not been posted or has already been removed
I/Surface: opservice is null false
D/DecorView: onWindowFocusChangedFromViewRoot hasFocus: true, DecorView@ef5993e[AppDrawer]
D/AndroidRuntime: Shutting down VM
E/AndroidRuntime: FATAL EXCEPTION: main
Process: com.example.launcherapplication, PID: 15904
java.lang.NullPointerException: Attempt to invoke virtual method 'void android.widget.TextView.setText(java.lang.CharSequence)' on a null object reference
at com.example.launcherapplication.AppAdapter.onBindViewHolder(AppAdapter.java:82)
at com.example.launcherapplication.AppAdapter.onBindViewHolder(AppAdapter.java:18)
//FILLER ERROR MESSAGES//
E/AndroidRuntime: at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:516)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:950)
I/Process: Sending signal. PID: 15904 SIG: 9
不要在 OnBindViewHolder 中创建新的 TextView,而是直接调用 viewHolder 的 textview 并确保您的 findViewById() 调用正确的 ID。(基于您的 logCat 错误)
@Override
public void onBindViewHolder(AppAdapter.ViewHolder viewHolder, int i) {
viewHolder.textView.setText(appLabel);
viewHolder.img.setImageDrawable(appIcon);}
我正在尝试创建一个带有通过 recyclerview 实现的应用程序抽屉的 andorid 启动器 - 基本上我只想列出设备上所有已安装的应用程序。
目前,当我 运行 activity 它崩溃时,我不太清楚为什么。我认为问题是我没有从 phone 中正确提取应用程序包,因此 onBindViewHolder 崩溃了,因为我给了它空对象引用,但我不确定包的问题到底在哪里经理是。
这是持有recyclerview的activity,AppDrawer.java:
public class AppDrawer extends AppCompatActivity {
RecyclerView recyclerView;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.app_drawer);
recyclerView = findViewById(R.id.appsList);
// add this
recyclerView.setLayoutManager(new LinearLayoutManager(this));
AppAdapter adapter = new AppAdapter(this);
// replace this line by this two. (you should not call adapter method directly).
// adapter.onCreateViewHolder(recyclerView, 0);
recyclerView.setAdapter(adapter);
// notify the adapter that the data has changed
//recyclerView.notifyDataSetChanged();
}
}
这是AppAdapter.java:
public class AppAdapter extends RecyclerView.Adapter<AppAdapter.ViewHolder> {
private List<AppObject> appsList;
public class ViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener {
public TextView textView;
public ImageView img;
//This is the subclass ViewHolder which simply
//'holds the views' for us to show on each row
public ViewHolder(View itemView) {
super(itemView);
//Finds the views from our row.xml
textView = (TextView) itemView.findViewById(R.id.text);
img = (ImageView) itemView.findViewById(R.id.image);
itemView.setOnClickListener(this);
}
@Override
public void onClick (View v) {
int pos = getAdapterPosition();
Context context = v.getContext();
Intent launchIntent = context.getPackageManager().getLaunchIntentForPackage(appsList.get(pos).getName());
context.startActivity(launchIntent);
Toast.makeText(v.getContext(), appsList.get(pos).getName(), Toast.LENGTH_LONG).show();
}
}
public AppAdapter(Context c) {
//This is where we build our list of app details, using the app
//object we created to store the label, package name and icon
PackageManager pm = c.getPackageManager();
appsList = new ArrayList<AppObject>();
Intent i = new Intent(Intent.ACTION_MAIN, null);
i.addCategory(Intent.CATEGORY_LAUNCHER);
List<ResolveInfo> allApps = pm.queryIntentActivities(i, 0);
for(ResolveInfo ri:allApps) {
AppObject app = new AppObject(ri.loadLabel(pm).toString(), ri.activityInfo.packageName, ri.activityInfo.loadIcon(pm), false);
// app.getName() = ri.loadLabel(pm);
// app.getPackageName() = ri.activityInfo.packageName;
// app.getImage() = ri.activityInfo.loadIcon(pm);
appsList.add(app);
}
}
@Override
public void onBindViewHolder(AppAdapter.ViewHolder viewHolder, int i) {
//Here we use the information in the list we created to define the views
String appLabel = appsList.get(i).getName();
String appPackage = appsList.get(i).getPackageName();
Drawable appIcon = appsList.get(i).getImage();
TextView textView = viewHolder.textView;
textView.setText(appLabel);
ImageView imageView = viewHolder.img;
imageView.setImageDrawable(appIcon);
}
@Override
public int getItemCount() {
//This method needs to be overridden so that Androids knows how many items
//will be making it into the list
return appsList.size();
}
@Override
public AppAdapter.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
//This is what adds the code we've written in here to our target view
LayoutInflater inflater = LayoutInflater.from(parent.getContext());
View view = inflater.inflate(R.layout.app_drawer_item, parent, false);
ViewHolder viewHolder = new ViewHolder(view);
return viewHolder;
}
}
AppObject.java:
public class AppObject {
private String name,
packageName;
private Drawable image;
private Boolean isAppInDrawer;
public AppObject(String packageName, String name, Drawable image, Boolean isAppInDrawer) {
this.name = name;
this.image = image;
this.packageName = packageName;
this.isAppInDrawer = isAppInDrawer;
}
public String getPackageName() {
return packageName;
}
public String getName() {
return name;
}
public Drawable getImage() {
return image;
}
public Boolean getIsAppInDrawer() {return isAppInDrawer;}
public void setPackageName(String packageName) {
this.packageName = packageName;
}
public void setName(String name) {
this.name = name;
}
public void setImage(Drawable image) {
this.image = image;
}
public void setIsAppInDrawer(Boolean appInDrawer) {
this.isAppInDrawer = appInDrawer;
}
}
这是我尝试 运行 代码时收到的错误消息:
I/Surface: opservice is null false
W/ActivityThread: handleWindowVisibility: no activity for token android.os.BinderProxy@365f0dd
E/OpApplicationPackageManagerInjector: Application package com.oneplus.iconpack.square not found
E/OpApplicationPackageManagerInjector: Application package com.oneplus.iconpack.square not found
I/chatty: uid=10302(com.example.launcherapplication) identical 36 lines
E/OpApplicationPackageManagerInjector: Application package com.oneplus.iconpack.square not found
W/cherapplicatio: resources.arsc in APK '/data/app/com.oneplus.gallery-u0eFcDkuFtHGko86_UqHPA==/base.apk' is compressed.
E/OpApplicationPackageManagerInjector: Application package com.oneplus.iconpack.square not found
I/chatty: uid=10302(com.example.launcherapplication) identical 24 lines
E/OpApplicationPackageManagerInjector: Application package com.oneplus.iconpack.square not found
W/cherapplicatio: resources.arsc in APK '/data/app/com.facebook.orca-omRvfq_ufIlgi54ffkzO9g==/base.apk' is compressed.
E/OpApplicationPackageManagerInjector: Application package com.oneplus.iconpack.square not found
I/chatty: uid=10302(com.example.launcherapplication) identical 58 lines
E/OpApplicationPackageManagerInjector: Application package com.oneplus.iconpack.square not found
V/ViewRootImpl: The specified message queue synchronization barrier token has not been posted or has already been removed
I/Surface: opservice is null false
D/DecorView: onWindowFocusChangedFromViewRoot hasFocus: true, DecorView@ef5993e[AppDrawer]
D/AndroidRuntime: Shutting down VM
E/AndroidRuntime: FATAL EXCEPTION: main
Process: com.example.launcherapplication, PID: 15904
java.lang.NullPointerException: Attempt to invoke virtual method 'void android.widget.TextView.setText(java.lang.CharSequence)' on a null object reference
at com.example.launcherapplication.AppAdapter.onBindViewHolder(AppAdapter.java:82)
at com.example.launcherapplication.AppAdapter.onBindViewHolder(AppAdapter.java:18)
//FILLER ERROR MESSAGES//
E/AndroidRuntime: at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:516)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:950)
I/Process: Sending signal. PID: 15904 SIG: 9
不要在 OnBindViewHolder 中创建新的 TextView,而是直接调用 viewHolder 的 textview 并确保您的 findViewById() 调用正确的 ID。(基于您的 logCat 错误)
@Override
public void onBindViewHolder(AppAdapter.ViewHolder viewHolder, int i) {
viewHolder.textView.setText(appLabel);
viewHolder.img.setImageDrawable(appIcon);}