Android 小部件 - Read_SMS 权限被拒绝 API 23
Android Widget - Read_SMS permission denied API 23
我是 android 的新手。
我打算做的是获取设备短信收件箱中当前的短信编号。
我希望这个数字显示在文本视图中。
我从其他 post 那里知道权限机制在 API 23 中发生了变化。
但是在所有这些 post 中,我们有一个 activity。
在我的例子中,我没有 activity,我试图在 AppWidgetProvider 的 onUpdate 方法中获取短信的数量。
在我的清单文件中,我添加了 READ_SMS 的权限。
AndroidManifest.xml
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.globa8track.smsgtw">
**<uses-permission android:name="android.permission.READ_SMS"/>**
<application
android:allowBackup="true"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:supportsRtl="true"
android:theme="@style/AppTheme">
<receiver android:name=".smsGtw">
<intent-filter>
<action android:name="android.appwidget.action.APPWIDGET_UPDATE" />
</intent-filter>
<meta-data
android:name="android.appwidget.provider"
android:resource="@xml/sms_gtw_info" />
</receiver>
</application>
</manifest>
然后在我的小部件上 Java Class
smsGtw.java
package com.globa8track.smsgtw;
import android.Manifest;
import android.app.DownloadManager;
import android.appwidget.AppWidgetManager;
import android.appwidget.AppWidgetProvider;
import android.content.ContentResolver;
import android.content.Context;
import android.content.pm.PackageManager;
import android.database.Cursor;
import android.net.Uri;
import android.support.v4.app.ActivityCompat;
import android.support.v4.content.ContextCompat;
import android.widget.RemoteViews;
import java.util.ArrayList;
public class smsGtw extends AppWidgetProvider {
void updateAppWidget(Context context, AppWidgetManager appWidgetManager,
int appWidgetId) {
ArrayList<String> inboxSms;
int nrSmsInInbox = 0;
inboxSms = fetchInbox(context);
nrSmsInInbox = inboxSms.size();
CharSequence widgetText = "Gtw Total Sms Received: " + nrSmsInInbox;
// Construct the RemoteViews object
RemoteViews views = new RemoteViews(context.getPackageName(), R.layout.sms_gtw);
views.setTextViewText(R.id.appwidget_text, widgetText);
// Instruct the widget manager to update the widget
appWidgetManager.updateAppWidget(appWidgetId, views);
}
@Override
public void onUpdate(Context context, AppWidgetManager appWidgetManager, int[] appWidgetIds) {
// There may be multiple widgets active, so update all of them
for (int appWidgetId : appWidgetIds) {
updateAppWidget(context, appWidgetManager, appWidgetId);
}
}
@Override
public void onEnabled(Context context) {
// Enter relevant functionality for when the first widget is created
}
@Override
public void onDisabled(Context context) {
// Enter relevant functionality for when the last widget is disabled
}
public static ArrayList<String> fetchInbox(Context context){
ArrayList<String> sms=new ArrayList<String>();
Uri uriSms=Uri.parse("content://sms/inbox");
ContentResolver cr = context.getContentResolver();
Cursor cursor = cr.query(uriSms, new String[]{"_id", "address", "date", "body"}, null, null, null);
cursor.moveToFirst();
while(cursor.moveToNext()){
String address=cursor.getString(1);
String body=cursor.getString(3);
sms.add("Address=>"+address+"\n Sms=>"+body);
}
return sms;
}
}
当我 运行 在 Android Studio 模拟器(Nexus 5 API 23) 上使用此代码时,我得到了
以下错误:
Process: com.globa8track.smsgtw, PID: 5397 java.lang.RuntimeException: Unable to start receiver com.globa8track.smsgtw.smsGtw: java.lang.SecurityException: Permission Denial: reading com.android.providers.telephony.SmsProvider uri content://sms/inbox from pid=5397, uid=10057 requires android.permission.READ_SMS, or grantUriPermission()
来自 post :
我知道需要先征求许可,然后检查该许可。正如@Tomáš Navara 所说。但在他的情况下有一个 activity.
我也必须有一个 activity 吗?我不需要用户交互,也不需要用于检查收件箱中存储的短信数量的用户界面。
另一件事,你能帮我开始 android 小部件世界吗?
我应该从哪里开始?
你能给我一些 pointers/resources 吗?
谢谢大家的耐心等待。
So I have to create an activity SMSRead that is called by the widgets onUpdate() through an intent?
没有。您现有的代码(大概)可以很好地获取消息和更新应用程序小部件。如果它适用于旧设备,如果它适用于 Android 6.0,如果您在“设置”中通过应用的屏幕手动授予权限,那么就可以了。
您需要 activity 的地方是能够请求用户的 READ_SMS
许可。
因此,在您的应用小部件代码中,您需要调用 ContextCompat.checkSelfPermission()
来查看您是否具有 READ_SMS
访问权限。如果您有访问权限,请继续更新您的应用小部件。如果您不这样做,请提出 Notification
让用户知道您需要他们授予您权限。理想情况下,Notification
将绑定到您的 activity,然后您可以在其中使用 ActivityCompat.requestPermissions()
请求 READ_SMS
。
您还可以安排 activity 作为您的应用程序小部件配置 activity,当您的应用程序小部件被添加到用户的主屏幕时,它会自动启动。这使您可以立即请求许可。但是,您仍然需要在 AppWidgetProvider
中调用 checkSelfPermission()
,因为用户可以通过“设置”应用撤销权限。
我是 android 的新手。
我打算做的是获取设备短信收件箱中当前的短信编号。 我希望这个数字显示在文本视图中。
我从其他 post 那里知道权限机制在 API 23 中发生了变化。 但是在所有这些 post 中,我们有一个 activity。 在我的例子中,我没有 activity,我试图在 AppWidgetProvider 的 onUpdate 方法中获取短信的数量。
在我的清单文件中,我添加了 READ_SMS 的权限。
AndroidManifest.xml
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.globa8track.smsgtw">
**<uses-permission android:name="android.permission.READ_SMS"/>**
<application
android:allowBackup="true"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:supportsRtl="true"
android:theme="@style/AppTheme">
<receiver android:name=".smsGtw">
<intent-filter>
<action android:name="android.appwidget.action.APPWIDGET_UPDATE" />
</intent-filter>
<meta-data
android:name="android.appwidget.provider"
android:resource="@xml/sms_gtw_info" />
</receiver>
</application>
</manifest>
然后在我的小部件上 Java Class smsGtw.java
package com.globa8track.smsgtw;
import android.Manifest;
import android.app.DownloadManager;
import android.appwidget.AppWidgetManager;
import android.appwidget.AppWidgetProvider;
import android.content.ContentResolver;
import android.content.Context;
import android.content.pm.PackageManager;
import android.database.Cursor;
import android.net.Uri;
import android.support.v4.app.ActivityCompat;
import android.support.v4.content.ContextCompat;
import android.widget.RemoteViews;
import java.util.ArrayList;
public class smsGtw extends AppWidgetProvider {
void updateAppWidget(Context context, AppWidgetManager appWidgetManager,
int appWidgetId) {
ArrayList<String> inboxSms;
int nrSmsInInbox = 0;
inboxSms = fetchInbox(context);
nrSmsInInbox = inboxSms.size();
CharSequence widgetText = "Gtw Total Sms Received: " + nrSmsInInbox;
// Construct the RemoteViews object
RemoteViews views = new RemoteViews(context.getPackageName(), R.layout.sms_gtw);
views.setTextViewText(R.id.appwidget_text, widgetText);
// Instruct the widget manager to update the widget
appWidgetManager.updateAppWidget(appWidgetId, views);
}
@Override
public void onUpdate(Context context, AppWidgetManager appWidgetManager, int[] appWidgetIds) {
// There may be multiple widgets active, so update all of them
for (int appWidgetId : appWidgetIds) {
updateAppWidget(context, appWidgetManager, appWidgetId);
}
}
@Override
public void onEnabled(Context context) {
// Enter relevant functionality for when the first widget is created
}
@Override
public void onDisabled(Context context) {
// Enter relevant functionality for when the last widget is disabled
}
public static ArrayList<String> fetchInbox(Context context){
ArrayList<String> sms=new ArrayList<String>();
Uri uriSms=Uri.parse("content://sms/inbox");
ContentResolver cr = context.getContentResolver();
Cursor cursor = cr.query(uriSms, new String[]{"_id", "address", "date", "body"}, null, null, null);
cursor.moveToFirst();
while(cursor.moveToNext()){
String address=cursor.getString(1);
String body=cursor.getString(3);
sms.add("Address=>"+address+"\n Sms=>"+body);
}
return sms;
}
}
当我 运行 在 Android Studio 模拟器(Nexus 5 API 23) 上使用此代码时,我得到了 以下错误:
Process: com.globa8track.smsgtw, PID: 5397 java.lang.RuntimeException: Unable to start receiver com.globa8track.smsgtw.smsGtw: java.lang.SecurityException: Permission Denial: reading com.android.providers.telephony.SmsProvider uri content://sms/inbox from pid=5397, uid=10057 requires android.permission.READ_SMS, or grantUriPermission()
来自 post :
我知道需要先征求许可,然后检查该许可。正如@Tomáš Navara 所说。但在他的情况下有一个 activity.
我也必须有一个 activity 吗?我不需要用户交互,也不需要用于检查收件箱中存储的短信数量的用户界面。
另一件事,你能帮我开始 android 小部件世界吗? 我应该从哪里开始? 你能给我一些 pointers/resources 吗? 谢谢大家的耐心等待。
So I have to create an activity SMSRead that is called by the widgets onUpdate() through an intent?
没有。您现有的代码(大概)可以很好地获取消息和更新应用程序小部件。如果它适用于旧设备,如果它适用于 Android 6.0,如果您在“设置”中通过应用的屏幕手动授予权限,那么就可以了。
您需要 activity 的地方是能够请求用户的 READ_SMS
许可。
因此,在您的应用小部件代码中,您需要调用 ContextCompat.checkSelfPermission()
来查看您是否具有 READ_SMS
访问权限。如果您有访问权限,请继续更新您的应用小部件。如果您不这样做,请提出 Notification
让用户知道您需要他们授予您权限。理想情况下,Notification
将绑定到您的 activity,然后您可以在其中使用 ActivityCompat.requestPermissions()
请求 READ_SMS
。
您还可以安排 activity 作为您的应用程序小部件配置 activity,当您的应用程序小部件被添加到用户的主屏幕时,它会自动启动。这使您可以立即请求许可。但是,您仍然需要在 AppWidgetProvider
中调用 checkSelfPermission()
,因为用户可以通过“设置”应用撤销权限。