问题
My main aim of the app is to read the call history of the device and show it to the user using recyclerview and cardview. But When i run on marshmallow device app getting force close. Here is the code that i have used to read call history and the error that i got, when i run on 6.0
My MainActivity look like:
public class MainActivity extends AppCompatActivity implements Callbacks {
ArrayList<CallLogItem> mItems = new ArrayList<>();
private RecyclerView mRecyclerView;
private RecyclerView.LayoutManager mLayoutManager;
private RecyclerView.Adapter mAdapter;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.calllog);
mRecyclerView = (RecyclerView) findViewById(R.id.recycler_view);
mRecyclerView.setHasFixedSize(true);
mLayoutManager = new LinearLayoutManager(this);
mRecyclerView.setLayoutManager(mLayoutManager);
getCallDetails();
}
private void getCallDetails() {
String strOrder = CallLog.Calls.DATE + " DESC";
Cursor managedCursor = managedQuery(CallLog.Calls.CONTENT_URI, null, null, null, strOrder);
int number = managedCursor.getColumnIndex(CallLog.Calls.NUMBER);
int type = managedCursor.getColumnIndex(CallLog.Calls.TYPE);
int date = managedCursor.getColumnIndex(CallLog.Calls.DATE);
int duration = managedCursor.getColumnIndex(CallLog.Calls.DURATION);
while (managedCursor.moveToNext()) {
String phNum = managedCursor.getString(number);
String callTypeCode = managedCursor.getString(type);
String strcallDate = managedCursor.getString(date);
Date callDate = new Date(Long.valueOf(strcallDate));
String callDuration = managedCursor.getString(duration);
String callType = null;
int callcode = Integer.parseInt(callTypeCode);
switch (callcode) {
case CallLog.Calls.OUTGOING_TYPE:
callType = "Outgoing";
break;
case CallLog.Calls.INCOMING_TYPE:
callType = "Incoming";
break;
case CallLog.Calls.MISSED_TYPE:
callType = "Missed";
break;
}
CallLogItem callLogItem = new CallLogItem();
callLogItem.setPhoneNumber(phNum);
callLogItem.setCallDate(String.valueOf(callDate));
callLogItem.setCallType(callType);
callLogItem.setCallDuration(callDuration);
mItems.add(callLogItem);
mAdapter = new CallLogAdapter(mItems, this);
mRecyclerView.setAdapter(mAdapter);
}
managedCursor.close();
}
@Override
public void onCustomClick(CallLogItem callLogItem) {
Toast.makeText(getApplicationContext(), "" + callLogItem.getPhoneNumber(), Toast.LENGTH_LONG).show();
}
@Override
public void onCustomLongClick(CallLogItem callLogItem) {
}}
My Adapter Class look like:
public class CallLogAdapter extends RecyclerView.Adapter<CallLogAdapter.ViewHolder> {
private List<CallLogItem> mItems;
private Callbacks mCallbacks;
public CallLogAdapter(ArrayList<CallLogItem> mItems, Callbacks callbacks) {
this.mItems = mItems;
this.mCallbacks = callbacks;
}
@Override
public ViewHolder onCreateViewHolder(ViewGroup viewGroup, int i) {
View v = LayoutInflater.from(viewGroup.getContext())
.inflate(R.layout.bookmark_card_item, viewGroup, false);
ViewHolder viewHolder = new ViewHolder(v);
return viewHolder;
}
@Override
public void onBindViewHolder(ViewHolder viewHolder, int position) {
CallLogItem callLogItem = mItems.get(position);
viewHolder.phoneNumber.setText("Phone Number: " + callLogItem.getPhoneNumber());
viewHolder.callDuration.setText("Call Duration(In Sec): " + callLogItem.getCallDuration());
viewHolder.callDate.setText("Call Date: " + callLogItem.getCallDate());
viewHolder.callType.setText("Call Type: " + callLogItem.getCallType());
}
@Override
public int getItemCount() {
return mItems.size();
}
class ViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener, View.OnLongClickListener {
public View view;
public TextView phoneNumber, callDuration, callDate, callType;
public ViewHolder(View itemView) {
super(itemView);
this.view = itemView;
phoneNumber = (TextView) itemView.findViewById(R.id.phoneNumber);
callDuration = (TextView) itemView.findViewById(R.id.callDuration);
callDate = (TextView) itemView.findViewById(R.id.callDate);
callType = (TextView) itemView.findViewById(R.id.callType);
view.setOnLongClickListener(this);
view.setOnClickListener(this);
}
// onCustomClick Listener for view
@Override
public void onClick(View v) {
int position = getAdapterPosition();
CallLogItem callLogItem = mItems.get(position);
mCallbacks.onCustomClick(callLogItem);
}
//onLongClickListener for view
@Override
public boolean onLongClick(View v) {
int position = getAdapterPosition();
CallLogItem callLogItem = mItems.get(position);
mCallbacks.onCustomLongClick(callLogItem);
return true;
}
}}
My POJO class look like:
public class CallLogItem {
private String phoneNumber;
private String callType;
private String callDate;
private String callDuration;
public String getPhoneNumber() {
return phoneNumber;
}
public void setPhoneNumber(String phoneNumber) {
this.phoneNumber = phoneNumber;
}
public String getCallType() {
return callType;
}
public void setCallType(String callType) {
this.callType = callType;
}
public String getCallDate() {
return callDate;
}
public void setCallDate(String callDate) {
this.callDate = callDate;
}
public String getCallDuration() {
return callDuration;
}
public void setCallDuration(String callDuration) {
this.callDuration = callDuration;
}}
My CallbackClass look like
public interface Callbacks {
void onCustomClick(CallLogItem callLogItem);
void onCustomLongClick(CallLogItem callLogItem);}
Error
Caused by: java.lang.SecurityException: Permission Denial:
opening provider com.android.providers.contacts.CallLogProvider from ProcessRecord{bf7427a 7579:karthik.callloghistory/u0a525} (pid=7579, uid=10525) requires android.permission.READ_CALL_LOG or android.permission.WRITE_CALL_LOG
at android.os.Parcel.readException(Parcel.java:1599)
at android.os.Parcel.readException(Parcel.java:1552)
at android.app.ActivityManagerProxy.getContentProvider(ActivityManagerNative.java:3860)
at android.app.ActivityThread.acquireProvider(ActivityThread.java:5055)
at android.app.ContextImpl$ApplicationContentResolver.acquireUnstableProvider(ContextImpl.java:2025)
at android.content.ContentResolver.acquireUnstableProvider(ContentResolver.java:1517)
at android.content.ContentResolver.query(ContentResolver.java:482)
at android.content.ContentResolver.query(ContentResolver.java:441)
at android.app.Activity.managedQuery(Activity.java:2033)
at karthik.callloghistory.MainActivity.getCallDetails(MainActivity.java:39)
at karthik.callloghistory.MainActivity.onCreate(MainActivity.java:31)
at android.app.Activity.performCreate(Activity.java:6583)
at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1114)
at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2531)
at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2666)
at android.app.ActivityThread.-wrap11(ActivityThread.java)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1493)
at android.os.Handler.dispatchMessage(Handler.java:111)
at android.os.Looper.loop(Looper.java:207)
Here is my manifest file looks like
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="karthik.callloghistory">
<uses-permission android:name="android.permission.READ_CALL_LOG" />
<uses-permission android:name="android.permission.WRITE_CALL_LOG" />
<application
android:allowBackup="true"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:supportsRtl="true"
android:theme="@style/AppTheme">
<activity android:name=".MainActivity">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
</application>
</manifest>
来源:https://stackoverflow.com/questions/39870043/how-to-read-call-log-history-of-a-device-in-android-in-6-0