【发布时间】:2022-04-04 14:46:57
【问题描述】:
Activity 有没有办法找出谁(即班级名称)发送了Intent?我正在为我的Activity 寻找一种通用的方式来响应收到的意图,将其发回给发件人,无论是谁。
【问题讨论】:
标签: android
Activity 有没有办法找出谁(即班级名称)发送了Intent?我正在为我的Activity 寻找一种通用的方式来响应收到的意图,将其发回给发件人,无论是谁。
【问题讨论】:
标签: android
可能还有另一种方法,但我知道的唯一解决方案是让 Activity A 通过 startActivityForResult() 调用 Activity B。然后 Activity B 可以使用getCallingActivity() 来检索 Activity A 的身份。
【讨论】:
Intents 的发送者和接收者,它首先使用这种技术,因为它是最简单的。你可以在这里找到更多dev.guardianproject.info/projects/trustedintents/wiki
txt.setText(getCallingActivity()); 但它显示'null'。我该怎么做才能让它显示调用活动的名称?
它是您接收意图的外部应用程序吗?你可以使用activity类的getReferrer()方法
一个简单的例子:我打开了谷歌地图应用程序,通过使用谷歌地图的分享选项与我的应用程序分享一些位置。然后我的应用程序打开并在 Activity 中调用此方法:
this.getReferrer().getHost()
将返回:
com.google.android.apps.maps
在此处查看文档:https://developer.android.com/reference/android/app/Activity.html#getReferrer()
请注意,这需要 API 22。对于较旧的 Android 版本,请参阅 ajwillliams 的回答
【讨论】:
我使用的一种技术是要求发送相关 Intent 的应用程序将 PendingIntent 添加为 Parcelable extra; PendingIntent 可以是任何类型(服务、广播等)。我的服务唯一要做的就是调用 PendingIntent.getCreatorUid() 和 getCreatorPackage();此信息在创建 PendingIntent 时填充,并且无法由应用程序伪造,因此我可以获得有关 Intent 发件人的信息。 唯一需要注意的是,该解决方案仅适用于 Jellybean 和后来的情况,这是我的情况。 希望这会有所帮助,
【讨论】:
PendingIntent 吗?当然,PendingIntent 没有公共构造函数,但 readPendingIntentOrNullFromParcel 看起来可以解决问题,不是吗?
这不是非常直接,但您可以从 ActivityManager 获取最近任务的列表。所以调用者本质上是你之前的任务,你可以获取关于该任务的信息。
示例用法:
ActivityManager am = (ActivityManager) this.getSystemService(ACTIVITY_SERVICE);
List<ActivityManager.RecentTaskInfo> recentTasks = am.getRecentTasks(10000,ActivityManager.RECENT_WITH_EXCLUDED);
上面将返回从最近(您的)到指定限制的所有任务的列表。请参阅文档here,了解可以从 RecentTaskInfo 对象中获取的信息类型。
【讨论】:
通常您不需要知道这一点。如果调用活动使用startActivityForResult(Intent, int),则被调用者可以使用setResult(int, Intent) 指定要发送回调用者的Intent。调用者将在其onActivityResult(int, int, Intent) 方法中收到此 Intent。
【讨论】:
setResult 的意图仅在子 Activity 关闭后发送。我希望能够在子活动运行时任意将意图发送回父活动。
根据您的问题,由于您想向发件人发送意图返回,因此 startActivityForResult 是比我建议的更好的选择。但是我需要在用户单击通知时启动活动 B,并在活动 B 中执行一些代码只有当发送者活动是活动 A 时。这就是我非常简单的做法。
内部活动 A:
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");
}
}
}
}
【讨论】:
就我而言,这里接受的和另一个投票最多的答案都不是完美的。
Activity.getCallerActivity() 仅适用于通过 startActivityForResult 启动您的活动的发送者,这意味着如果发件人也在您的应用中并且您拥有完全控制权,则它可以工作,但并非每个外部应用都以这种方式启动其他应用。
另一个投票最多的答案为外部应用程序提供了解决方案,但它也有问题。首先,我更喜欢 getAuthority() 而不是 getHost(),其次,如果发件人是浏览器类型应用程序,例如 Chrome,主机和权限都会给您浏览网页的地址主机,例如 www.google.com,而不是应用程序本身。所以这取决于你如何定义'发送者',如果你需要找出哪个网页启动你,权限/主机足够好,但如果你需要找出哪个应用程序启动你,恐怕权限/主机可以只有当 getScheme() 为您提供 android-app 而不是 http。
【讨论】:
使用 UsageStatsManager 和旧的 RecentTaskInfo 获取 OnCreate 或 onNewIntent 的意图发送者:
public static String getTopMostThirdPartyPackage(Context context) {
String thisPak = null, tmp, top = null;
try {
thisPak = context.getPackageName();
if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP_MR1) {
UsageStatsManager man = (UsageStatsManager) context.getSystemService(Context.USAGE_STATS_SERVICE);
long now = System.currentTimeMillis();
UsageEvents uEvts = man.queryEvents(now - 5000,now); // query in 5 sec
UsageEvents.Event e = new UsageEvents.Event();
while (uEvts.getNextEvent(e)){
tmp = e.getPackageName();
if (!thisPak.equals(tmp)) {
top = tmp;
break;
}
}
} else {
ActivityManager man = (ActivityManager) context.getSystemService(Context.ACTIVITY_SERVICE);
List<ActivityManager.RecentTaskInfo> tasks = man.getRecentTasks(3, 0);
for(ActivityManager.RecentTaskInfo info:tasks) {
tmp = info.baseIntent.getComponent().getPackageName();
if (!thisPak.equals(tmp)) {
top = tmp;
break;
}
}
}
} catch (Exception e) {
}
return top;
}
权限:
<uses-permission android:name="android.permission.PACKAGE_USAGE_STATS" />
<uses-permission android:name="android.permission.GET_TASKS" />
intent = new Intent(Settings.ACTION_USAGE_ACCESS_SETTINGS);
startActivity(intent);
【讨论】: