AppCompat破坏启动器小部件功能.“使用错误视图找不到任何视图"; [英] AppCompat Breaks Launcher Widget ability. "couldn't find any view, using error view"
问题描述
我是启动器开发人员,而小部件的基础始终遵循我发现的这个简单指南:
I'm a launcher developer and for the basis for widgets have always followed this simple guide I found: Hosting Android Widgets. Now this method works 100 % when using the demo app. The problem is as soon as I add an AppCompat
theme and extend AppCompatActivity
rather than Activity
with the latest com.android.support:appcompat-v7:25.1.1
, I run into problems. After selecting certain widgets from the ACTION_APPWIDGET_PICK
dialog, I get the error as follows:
W/AppWidgetHostView: updateAppWidget couldn't find any view, using error view android.widget.RemoteViews$ActionException: view: android.support.v7.widget.AppCompatImageView can't use method with RemoteViews: setImageResource(int)
at android.widget.RemoteViews.getMethod(RemoteViews.java:775)
at android.widget.RemoteViews.access$300(RemoteViews.java:69)
at android.widget.RemoteViews$ReflectionAction.apply(RemoteViews.java:1266)
at android.widget.RemoteViews.performApply(RemoteViews.java:2587)
at android.widget.RemoteViews.apply(RemoteViews.java:2547)
at android.appwidget.AppWidgetHostView.updateAppWidget(AppWidgetHostView.java:395)
at android.appwidget.AppWidgetHost.createView(AppWidgetHost.java:336)
at com.lgfischer.widgethost.WidgetHostExampleActivity.createWidget(WidgetHostExampleActivity.java:129)
at com.lgfischer.widgethost.WidgetHostExampleActivity.onActivityResult(WidgetHostExampleActivity.java:93)
at android.app.Activity.dispatchActivityResult(Activity.java:6168)
at android.app.ActivityThread.deliverResults(ActivityThread.java:3732)
at android.app.ActivityThread.handleSendResult(ActivityThread.java:3779)
at android.app.ActivityThread.access$1300(ActivityThread.java:162)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1461)
at android.os.Handler.dispatchMessage(Handler.java:106)
at android.os.Looper.loop(Looper.java:189)
at android.app.ActivityThread.main(ActivityThread.java:5529)
at java.lang.reflect.Method.invoke(Native Method)
at java.lang.reflect.Method.invoke(Method.java:372)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:950)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:745)
此外, AppWidgetHostView
显示无法添加小部件"
.根据错误日志,自然会看到 WidgetHostExampleActivity.java第129行
,但这只是调用 mAppWidgetHost.createView(this,appWidgetId,appWidgetInfo);
In addition the AppWidgetHostView
displays "Couldn't add widget"
. Based on the error log, one would naturally take a look at WidgetHostExampleActivity.java line #129
, but that is simply calling mAppWidgetHost.createView(this, appWidgetId, appWidgetInfo);
.
该代码似乎可以在 appcompat-v7:22.1.1
上运行,但除此之外没有其他功能.
It seems that the code will work on appcompat-v7:22.1.1
, but nothing above that.
注意:
- 我已经在
Android 5.0.2
和Android 7.1.1
上测试并确认了此错误 - 这仅在某些小部件中发生.有些失败的是
Android 7.1.1
上的Default Calendar应用
和Play-My Library
播放商店小部件. - 在我的Play商店的实际启动器中,我创建了一个自定义小部件选择活动,该活动仍然存在所描述的问题
- I have tested and confirmed this error on
Android 5.0.2
andAndroid 7.1.1
- This only happens with some widgets. Some that have failed are the
Default Calendar app
onAndroid 7.1.1
andPlay - My Library
play store widget. - In my actual launcher on the play store I have created a custom widget select activity which still has the problem described
I have the full source code for this project with the modifications I mentioned above here: Google Drive
这是完整的 WidgetHostExampleActivity
:
public class WidgetHostExampleActivity extends AppCompatActivity{
final static int APPWIDGET_HOST_ID = 111;
final static int REQUEST_PICK_APPWIDGET = 222;
final static int REQUEST_CREATE_APPWIDGET = 333;
static final String TAG = "WidgetHostExampleActivity";
AppWidgetManager mAppWidgetManager;
AppWidgetHost mAppWidgetHost;
ViewGroup mainlayout;
/**
* Called on the creation of the activity.
*/
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
mainlayout = (ViewGroup) findViewById(R.id.main_layout);
mAppWidgetManager = AppWidgetManager.getInstance(this);
mAppWidgetHost = new AppWidgetHost(this, APPWIDGET_HOST_ID);
}
/**
* Launches the menu to select the widget. The selected widget will be on
* the result of the activity.
*/
void selectWidget() {
int appWidgetId = this.mAppWidgetHost.allocateAppWidgetId();
Intent pickIntent = new Intent(AppWidgetManager.ACTION_APPWIDGET_PICK);
pickIntent.putExtra(AppWidgetManager.EXTRA_APPWIDGET_ID, appWidgetId);
addEmptyData(pickIntent);
startActivityForResult(pickIntent, REQUEST_PICK_APPWIDGET);
}
/**
* This avoids a bug in the com.android.settings.AppWidgetPickActivity,
* which is used to select widgets. This just adds empty extras to the
* intent, avoiding the bug.
*
* See more: http://code.google.com/p/android/issues/detail?id=4272
*/
void addEmptyData(Intent pickIntent) {
ArrayList<AppWidgetProviderInfo> customInfo = new ArrayList<AppWidgetProviderInfo>();
pickIntent.putParcelableArrayListExtra(AppWidgetManager.EXTRA_CUSTOM_INFO, customInfo);
ArrayList<Bundle> customExtras = new ArrayList<Bundle>();
pickIntent.putParcelableArrayListExtra(AppWidgetManager.EXTRA_CUSTOM_EXTRAS, customExtras);
}
/**
* If the user has selected an widget, the result will be in the 'data' when
* this function is called.
*/
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
if (resultCode == RESULT_OK) {
if (requestCode == REQUEST_PICK_APPWIDGET) {
configureWidget(data);
} else if (requestCode == REQUEST_CREATE_APPWIDGET) {
createWidget(data);
}
} else if (resultCode == RESULT_CANCELED && data != null) {
int appWidgetId = data.getIntExtra(AppWidgetManager.EXTRA_APPWIDGET_ID, -1);
if (appWidgetId != -1) {
mAppWidgetHost.deleteAppWidgetId(appWidgetId);
}
}
}
/**
* Checks if the widget needs any configuration. If it needs, launches the
* configuration activity.
*/
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, REQUEST_CREATE_APPWIDGET);
} else {
createWidget(data);
}
}
/**
* Creates the widget and adds to our view layout.
*/
public void createWidget(Intent data) {
Bundle extras = data.getExtras();
int appWidgetId = extras.getInt(AppWidgetManager.EXTRA_APPWIDGET_ID, -1);
AppWidgetProviderInfo appWidgetInfo = mAppWidgetManager.getAppWidgetInfo(appWidgetId);
AppWidgetHostView hostView = mAppWidgetHost.createView(this, appWidgetId, appWidgetInfo);
hostView.setAppWidget(appWidgetId, appWidgetInfo);
mainlayout.addView(hostView);
Log.i(TAG, "The widget size is: " + appWidgetInfo.minWidth + "*" + appWidgetInfo.minHeight);
}
/**
* Registers the AppWidgetHost to listen for updates to any widgets this app
* has.
*/
@Override
protected void onStart() {
super.onStart();
mAppWidgetHost.startListening();
}
/**
* Stop listen for updates for our widgets (saving battery).
*/
@Override
protected void onStop() {
super.onStop();
mAppWidgetHost.stopListening();
}
/**
* Removes the widget displayed by this AppWidgetHostView.
*/
public void removeWidget(AppWidgetHostView hostView) {
mAppWidgetHost.deleteAppWidgetId(hostView.getAppWidgetId());
mainlayout.removeView(hostView);
}
/**
* Handles the menu.
*/
@Override
public boolean onOptionsItemSelected(MenuItem item) {
Log.i(TAG, "Menu selected: " + item.getTitle() + " / " + item.getItemId() + " / " + R.id.addWidget);
switch (item.getItemId()) {
case R.id.addWidget:
selectWidget();
return true;
case R.id.removeWidget:
removeWidgetMenuSelected();
return false;
}
return super.onOptionsItemSelected(item);
}
/**
* Handle the 'Remove Widget' menu.
*/
public void removeWidgetMenuSelected() {
int childCount = mainlayout.getChildCount();
if (childCount > 1) {
View view = mainlayout.getChildAt(childCount - 1);
if (view instanceof AppWidgetHostView) {
removeWidget((AppWidgetHostView) view);
Toast.makeText(this, R.string.widget_removed_popup, Toast.LENGTH_SHORT).show();
return;
}
}
Toast.makeText(this, R.string.no_widgets_popup, Toast.LENGTH_SHORT).show();
}
/**
* Creates the menu with options to add and remove widgets.
*/
@Override
public boolean onCreateOptionsMenu(Menu menu) {
MenuInflater inflater = getMenuInflater();
inflater.inflate(R.menu.widget_menu, menu);
return true;
}
}
这是我的 settings.gradel
:
apply plugin: 'com.android.application'
android {
compileSdkVersion 25
buildToolsVersion "25.0.2"
defaultConfig {
applicationId "com.lgfischer.widgethost"
minSdkVersion 11
targetSdkVersion 22
}
buildTypes {
release {
minifyEnabled false
shrinkResources false
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.txt'
}
}
}
dependencies {
compile 'com.android.support:appcompat-v7:25.1.1'
}
PS:我现在几乎从来没有发过问题,所以当我这样做时,您就会知道这是一个真正的问题.
PS: I hardly ever post questions now-a-days, so when I do, you know it's a real problem.
推荐答案
将管理器和主机的上下文更改为应用程序上下文,而不是活动上下文.
change the context of the manager and host to be the application context instead of the activity context.
AppWidgetManager = AppWidgetManager.getInstance(getApplicationContext());
mAppWidgetHost = new AppWidgetHost(getApplicationContext(), APPWIDGET_HOST_ID);
请为我解决该问题.
这篇关于AppCompat破坏启动器小部件功能.“使用错误视图找不到任何视图";的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!