什么是Android PendingIntent?

623

我已经阅读了Android文档,但我仍需要更多的解释。那么,PendingIntent到底是什么?

18个回答

1021

PendingIntent是一个令牌,您可以将其提供给其他应用程序(例如NotificationManagerAlarmManager、主屏幕 AppWidgetManager或其他第三方应用程序),它允许其他应用程序使用您的应用程序权限来执行预定义的代码

如果您向其他应用程序提供了一个意图(Intent),它将使用自己的权限执行您的Intent。但是,如果您向其他应用程序提供了一个PendingIntent,该应用程序将使用您的应用程序权限执行您的Intent


5
除了通知之外,你在哪里看到使用pendingIntents?我认为我只看到过通知使用它... - android developer
13
@LieRyan 这个答案比developer.google关于PendingIntent的解释更好,感谢您。 - Antwan
4
@Johnny_D: 这句话的意思是,通常情况下,您需要创建一个明确的 Intent,并将其组件名称设置为绝对名称,以便无歧义地引用您自己的类之一。否则,该 Intent 可能会被发送到另一个应用程序中,这可能会导致问题,因为该 Intent 将在您的应用程序权限下运行。 - Lie Ryan
4
@LieRyan,这里的应用程序权限是指我们在清单中指定的权限吗?例如INTERNET权限? - Diffy
6
在你的情况下,如果一个特权应用程序A给了应用程序B一个待定意图以便B在想要读取联系人数据时发送它。那么A有责任询问用户希望向B提供哪些联系人数据,并且只提供那些数据给B。待定意图是一种特权升级机制,就像任何特权升级机制一样,伴随着强大的能力也有着伟大的责任。用户有责任决定是否信任应用程序B获取用户选择的联系人数据。 - Lie Ryan
显示剩余8条评论

68
PendingIntent为什么是必需的? 我曾经想过
  1. 接收应用程序本身不能创建意图或
  2. 我们不能使用简单的意图来实现同样的目的。

例如:Intent bluetoothIntent= new Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE);

如果我将bluetoothIntent发送到另一个没有权限android.permission.BLUETOOTH_ADMIN的应用程序,则该接收应用程序无法使用startActivity(bluetoothIntent)启用蓝牙。

使用PendingIntent克服了这个限制。通过PendingIntent,接收应用程序不需要具有android.permission.BLUETOOTH_ADMIN即可启用蓝牙。来源


5
你的蓝牙意图示例非常有价值。谢谢。 - Nicks
2
@Kiran - 如果接收应用程序可以通过挂起意图打开蓝牙,那么为什么该应用程序没有在其清单中包含此权限?这就像我正在制作一个可以拨打电话的应用程序,但我没有包含CALL_PHONE权限,因为我希望其他应用程序向我发送挂起意图以进行此通话。这是您想要表达的吗? - CopsOnRoad
2
@CopsOnRoad PendingIntent的接收应用程序可以是一个通用应用程序,它接收任何请求并代表请求者执行请求。它的角色只是一个中间人,因此没有所有权限。这种中间人应用程序的一个例子是通知管理器,它可以从通知中启动任何预期的应用程序,而不拥有权限。 - Xiao-Feng Li
这是一个有用的例子。我对普通Intent和PendingIntent之间的区别有了清晰的理解。谢谢。 - Prasanna Kumar

56

一个Pending Intent是您提供给某个应用程序的令牌,以代表您的应用执行某个操作,无论您的应用进程是否存活。

我认为文档已经足够详细:Pending Intent文档

只需考虑Pending Intent的用例,例如广播意图和定时闹钟,文档就会变得更清晰和有意义。


我认为Intent也是我们授权给其他应用程序代表我们执行某些动作的一种令牌。那么,Pending Intent和Intent之间唯一的区别就是我们的应用程序进程生命周期吗? - CopsOnRoad

52

在我的情况下,以上答案和谷歌官方文档都没有帮助我理解PendingIntent类的概念。

然后我发现了这个视频:Google I/O 2013, Beyond the Blue Dot session。在这个视频中,前谷歌工程师Jaikumar Ganesh讲解了PendingIntent是什么,这让我对它有了一个整体的认识。

以下是上述视频的文字记录(从15:24开始)。

那么何为pending intent?

它是你的应用进程会给位置进程的一个标记,位置进程会使用它来唤醒你的应用程序,当感兴趣的事件发生时。 这基本上意味着你的后台应用程序不必一直运行。 当发生感兴趣的事情时,我们会唤醒您。 这可以节省很多电量。

这段代码片段(包含在演示幻灯片中)使得这个解释更加清晰。

PendingIntent mIntent = PendingIntent.getService(...);

mLocationClient.requestLocationUpdates(locationRequest, mIntent);

public void onHandleIntent(Intent intent) {   
    String action = intent.getAction();   
    if (ACTION_LOCATION.equals(action)) {       
        Location location = intent.getParcelableExtra(...)   
    }
}

同意,这很简单明了。但它并没有告诉我们 PendingIntent 给其他应用程序的权限。 - CopsOnRoad

31

挂起意图是一种稍后启动的意图。当传递给 startActivity(Intent)StartService(Intent) 时,普通意图会立即启动。


23

什么是Intent?

Intent 是在Android中的一个特定命令,允许您向Android操作系统发送指令以执行特定操作。可以将其视为需要执行的操作。可以执行许多操作,例如:发送电子邮件,或将照片附加到电子邮件中,甚至是启动应用程序。创建 Intent 的逻辑工作流程通常如下所示: a. 创建 Intent b. 添加 Intent 选项 -> 比如我们要向操作系统发送什么类型的 Intent 或者与该 Intent 关联的任何属性,例如文本字符串或任何带有 Intent 的内容。 c. 运行 Intent

现实生活的例子:假设我早上起床想去洗手间。我首先要想到去洗手间,但这并不能直接让我到达洗手间。然后我会告诉我的大脑先下床,然后走到洗手间,然后解决问题,然后去洗手,最后去擦手。一旦我知道我要去哪里,我就发送开始的命令,我的身体开始行动。

什么是Pending Intents?

继续以上现实生活的例子,假设我想洗澡,但我想在刷牙和吃早饭后再洗澡。因此,我知道我至少需要等待30-40分钟才会洗澡。我仍然记得需要准备好我的衣服,然后走回浴室,然后脱衣服再洗澡。但是,在30-40分钟之前不会发生这种情况。现在我有了一个“待处理的意图”来洗澡。它会持续30-40分钟。

这基本上是待处理的意图和常规的意图之间的区别。可以创建常规意图而无需待处理的意图,但是要创建待处理的意图,必须先设置常规意图。


我非常喜欢这个简单的例子,通过这些话语,我理解得很好。 - Josema
我很高兴这篇文章对你有用,Josema。 - Narendra Motwani
这与Shakeeb Ayaz上面的解释完全相同。谁抄袭了谁? :) - likejudo
哦,这解释得很好。 - Sãúrâßh Jáðhàv

20

出租车类比

意图

意图通常用于启动服务。例如:

Intent intent = new Intent(CurrentClass.this, ServiceClass.class);
startService(intent);

这就像你叫出租车一样:

Myself = CurrentClass
Taxi Driver = ServiceClass

待定意图

您将需要使用类似于以下代码:

Intent intent = new Intent(CurrentClass.this, ServiceClass.class);
PendingIntent pi = PendingIntent.getService(parameter, parameter, intent, parameter);
getDataFromThirdParty(parameter, parameter, pi, parameter);

现在,这个第三方将会代表你启动服务。一个实际的生活类比是Uber或Lyft,它们都是出租车公司。

当你向Uber/Lyft发送乘车请求时,他们将代表您呼叫其中一名司机。

因此:

Uber/Lyft ------ ThirdParty which receives PendingIntent
Myself --------- Class calling PendingIntent
Taxi Driver ---- ServiceClass

感谢您使用 new Intent(CurrentClass.this)。其他人只是放了一个 context,但您提供了实际的上下文,告诉我们在这里提供什么。 - LinusGeffarth
如果你相信上帝,愿上帝保佑你。我现在感觉想哭,眼泪真的流了出来。 - Ezekiel
伟大的编程类比。 - Sãúrâßh Jáðhàv

17

一个可以被其他应用程序使用的未来意图。
以下是创建未来意图的示例:

Intent intent = new Intent(context, MainActivity.class);
PendingIntent pendIntent = PendingIntent.getActivity(context, 0, intent, 0);

9
因为你没有真正解释“将来”意图在何处特殊或可用于其他应用程序,所以被踩。 - Vic
@WhereDatApp.com 这句话是由安托万·德·圣-埃克苏佩里说的,由刘易斯·加兰蒂耶翻译。;) - Choletski
@Choletski 谢谢,我不知道翻译的事情。 - Oded Breiner

11

一个PendingIntent是一个令牌,您可以将其提供给另一个应用程序(例如通知管理器、闹钟管理器或其他第三方应用程序),从而允许此其他应用程序使用您的应用程序权限来执行预定义的代码块。 要通过pending intent执行广播,请通过PendingIntent.getBroadcast()获取PendingIntent。要通过pending intent执行活动,您可以通过PendingIntent.getActivity()接收该活动。


8

PendingIntent基本上是一个包装另一个Intent对象的对象。然后,它可以传递给外部应用程序,您授予该应用程序执行操作的权利,即像从您自己的应用程序进程执行意图一样执行该意图(具有相同的权限和身份)。出于安全原因,您应始终将显式意图传递给PendingIntent而不是隐式意图。

 PendingIntent aPendingIntent = PendingIntent.getService(Context, 0, aIntent,
                    PendingIntent.FLAG_CANCEL_CURRENT);

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接