RemoteViewsFactory中的onClick PendingIntent

时间:2012-07-30 13:33:35

标签: java android android-appwidget android-pendingintent remoteview

我正在为应用开发Android Widget,问题是我无法在onClickPendingIntent()的按钮上设置RemoteViewsFactory

我解释说:我创建了一个AppWidgetProvider,它调用RemoteViewsService的扩展名,调用RemoteViewsFactory的扩展名,以便在我的小部件中完成ListViewRemoteViewsFactory必须返回所有要更新的项目,或者创建它们并在窗口小部件上显示。但是对于列表视图的每个项目,我有两种类型的按钮:

  1. 打开gmaps / dialer / sms的按钮(工作正常)。
  2. 一个按钮,用于调用我的应用中的活动,并使用参数将其发送给项目的ID。
  3. 问题是第二个按钮,我的解决方案不起作用。

    问题在于:

    所以,这是不起作用的代码:

    row.setOnClickPendingIntent(R.id.taskButton, onClickPendingIntent);
    
    // Creating an onclick event for the done button
    Intent doneIntent = new Intent(mContext, WidgetProvider.class);
    doneIntent.putExtra("DONE_TASK", "DOOOOM");
    
    PendingIntent onDoneIntent = PendingIntent.getActivity(mContext, 0, doneIntent, 0);
    row.setOnClickPendingIntent(R.id.doneButton, onDoneIntent);
    

    以下是完整的WidgetFactory课程:

    import java.util.Collections;
    import java.util.Comparator;
    import java.util.GregorianCalendar;
    import java.util.Vector;
    
    import android.app.PendingIntent;
    import android.content.Context;
    import android.content.Intent;
    import android.graphics.Color;
    import android.net.Uri;
    import android.view.View;
    import android.widget.RemoteViews;
    import android.widget.RemoteViewsService;
    
    public class WidgetFactory implements RemoteViewsService.RemoteViewsFactory {
    
        private Vector<EventInfo> mAllEvents;
        private Context mContext;
    
        public WidgetFactory(Context ctxt, Intent intent) {
            // Creating member vars
            mContext = ctxt;
    
            updateAllEventsVector();
        }
    
    
        private void updateAllEventsVector() {
            SharedInstances sharedInstances = SharedInstances.get();
            mAllEvents = new Vector<EventInfo>(); 
    
            if (sharedInstances != null) {
                TaskRequestManager taskManager = sharedInstances
                        .getTaskRequestManager();
                CalendarRequestManager calManager = sharedInstances
                        .getCalendarRequestManager();
    
                Vector<TaskEvent> tasks = null;
                Vector<CalendarEvent> events = null;
    
                if (taskManager != null) 
                    tasks = taskManager.readTasksToday(mContext);
    
                if (calManager != null)
                    events = calManager.readCalendarEventsToday(mContext);
    
                if (!tasks.isEmpty())
                    mAllEvents.addAll(tasks);
    
    
                if (!events.isEmpty())
                    mAllEvents.addAll(events);
    
                mAllEvents = sortByDate(mAllEvents);
            }
        }
    
        @SuppressWarnings({ "unchecked", "rawtypes" })
        public Vector<EventInfo> sortByDate(Vector<EventInfo> events)
        {
    
            Vector<EventInfo> sortedEvents = new Vector<EventInfo>();
    
            for(EventInfo event : events)
            {
                if ((event.getStartTime()+event.getEventDuration()) > GregorianCalendar.getInstance().getTimeInMillis())
                    sortedEvents.add(event);
            }
    
            Collections.sort(events, new Comparator() {
                public int compare(Object arg0, Object arg1)
                {
                    EventInfo event0 = (EventInfo)arg0;
                    EventInfo event1 = (EventInfo)arg1;
    
                    if (event0.getStartTime()+event0.getEventDuration() > event1.getStartTime()+event1.getEventDuration())
                        return 1;
                    else if (event0.getStartTime()+event0.getEventDuration() == event1.getStartTime()+event1.getEventDuration())
                        return 0;
                    else if (event0.getStartTime()+event0.getEventDuration() < event1.getStartTime()+event1.getEventDuration())
                        return -1;
    
                    return 0;
                }
            });
    
            return sortedEvents;
        }
    
        @Override
        public int getCount() {
            return mAllEvents.size();
        }
    
        @Override
        public long getItemId(int arg0) {
            return (arg0);
        }
    
        @Override
        public RemoteViews getLoadingView() {
            return null;
        }
    
        @Override
        public RemoteViews getViewAt(int position) {
    
            // Getting item view
            RemoteViews row = new RemoteViews(mContext.getPackageName(),
                    R.layout.done_task_item);
    
            EventInfo eventInfo = mAllEvents.get(position);
    
    
    
            row.setInt(R.id.item_event, "setBackgroundColor", Color.argb(60, Color.red(eventInfo.getColor()), Color.green(eventInfo.getColor()), Color.blue(eventInfo.getColor())));
    
            // Converts startTime and endTime in string
            String startTime = TimeCursor.getAdaptativeTime(eventInfo.getStartTime());
            String endTime = TimeCursor.getAdaptativeTime((eventInfo
                    .getEventDuration() + eventInfo.getStartTime()));
    
            //Get title
            String title = eventInfo.getTitle();
    
            // Setting data in the view
            row.setTextViewText(R.id.titleTask, title);
            row.setTextViewText(R.id.periodTask, startTime + " to " + endTime);
    
            //Check type of event
            if (eventInfo.isTask()) {
                //endDate > GregorianCalendar.getInstance().getTimeInMillis() ) {
    
                //Check if action exists
                if (eventInfo.getAction() != null) {
    
                    //Get the action title
                    String action = eventInfo.getAction()
                            .getTitleText();
    
                    //Create a onClickPendingIntent for taskButton
                    PendingIntent onClickPendingIntent = null;
    
                    //Add related button
                    if (action.equals("Call"))
                    {
                        //Set call icon to taskButton
                        row.setImageViewResource(R.id.taskButton, R.drawable.ic_call_white );
    
                        //Get numbers from the contact
                        Vector<TelOrEmailItem> tel = eventInfo.getContact().getAllPhoneNumbers(mContext.getResources() , mContext, eventInfo.getAction());
    
                        // Creating an onclick event for call somebody
                        Intent callIntent = new Intent(Intent.ACTION_CALL, Uri.parse("tel:"+tel.get(0).getMainText()));
                        onClickPendingIntent = PendingIntent.getActivity(
                                mContext, 0, callIntent, 0);
    
                    }
                    else if (action.equals("SMS"))
                    {
                        //Set sms icon to taskButton
                        row.setImageViewResource(R.id.taskButton, R.drawable.ic_sms_white);
                        //Get numbers from the contact
                        Vector<TelOrEmailItem> tel = eventInfo.getContact().getAllPhoneNumbers(mContext.getResources() , mContext, eventInfo.getAction());
    
                        // Creating an onclick event for call somebody
                        Intent smsIntent = new Intent(Intent.ACTION_SENDTO, Uri.parse("smsto:"+tel.get(0).getMainText()));
                        onClickPendingIntent = PendingIntent.getActivity(
                                mContext, 0, smsIntent, 0);
                    }
                    /*else if (action.equals("Chat with"))
                        row.setImageViewResource(R.id.taskButton, R.drawable.ic_chat_white);*/
                    else if (action.equals("eMail") || action.equals("Mail") || action.equals("Write to"))
                    {
                        //Set email icon to taskButton
                        row.setImageViewResource(R.id.taskButton, R.drawable.ic_email_white);
    
                        //Get numbers from the contact
                        Vector<TelOrEmailItem> tel = eventInfo.getContact().getAllEMails(mContext, eventInfo.getAction());
    
                        //Creating an onclick event for email somebody
                        Intent emailIntent = new Intent(Intent.ACTION_SEND);
                        emailIntent.setType("plain/text");
    
                        emailIntent.putExtra(Intent.EXTRA_EMAIL, 
                                        new String[]{tel.get(0).getMainText()}); 
    
                        onClickPendingIntent = PendingIntent.getActivity(
                                mContext, 0, emailIntent, 0);
                    }
                    /*else if (action.equals("Skype"))
                        row.setImageViewResource(R.id.taskButton, R.drawable.ic_skype_white);*/
    
                    //Assign the intent to the taskButton
                    row.setOnClickPendingIntent(R.id.taskButton, onClickPendingIntent);
    
                    // Creating an onclick event for the done button
                    Intent doneIntent = new Intent(mContext, WidgetProvider.class);
    
                    doneIntent.putExtra("DONE_TASK", "DOOOOM");
    
                    PendingIntent onDoneIntent = PendingIntent.getActivity(mContext, 0, doneIntent, 0);
    
                    row.setOnClickPendingIntent(R.id.doneButton, onDoneIntent);
    
                }
                else
                    row.setViewVisibility(R.id.taskButton, View.GONE); //hidde the taskButton
    
                return row;
    
            }
            //Check if it's an event
            else if(eventInfo.isEvent()) {
    
                //hidde task button (Done)
                row.setViewVisibility(R.id.doneButton, View.GONE);
    
                CalendarEvent ev = eventInfo.getCalendarEvent();
                String location = ev.getEventLocation();
                if (location != null && !location.isEmpty())
                {
                    //Set the locate icon on the taskButton
                    row.setImageViewResource(R.id.taskButton, R.drawable.ic_locate_white);
    
                    //Define the place to open the map
                    Intent mapIntent = new Intent(Intent.ACTION_VIEW, Uri.parse("geo:0,0?q="+location));
                    PendingIntent onMapIntent = PendingIntent.getActivity(
                            mContext, 0, mapIntent, 0);
                    row.setOnClickPendingIntent(R.id.taskButton, onMapIntent);
                }
                else
                    row.setViewVisibility(R.id.taskButton, View.GONE);
    
                return row;
            }
    
    
            return null;
        }
    
        @Override
        public int getViewTypeCount() {
            return 1;
        }
    
        @Override
        public boolean hasStableIds() {
            return (true);
        }
    
        @Override
        public void onCreate() {
        }
    
        @Override
        public void onDataSetChanged() {
            // On data changes, update mTasks
            updateAllEventsVector();
        }
    
        @Override
        public void onDestroy() {
            mAllEvents = null;
        }
    
    }
    

    谢谢你:)


    修改 是的! 问题解决与否......

    方法onClickPendingIntent()现在正在运行,这是代码:

    // Creating an onclick event for the done button
    Intent onClickDone = new Intent(mContext, DoneTaskActivity.class);
    onClickDone.putExtra("TASK_ID", eventInfo.getTaskEvent().getTaskId());
    PendingIntent onClickPendingDone = PendingIntent.getActivity(mContext, 0, onClickDone, 0);
    row.setOnClickPendingIntent(R.id.doneButton, onClickPendingDone);
    

    但存在另一个问题:DoneTaskActivity未收到声明为TASK_ID的额外内容。在onCreate()的{​​{1}}方法中,参数中的DoneTaskActivity var保持为Bundle

    帮助:(

3 个答案:

答案 0 :(得分:0)

'putExtra'的第一个参数必须包含一个包前缀。 如果你的应用程序包的名称是'com.test',你应该输入'com.test.TASK_ID'。接收部分名称相同。

答案 1 :(得分:0)

尝试添加:

// When intents are compared, the extras are ignored, so we need to embed the extras
// into the data so that the extras will not be ignored.
onClickDone.setData(Uri.parse(onClickDone.toUri(Intent.URI_INTENT_SCHEME)));

row.setOnClickPendingIntent(R.id.doneButton, onClickPendingDone);

答案 2 :(得分:0)

在窗口小部件中使用列表视图时,您需要使用setOnClickFillInIntent侦听器。来自官方文档;

  

在小部件中使用集合(例如ListView,StackView等)时   在单个项目上设置PendingIntents是非常昂贵的,而且是   因此不允许。相反,可以使用单个PendingIntent模板   在集合上设置

在您的RemoteViewsFactory中,您可以像这样使用它;

public RemoteViews getViewAt(int position) {
    // position will always range from 0 to getCount() - 1.

    // Construct a RemoteViews item based on the app widget item XML file, and set the
    // text based on the position.
    RemoteViews rv = new RemoteViews(mContext.getPackageName(), R.layout.widget_item);
    rv.setTextViewText(R.id.widget_item, mWidgetItems.get(position).text);

    // Next, set a fill-intent, which will be used to fill in the pending intent template
    // that is set on the collection view in StackWidgetProvider.
    Bundle extras = new Bundle();
    extras.putInt(StackWidgetProvider.EXTRA_ITEM, position);
    Intent fillInIntent = new Intent();
    fillInIntent.putExtras(extras);
    // Make it possible to distinguish the individual on-click
    // action of a given item
    rv.setOnClickFillInIntent(R.id.widget_item, fillInIntent);

    ...

    // Return the RemoteViews object.
    return rv;
}

您还需要使用标准的PendingIntent,因为单个列表项无法设置PendingIntents,请参阅AppWidgets上的文档。