AppCompat破坏启动器小部件功能.“使用错误视图找不到任何视图"; [英] AppCompat Breaks Launcher Widget ability. "couldn't find any view, using error view"

查看:81
本文介绍了AppCompat破坏启动器小部件功能.“使用错误视图找不到任何视图";的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我是启动器开发人员,而小部件的基础始终遵循我发现的这个简单指南:

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.

注意:

  1. 我已经在 Android 5.0.2 Android 7.1.1
  2. 上测试并确认了此错误
  3. 这仅在某些小部件中发生.有些失败的是 Android 7.1.1 上的 Default Calendar应用 Play-My Library 播放商店小部件.
  4. 在我的Play商店的实际启动器中,我创建了一个自定义小部件选择活动,该活动仍然存在所描述的问题
  1. I have tested and confirmed this error on Android 5.0.2 and Android 7.1.1
  2. This only happens with some widgets. Some that have failed are the Default Calendar app on Android 7.1.1 and Play - My Library play store widget.
  3. 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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆