我正在创建一个托管小部件的应用程序,除了我添加电子邮件小部件时它运行良好。当我这样做时,我得到一个java.lang.SecurityException:Permission Denial error:starting intent。
以下是错误日志:
java.lang.RuntimeException: Failure delivering result ResultInfo{who=null, request=11, result=-1, data=Intent { (has extras) }} to activity {aheschl.screenscortcut/aheschl.screenscortcut.WidgetEdge}: java.lang.SecurityException: Permission Denial: starting Intent { act=android.appwidget.action.APPWIDGET_CONFIGURE cmp=com.samsung.android.email.provider/com.samsung.android.email.widget.EmailWidgetConfig (has extras) } from ProcessRecord{af0a74c 10759:aheschl.screenscortcut/u0a319} (pid=10759, uid=10319) not exported from uid 10033
at android.app.ActivityThread.deliverResults(ActivityThread.java:4926)
at android.app.ActivityThread.handleSendResult(ActivityThread.java:4969)
at android.app.ActivityThread.access$1600(ActivityThread.java:222)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1850)
at android.os.Handler.dispatchMessage(Handler.java:102)
at android.os.Looper.loop(Looper.java:158)
at android.app.ActivityThread.main(ActivityThread.java:7230)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1230)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1120)
Caused by: java.lang.SecurityException: Permission Denial: starting Intent { act=android.appwidget.action.APPWIDGET_CONFIGURE cmp=com.samsung.android.email.provider/com.samsung.android.email.widget.EmailWidgetConfig (has extras) } from ProcessRecord{af0a74c 10759:aheschl.screenscortcut/u0a319} (pid=10759, uid=10319) not exported from uid 10033
at android.os.Parcel.readException(Parcel.java:1620)
at android.os.Parcel.readException(Parcel.java:1573)
at android.app.ActivityManagerProxy.startActivity(ActivityManagerNative.java:3131)
at android.app.Instrumentation.execStartActivity(Instrumentation.java:1541)
at android.app.Activity.startActivityForResult(Activity.java:4284)
at android.app.Activity.startActivityForResult(Activity.java:4231)
at aheschl.screenscortcut.WidgetEdge.configureWidget(WidgetEdge.java:124)
at aheschl.screenscortcut.WidgetEdge.onActivityResult(WidgetEdge.java:94)
at android.app.Activity.dispatchActivityResult(Activity.java:7138)
at android.app.ActivityThread.deliverResults(ActivityThread.java:4922)
at android.app.ActivityThread.handleSendResult(ActivityThread.java:4969)
at android.app.ActivityThread.access$1600(ActivityThread.java:222)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1850)
at android.os.Handler.dispatchMessage(Handler.java:102)
at android.os.Looper.loop(Looper.java:158)
at android.app.ActivityThread.main(ActivityThread.java:7230)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1230)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1120)
以下是日志中提到的configureWidget方法
private void configureWidget(Intent data) {
Bundle extras = data.getExtras();
int appWidgetId = extras.getInt(AppWidgetManager.EXTRA_APPWIDGET_ID, -1);
AppWidgetProviderInfo appWidgetInfo = mAppWidgetManager.getAppWidgetInfo(appWidgetId);
if (appWidgetInfo.configure != null) {
Intent intent = new Intent(AppWidgetManager.ACTION_APPWIDGET_CONFIGURE);
intent.setComponent(appWidgetInfo.configure);
intent.putExtra(AppWidgetManager.EXTRA_APPWIDGET_ID, appWidgetId);
startActivityForResult(intent, Constants.REQUEST_CREATE_APPWIDGET);
} else {
createWidget(data);
}
}
这里是onActivityResult()
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if (resultCode == RESULT_OK) {
if (requestCode == Constants.REQUEST_PICK_APPWIDGET) {
configureWidget(data);
} else if (requestCode == Constants.REQUEST_CREATE_APPWIDGET) {
createWidget(data);
} else if(requestCode == Constants.RESIZE_WIDGETS_CODE){
//getParams
int height = data.getIntExtra("height", 100);
int width = data.getIntExtra("width", 100);
receivedHeight = height;
receivedWidth = width;
waitingForResult = false;
}
} else if (resultCode == RESULT_CANCELED && data != null) {
int appWidgetId = data.getIntExtra(AppWidgetManager.EXTRA_APPWIDGET_ID, -1);
if (appWidgetId != -1) {
mAppWidgetHost.deleteAppWidgetId(appWidgetId);
}
}
}
非常感谢任何帮助。
答案 0 :(得分:1)
这是一个老问题,但我想我找到了解决方案。
我想知道带有exported = "false"
标签的活动如何仍被某些启动器调用。
这些启动器使用的AppWidgetHost中有一种方法startAppWidgetConfigureActivityForResult
。
启动应用程序窗口小部件提供程序代表调用方配置结果的活动。如果提供者在另一个配置文件中,因为您不允许在另一个配置文件中启动活动,请使用此方法。您可以选择提供在Activity#onActivityResult(int,int,android.content.Intent)中返回的请求代码,以及将传递给已启动活动的选项包。 请注意,必须绑定提供的应用程序小部件才能使此方法起作用。
因此,该方法不仅可以在另一个配置文件中启动活动,而且还忽略了exported = "false"
标签。对我来说听起来像是一个安全问题。