Android Studio标准ListView点击按钮崩溃问题求助
Hey there! Let's figure out why your app crashes when navigating to the ListViewLoader activity. Based on your code and the partial Logcat output, the most likely culprit is missing permissions for accessing device contacts—here's how to fix it step by step:
1. Add Contacts Permission to Manifest
First, you need to declare the READ_CONTACTS permission in your AndroidManifest.xml file. Add this line inside the root <manifest> tag (before the <application> tag):
<uses-permission android:name="android.permission.READ_CONTACTS" />
2. Request Runtime Permission (Android 6.0+)
Android 6.0 (API level 23) and above require apps to request dangerous permissions like contact access at runtime, not just in the manifest. Update your ListViewLoader code to handle this:
Update the onCreate Method
Modify the onCreate method to check for permission before initializing the loader:
@Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); // Keep your existing progress bar setup code here ProgressBar progressBar = new ProgressBar(this); progressBar.setLayoutParams(new LinearLayout.LayoutParams(LinearLayout.LayoutParams.WRAP_CONTENT, LinearLayout.LayoutParams.WRAP_CONTENT, Gravity.CENTER)); progressBar.setIndeterminate(true); getListView().setEmptyView(progressBar); ViewGroup root = (ViewGroup) findViewById(android.R.id.content); root.addView(progressBar); // Keep your existing cursor adapter setup code here String[] fromColumns = {ContactsContract.Data.DISPLAY_NAME}; int[] toViews = {android.R.id.text1}; mAdapter = new SimpleCursorAdapter(this, android.R.layout.simple_list_item_1, null, fromColumns, toViews, 0); setListAdapter(mAdapter); // Check and request READ_CONTACTS permission if (ContextCompat.checkSelfPermission(this, Manifest.permission.READ_CONTACTS) != PackageManager.PERMISSION_GRANTED) { // Request permission from user ActivityCompat.requestPermissions(this, new String[]{Manifest.permission.READ_CONTACTS}, 100); // Request code can be any integer } else { // Permission already granted, initialize loader getLoaderManager().initLoader(0, null, this); } }
Add Permission Result Handler
Add this method to your ListViewLoader class to handle the user's permission choice:
@Override public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) { super.onRequestPermissionsResult(requestCode, permissions, grantResults); if (requestCode == 100) { if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) { // Permission approved, start loading contacts getLoaderManager().initLoader(0, null, this); } else { // Permission denied—notify user and go back to MainActivity Toast.makeText(this, "Cannot load contacts without permission", Toast.LENGTH_SHORT).show(); finish(); } } }
Import Required Packages
Don't forget to add these imports at the top of ListViewLoader.java:
import android.Manifest; import android.content.pm.PackageManager; import android.support.v4.app.ActivityCompat; import android.support.v4.content.ContextCompat; import android.widget.Toast;
3. Verify Logcat for Additional Issues
If the crash still happens after adding permissions, check the full Logcat output (your snippet cuts off). Common secondary issues could include:
- Incorrect URI or projection in the
CursorLoader(your currentPROJECTIONusesContactsContract.Data._IDandDISPLAY_NAME, which is valid, but double-check the URI) - Issues with the
SimpleCursorAdapterconfiguration
Why This Works
The crash occurs because your app tries to access contact data without proper permission. Android runs the CursorLoader in a background thread (hence the AsyncTask #1 error), and when it hits a permission denial, it throws an unhandled exception. By requesting the permission upfront, you let the user grant access before the loader tries to fetch data.
内容的提问来源于stack exchange,提问作者Wouter

