2017-02-11 19 views
2

Я разработчик Launcher и за основу для виджетов всегда следил за этим простым руководством, которое я нашел: Hosting Android Widgets. Теперь этот метод работает 100% при использовании демонстрационного приложения. Проблема заключается в том, чтобы добавить тему AppCompat и расширить AppCompatActivity, а не Activity с последними com.android.support:appcompat-v7:25.1.1. У меня возникают проблемы. После выбора определенных виджетов из диалога ACTION_APPWIDGET_PICK, я получаю ошибку следующим образом:AppCompat Breaks Launcher Widget. «не удалось найти какое-либо представление, используя представление ошибки»

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 дисплеи "Couldn't add widget". Основываясь на журнале ошибок, можно было бы естественно взглянуть на WidgetHostExampleActivity.java line #129, но это просто вызов mAppWidgetHost.createView(this, appWidgetId, appWidgetInfo);.

Кажется, что код будет работать на appcompat-v7:22.1.1, но ничего выше этого.

Примечание:

  1. Я проверил и подтвердил эту ошибку на Android 5.0.2 и Android 7.1.1
  2. Это происходит только с некоторыми виджетами. Некоторыми неудачными являются Default Calendar app на Android 7.1.1 и Play - My Library виджет игрового магазина.
  3. В моей реальной пусковой на игровом магазине я создал пользовательский виджет выбора деятельности, которая по-прежнему имеет проблемы, описанные

У меня есть полный исходный код этого проекта с изменениями, которые я упоминал выше здесь: 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: Я почти никогда не ставил вопросы сейчас, поэтому, когда я это делаю, вы знаете, что это настоящая проблема.

ответ

7

изменить контекст менеджера и хоста как контекст приложения, а не контекст активности.

AppWidgetManager = AppWidgetManager.getInstance(getApplicationContext()); 
mAppWidgetHost = new AppWidgetHost(getApplicationContext(), APPWIDGET_HOST_ID); 

Только что исправил эту проблему для меня.

+0

Довольно интересно это работает на Android 5.0.2, но не на Android 7.1.1 –

+3

EDIT: OK это работает, если вы также выполните: «mAppWidgetHost.createView (getApplicationContext(), appWidgetId, appWidgetInfo); –

+0

Да, это сработало отлично для меня на Android 7.x – dasfima

 Смежные вопросы

  • Нет связанных вопросов^_^