此应用小部件片段中所有意图 (PendingIntents) 的逻辑流

Posted

技术标签:

【中文标题】此应用小部件片段中所有意图 (PendingIntents) 的逻辑流【英文标题】:Logical Flow of all Intents (PendingIntents) in this app widget snippet 【发布时间】:2014-11-03 21:53:48 【问题描述】:

我正在学习如何在 android 中构建主屏幕小部件。此代码用于应用小部件将 RingerMode 从 NORMAL 切换为 SILENT,反之亦然。

这很好用,但我需要全面了解其中所有意图的逻辑流程(即何时启动、去往何处、做什么、何时终止)。

请帮助我更清楚地理解这个主题。

package com.dummies.android.silentmodetoggle;

import android.app.Activity;
import android.app.IntentService;
import android.app.PendingIntent;
import android.appwidget.AppWidgetManager;
import android.appwidget.AppWidgetProvider;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.media.AudioManager;
import android.util.Log;
import android.widget.RemoteViews;

public class AppWidget extends AppWidgetProvider 

public static String tag ="SilentModeToggleWidget";

@Override
public void onReceive(Context context, Intent intent) 
    // TODO Auto-generated method stub
    Log.d(tag, "onReceive() first line");


    if(intent.getAction()==null)
    
        //Do Something
        Log.d(tag, "before startService()");
        context.startService(new Intent(context, ToggleService.class));
    
    else
        super.onReceive(context, intent);
    






@Override
public void onUpdate(Context context, AppWidgetManager appWidgetManager,
        int[] appWidgetIds) 

    // Do something in specified intervals
    context.startService(new Intent(context, ToggleService.class));


public static class ToggleService extends IntentService

    public ToggleService()

        super("AppWidget$ToggleService");

        Log.d(tag, "In ToggleService construcor");
    

    @Override
    protected void onHandleIntent(Intent arg0) 

        Log.d(tag, "In ToggleService > onHandleIntent");

        // TODO Auto-generated method stub
        ComponentName cn = new ComponentName(this, AppWidget.class);
        AppWidgetManager mgr = AppWidgetManager.getInstance(this);

        mgr.updateAppWidget(cn, buildUpdate(this));

    


    private RemoteViews buildUpdate(Context context)
        RemoteViews updateViews = new RemoteViews(context.getPackageName(), R.layout.widget);

        AudioManager audioManager = (AudioManager)context.getSystemService(Activity.AUDIO_SERVICE);

        if(audioManager.getRingerMode() == AudioManager.RINGER_MODE_SILENT)
            updateViews.setImageViewResource(R.id.phoneState, R.drawable.phone_on);
            audioManager.setRingerMode(AudioManager.RINGER_MODE_NORMAL);
        

        else
            updateViews.setImageViewResource(R.id.phoneState, R.drawable.phone_silent);
            audioManager.setRingerMode(AudioManager.RINGER_MODE_SILENT);
        


        Intent i = new Intent(this, AppWidget.class);

        PendingIntent pi = PendingIntent.getBroadcast(context, 0, i, 0);

        updateViews.setOnClickPendingIntent(R.id.phoneState, pi);

        return updateViews;






【问题讨论】:

“意图的生命周期”,这毫无意义。对不起。 Intent 只是一个数据对象,它存储框架用来启动组件的信息。上面没有生命周期之类的东西。 感谢@Budius 先生让我知道错误的术语使用和不存在意图生命周期。我已经纠正了这个问题。现在可以理解了吗? 【参考方案1】:

仍然不确定你在问什么,但我会尽力回答,如果不是你想要的,请以不同的方式解释。

Intent 通常会立即启动。你创建一个Intent可以通过调用startService或者startActivity来启动它,比如:

context.startService(new Intent(context, ToggleService.class));

在您编写上述代码的两次中,服务ToggleService 都会立即启动。

另一方面,PendingIntent 被保存以供以后启动,例如

updateViews.setOnClickPendingIntent(R.id.phoneState, pi);

在上述行中,AppWidget 广播在用户点击您的 HomeScreen AppWidget 中的R.id.phoneState 时启动。

每个PendingIntent 都以特定的ID 存储在系统中,此ID 是requestCode 参数(您在代码中使用了zero)...这意味着,如果您创建不同的PendingIntent使用相同的 ID 它将覆盖它,这意味着当用户单击 R.id.phoneState 时将启动不同的操作

【讨论】:

以上是关于此应用小部件片段中所有意图 (PendingIntents) 的逻辑流的主要内容,如果未能解决你的问题,请参考以下文章

Android 应用小部件实例发送相同的待处理意图

调用语音识别应用程序的小部件

Android小部件ListView项目点击不起作用

AppCompat v22.1.0 没有为片段正确主题化所有 xml 小部件

Android小部件,启动一个片段?

小部件上每个按钮的单独待定意图