2010-07-21 27 views
31

Activity有没有办法找出谁(即班级名称)发送了Intent?我正在寻找一种通用的方式,以便我的Activity通过将收到的意向发送回发件人(可能是任何人)来回应收到的意向。如何获取意图的发件人?

回答

27

可能还有其他方法,但我知道的唯一解决方案是让活动A通过startActivityForResult()调用活动B.然后活动B可以使用getCallingActivity()来检索活动A的身份。

+1

我们在图书馆工作了核实'Intent's使用这种技术开始与发送者和接收者,因为它最简单的答案。你可以找到更多在这里https://dev.guardianproject.info/projects/trustedintents/wiki – 2014-07-30 18:30:26

+1

如何使用getCallingActivity()?我试着用它来设置这样的文本:'txt.setText(getCallingActivity());'但它显示'null'。我能做些什么才能显示呼叫活动的名称? – 2015-12-13 14:33:50

7

这不是令人难以置信的直接,但您可以从ActivityManager获取最近任务的列表。因此,调用者本质上是您的任务之前的任务,您可以获取有关该任务的信息。

用法示例:

ActivityManager am = (ActivityManager) this.getSystemService(ACTIVITY_SERVICE); 
List<ActivityManager.RecentTaskInfo> recentTasks = am.getRecentTasks(10000,ActivityManager.RECENT_WITH_EXCLUDED); 

以上将返回从最近的(你的)的所有任务列表来指定的限制。有关您可以从RecentTaskInfo对象获取的信息类型,请参阅文档here

+2

getRecentTasks被弃用API 21,并且将不再为没有通过您的应用程序拥有的栈工作。见http://developer.android.com/reference/android/app/ActivityManager.html#getRecentTasks(int,INT) – 2015-08-31 22:25:22

7

我使用的技术是要求应用程序发送相关的意图添加一个PendingIntent作为一个Parcelable额外; PendingIntent可以是任何类型(服务,广播等)。我的服务唯一能做的就是调用PendingIntent.getCreatorUid()和getCreatorPackage();这个信息在PendingIntent被创建时填充,并且不能被应用伪造,所以我可以获得关于Intent发送者的信息。 唯一需要注意的是该解决方案仅适用于Jellybean,后来才是这种情况。 希望这有助于,根据您的问题

+0

你如何要求他们送的PendingIntent?我没有看到一个意图过滤选项。你是否放弃了没有额外的意图? – TBridges42 2015-07-15 12:48:07

+0

看起来像一个不好的主意一见钟情。难道恶意应用程序伪造了PendingIntent吗?当然,'PendingIntent'没有公共构造函数,但'readPendingIntentOrNullFromParcel'看起来可以做到这一点,不是吗? – Giszmo 2016-10-17 16:55:46

+1

@Giszmo以及getCreatorUid()文档声明它不能被欺骗。不知道如何处理序列化,但必须有一些特殊的安全措施,如使用创建者拥有的私钥对序列化内容进行签名。也就是说,正如getCreatorUid()文档指出的那样,您仍然必须小心这个策略。仅仅因为某些包X具有由Y创建的PendingIntent并不意味着X == Y. Y可能已将PendingIntent发送给X用于某种不相关的目的。 Y向X发送一个PendingIntent意味着Y相信这个特定的动作,而不是一般的。 – 2017-08-30 18:00:43

1

,因为你想的意图向发件人发送startActivityForResult比什么,我要提出一个更好的选择。但是,当用户点击通知时,我需要启动活动B,并且只有在发件人活动为活动A时才执行活动B 中的某些代码。这就是我很简单的做法。

内活动答:

String senderName = this.getClass().getSimpleName();   
Intent clickIntent = new Intent(ActivityA.this, ActivityB.class); 
clickIntent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP); 
clickIntent.putExtra("SENDER_CLASS_NAME", senderName); 

//I use PendingIntent to start Activity B but you can use what you like such as this.startActivity(clickIntent); 
PendingIntent.getActivity(ActivityA.this, NOTIFICATION_ID, clickIntent, PendingIntent.FLAG_ONE_SHOT); 

内活动B:

@Override 
public void onCreate(Bundle savedInstanceState) { 
    super.onCreate(savedInstanceState); 

    if (savedInstanceState == null) { 
     Bundle bundle = getIntent().getExtras(); 
     if (bundle != null) { 
      if(bundle.containsKey("SENDER_CLASS_NAME")){ 
       String senderName = bundle.getString("SENDER_CLASS_NAME");     
       //Execute some code 
       Log.d("GCM", "Notifications clicked"); 
       } 
      } 
     } 
    } 
9

难道您收到的意图外部应用程序?您可以使用活动类

一个简单的例子getReferrer()方法:我打开谷歌地图应用程序中使用谷歌地图的股权与大家分享我的应用程序的某个位置。然后,我的应用程序打开,并在活动调用此方法:

this.getReferrer().getHost() 

将返回:

com.google.android.apps.maps 

看到文档的位置:https://developer.android.com/reference/android/app/Activity.html#getReferrer()

注意,这需要API 22。对于较旧的Android版本,看到ajwillliams

+0

如果您的应用程序已在Google地图中使用共享功能时已打开并保留在后台中,该怎么办?它还会返回谷歌地图的包名吗? – mathew11 2017-06-07 14:50:07

+1

getReferrer()需要API22(Android 5.1)。在4.4版本等较低版本中应该做些什么? – 2017-08-31 15:03:57

+0

一些代码来检查API22: 字符串startedFrom = NULL; 如果(android.os.Build.VERSION.SDK_INT> = Build.VERSION_CODES.LOLLIPOP_MR1){ startedFrom = this.getReferrer()和getHost(); } – FrankKrumnow 2017-11-14 11:20:23