【问题标题】:Android Widgets w/ AdapterViewFlipper - Pending Intent Template does not get filled in with extras带有 AdapterViewFlipper 的 Android 小部件 - 未用附加功能填充待处理的意图模板
【发布时间】:2014-04-23 19:17:05
【问题描述】:

我正在制作一个 Android 主屏幕小部件,其中填充了来自网络的内容。设置它我从 google 的页面和其他一些 questions regarding the setOnClickFillInIntent() function being used 引用 StackWidget 示例。尽管如此,我还是不知道为什么在没有填充模板的情况下点击意图触发。 extras 不为空。小部件可以很好地加载和显示内容,但如果单击它会崩溃并出现 NullPointerEx。

我注意到,如果项目布局中的点击 ID widget_capsule_content 位于布局的根级别(LinearLayout),则根本不会触发意图。如果它在其子项(FrameLayout)中,它确实会触发,但附加项会被忽略。

widget_capsule.xml 的布局 - 单个集合项: - 这些示例都不是优雅的。

<?xml version="1.0" encoding="utf-8"?>
  <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"

android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="horizontal"
android:clickable="true"
android:focusable="true"
android:background="@drawable/capsule_bg5">

<FrameLayout
    android:id="@+id/widget_capsule_content"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:layout_weight="1"
    android:orientation="horizontal">

    <ImageView
        android:id="@+id/widget_thumbnail"
        android:layout_height="match_parent"
        android:layout_width="match_parent"
        android:scaleType="centerCrop" />
    <TextView
        android:id="@+id/capsule_title"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:textSize="10sp"
        android:layout_gravity="bottom"
        android:textColor="@color/white_text"
        android:background="#80000000"
        android:text="title"/>
</FrameLayout>
</LinearLayout>

widget_layout.xml 的布局,集合持有者:

<LinearLayout  xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_marginTop="5dp"
android:orientation="horizontal">
<LinearLayout
    android:layout_width="0dp"
    android:layout_height="match_parent"
    android:layout_weight="1"
    android:orientation="vertical">

    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:textColor="@color/white_text"
        android:textSize="18sp" />

    <AdapterViewFlipper
        android:id="@+id/widget_flipper"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:autoStart="true"
        android:flipInterval="10000"/>

    <ImageView
        android:id="@+id/widget_loading"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:background="@drawable/widget_loading"/>

</LinearLayout>
</LinearLayout>

来自 WidgetReceiver 的相关代码(扩展 AppWidgetProvider):

@Override
public void onUpdate(Context context, AppWidgetManager wManager, int[] appWidgetIds){
    //This method is allowed to handle multiple widgets VIA appWidgetId.
    ComponentName thisWidget = new ComponentName(context,
            IHWidgetReceiver.class);
    int[] allWidgetIds = wManager.getAppWidgetIds(thisWidget);
    for (int widgetId : allWidgetIds) {
        //service intent
        Intent sIntent = new Intent(context, IHWidgetService.class);
        sIntent.putExtra(AppWidgetManager.EXTRA_APPWIDGET_ID, widgetId);
        sIntent.setData(Uri.parse(sIntent.toUri(Intent.URI_INTENT_SCHEME)));

        RemoteViews remoteViews = new RemoteViews(context.getPackageName(),
                R.layout.widget_layout);
        remoteViews.setRemoteAdapter(R.id.widget_flipper, sIntent);

        // The empty view is displayed when the collection has no items. It should be a sibling
        // of the collection view.
        remoteViews.setEmptyView(R.id.widget_flipper, R.id.widget_loading);

        //Pending Intent to prepare individual item clicks
        /*Class<? extends  Activity> startA = IntentUtil.getActivityClass(context, IHDetail.class);
        Intent pI = new Intent(context, startA); //3
        pI.setAction(Intent.ACTION_VIEW);
        pI.putExtra(AppWidgetManager.EXTRA_APPWIDGET_ID, widgetId);
        pI.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);  //3
        pI.setData(Uri.parse(pI.toUri(Intent.URI_INTENT_SCHEME)));
        remoteViews.setPendingIntentTemplate(R.id.widget_flipper,
                PendingIntent.getActivity(context, 0, pI, PendingIntent.FLAG_UPDATE_CURRENT));*/

        //For sake of breakpointing below, this block is made to match the StackViewWidget sample as much as possible.
        //It suffers the same issue as the activity launch behavior above
        Intent pI = new Intent(context, IHWidgetReceiver.class);
        pI.setAction(ACTION_CLICK);
        pI.putExtra(AppWidgetManager.EXTRA_APPWIDGET_ID, widgetId);
        pI.setData(Uri.parse(pI.toUri(Intent.URI_INTENT_SCHEME)));
        remoteViews.setPendingIntentTemplate(R.id.widget_flipper,
                PendingIntent.getBroadcast(context, 0, pI, PendingIntent.FLAG_UPDATE_CURRENT));


        //done
        Log.i("Widget", "Widget Updated");
        wManager.updateAppWidget(widgetId, remoteViews);
        wManager.notifyAppWidgetViewDataChanged(allWidgetIds, widgetId);

    }
    super.onUpdate(context, wManager, appWidgetIds);
} 

@Override
public void onReceive(Context rContext, Intent rIntent) {
    Ln.e("RECEIVED THING + ");
    AppWidgetManager wManager = AppWidgetManager.getInstance(rContext);
    if (rIntent.getAction().equals(ACTION_CLICK)) {

        Toast.makeText(rContext, "Touched view ", Toast.LENGTH_SHORT).show();
            Bundle eBundle = rIntent.getExtras();
            CmsContent content = (CmsContent) eBundle.getSerializable(IHConstants.MS_CONTENT_EXTRA);
            String id = eBundle.getString(IHConstants.MS_ID_EXTRA);
            //trying again without the bundle
            CmsContent content2 = (CmsContent)  rIntent.getSerializableExtra(IHConstants.MS_CONTENT_EXTRA);
            String id2 = rIntent.getStringExtra(IHConstants.MS_ID_EXTRA);
            //breakpointed here. all of the above extras are null. the next line is a NPE

             Intent activityIntent = IntentUtil.getDetailIntent(rContext, content2, id2);
            activityIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
            rContext.startActivity(activityIntent);
    }
    super.onReceive(rContext, rIntent);
}

WidgetViewsFactory 的相关代码(实现 RemoteViewsService.RemoteViewsFactory ):

@Override
public RemoteViews getViewAt(int position) {
    //populate view w/ data
    RemoteViews rv = new RemoteViews(context.getPackageName(), R.layout.widget_capsule);
    rv.setTextViewText(R.id.capsule_title, getContent(position).getShortTitle());
    rv.setImageViewBitmap(R.id.widget_thumbnail, getContent(position).getThumbnail());

    //intent junk
    Bundle extras = new Bundle();
    Intent act = new Intent();
    //act.putExtra(IHConstants.MS_ID_EXTRA, capsules.get(position).getId());
    //act.putExtra(IHConstants.MS_CONTENT_EXTRA, getContent(position));
    extras.putString(IHConstants.MS_ID_EXTRA, capsules.get(position).getId());
    extras.putSerializable(IHConstants.MS_CONTENT_EXTRA, getContent(position));
    act.putExtras(extras);

    Ln.e("content in extras " + capsules.get(position).getId() + " | " + getContent(position).getDetailSection());  
    //Log indicates that the extras were not null when inserted
    rv.setOnClickFillInIntent(R.id.widget_capsule_content, act);
    return rv;
}

【问题讨论】:

  • 尝试从 widget_capsule.xml 中移除可点击和可聚焦的属性。在我的情况下,它适用于包装到 RelativeLayout 中的单个 ImageView。拥有一个根布局对于 AdapterViewFlipper 传递点击意图似乎至关重要。

标签: android android-layout android-intent android-widget


【解决方案1】:

我能够通过删除待处理意图模板中的额外内容来解决此问题。将这些额外的东西放在模板中会吹走适配器设置的额外捆绑包。

//pI.putExtra(AppWidgetManager.EXTRA_APPWIDGET_ID, widgetId); 
remoteViews.setPendingIntentTemplate(R.id.widget_flipper,
                 PendingIntent.getActivity(context, 0, pI, PendingIntent.FLAG_UPDATE_CURRENT));

仅在使用 setOnClickFillInIntent() 的捆绑集中放置额外内容。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2021-12-15
    • 1970-01-01
    • 2021-11-13
    • 2017-05-20
    • 2016-11-02
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多