在android中按下通知时如何打开片段页面
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/26608627/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
How to open fragment page, when pressed a notification in android
提问by Venkat Ramarao Potlapalli
I am trying to open a fragment when I press a notification in the notification bar. My app structure is:
当我按下通知栏中的通知时,我试图打开一个片段。我的应用程序结构是:
- a base activity with a nav drawer menu
some fragment that are opened from menu
b.setOnClickListener(new OnClickListener() { @SuppressWarnings({ "deprecation", "static-access" }) public void onClick(View v) { w_nm=(NotificationManager) getActivity().getSystemService(getActivity().NOTIFICATION_SERVICE); Notification notify=new Notification(R.drawable.notnificationlogo,waternoti,System.currentTimeMillis()); Intent notificationIntent = new Intent(getActivity(), Abc.class); PendingIntent pending=PendingIntent.getActivity(getActivity(), 0,notificationIntent, 0); notificationIntent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP | Intent.FLAG_ACTIVITY_SINGLE_TOP ); notify.flags = Notification.DEFAULT_LIGHTS | Notification.FLAG_AUTO_CANCEL; notify.setLatestEventInfo(getActivity(),waternoti,waternoti1, pending); w_nm.notify(0, notify);
- 带有导航抽屉菜单的基本活动
从菜单中打开的一些片段
b.setOnClickListener(new OnClickListener() { @SuppressWarnings({ "deprecation", "static-access" }) public void onClick(View v) { w_nm=(NotificationManager) getActivity().getSystemService(getActivity().NOTIFICATION_SERVICE); Notification notify=new Notification(R.drawable.notnificationlogo,waternoti,System.currentTimeMillis()); Intent notificationIntent = new Intent(getActivity(), Abc.class); PendingIntent pending=PendingIntent.getActivity(getActivity(), 0,notificationIntent, 0); notificationIntent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP | Intent.FLAG_ACTIVITY_SINGLE_TOP ); notify.flags = Notification.DEFAULT_LIGHTS | Notification.FLAG_AUTO_CANCEL; notify.setLatestEventInfo(getActivity(),waternoti,waternoti1, pending); w_nm.notify(0, notify);
Can anyone tell me how to link with next fragment page (the present code is in class that extends fragment)
谁能告诉我如何链接下一个片段页面(当前代码在扩展片段的类中)
回答by Vito
You will need to start your base activity as usual, but add some extra info to the intent about what menu fragment will be opened. Here you can see how it can be done: https://stackoverflow.com/a/8610916/1652236
您将需要像往常一样开始您的基本活动,但在意图中添加一些关于将打开哪个菜单片段的额外信息。在这里你可以看到它是如何完成的:https: //stackoverflow.com/a/8610916/1652236
This depends on the extra information which you retrieve in the activities 'onCreate()' method in which you will use to start/load the fragment.
这取决于您在活动“onCreate()”方法中检索的额外信息,您将使用该方法启动/加载片段。
See here for example how work with fragments: http://www.tutorialspoint.com/android/android_fragments.htmhttp://developer.android.com/guide/components/fragments.html
请参见此处的示例,例如如何使用片段:http: //www.tutorialspoint.com/android/android_fragments.htm http://developer.android.com/guide/components/fragments.html
It Intent to launch this procedure will be something like:
启动此程序的意图将类似于:
Intent notificationIntent = new Intent(getActivity(), Abc.class);
notificationIntent.putExtra("menuFragment", "favoritesMenuItem");
and in your base activity:
并在您的基本活动中:
@Override
protected void onCreate(final Bundle savedInstanceState)
{
String menuFragment = getIntent().getStringExtra("menuFragment");
FragmentManager fragmentManager = getFragmentManager();
FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction();
// If menuFragment is defined, then this activity was launched with a fragment selection
if (menuFragment != null) {
// Here we can decide what do to -- perhaps load other parameters from the intent extras such as IDs, etc
if (menuFragment.equals("favoritesMenuItem")) {
FavoritesFragment favoritesFragment = new FavoritesFragment();
fragmentTransaction.replace(android.R.id.content, favoritesFragment);
}
} else {
// Activity was not launched with a menuFragment selected -- continue as if this activity was opened from a launcher (for example)
StandardFragment standardFragment = new StandardFragment();
fragmentTransaction.replace(android.R.id.content, standardFragment);
}
}
回答by arsent
Welcome to 2019 and Navigation Component :)
欢迎来到 2019 和导航组件:)
If you are using Navigation
Component you can open a specific destination using NavDeepLinkBuilder
:
如果您使用的是Navigation
组件,您可以使用NavDeepLinkBuilder
以下命令打开特定目的地:
val pendingIntent = NavDeepLinkBuilder(context)
.setComponentName(MainActivity::class.java)
.setGraph(R.navigation.nav_graph)
.setDestination(R.id.destination)
.setArguments(bundle)
.createPendingIntent()
...
notificationBuilder.setContentIntent(pendingIntent)
...
Please note that it's important to use setComponentName
only if your destination isn't in the launcher activity.
请注意,setComponentName
仅当您的目的地不在启动器活动中时才使用它很重要。
回答by gustavo
notificationIntent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP
| Intent.FLAG_ACTIVITY_SINGLE_TOP )
As your intent set Flags: FLAG_ACTIVITY_SINGLE_TOP, "onCreate()" will not be called when the activity has been created, you should receive the params in the method called "onNewIntent()" instead.
由于您的意图设置了 Flags: FLAG_ACTIVITY_SINGLE_TOP,因此在创建活动时不会调用“onCreate()”,您应该在名为“onNewIntent()”的方法中接收参数。
回答by Jishant
you should also add .commit();and ft1.addToBackStack(null);so that it would not overlap on prevoius one and if you will not ad this ft1.addToBackStack(null);on back your app will exit so add this according to your functionality
你还应该添加.commit(); 和ft1.addToBackStack(null); 这样它就不会与上一个重叠,如果您不添加此ft1.addToBackStack(null); 在后面,您的应用程序将退出,因此请根据您的功能添加它
String menuFragment = getIntent().getStringExtra("menuFragment");
ft1 = getSupportFragmentManager().beginTransaction();
ft1.addToBackStack(null);
ft1.replace(R.id.frame_container, favoritesFragment).commit();
回答by fthopkins
It is a detailed answer and i believe if you follow it carefully. You will solve your problem.
这是一个详细的答案,我相信如果您仔细遵循它。你会解决你的问题。
When you send the notification
from Firebase
this methods runs first
当你notification
从Firebase
这个方法发送时首先运行
public class FirebaseMessageService extends FirebaseMessagingService {
private static final String TAG = "MyFirebaseMsgService";
Map<String, String> data;
// [START receive_message]
@Override
public void onMessageReceived(RemoteMessage remoteMessage) {
if (remoteMessage.getData().size() > 0) {
removeUserInfoByKeyAsStatic(getApplicationContext(), USER_KNOW_CREATED_EVENT_NOTIFICATION_DATA);
Log.d(TAG, "Message data payload: " + remoteMessage.getData());
data = remoteMessage.getData();
HashMap<String, String> copyData = new HashMap<>(data);
//Calling method to generate notification
sendNotification(data.get("body"), data.get("title"), copyData);
}
}
then you run the above sendNotification(..)
method. In this method i set the notification data
to the SharedPref
. Dont be offensive about it., we will remove it later immediately when we use it.
然后你运行上面的sendNotification(..)
方法。在这种方法中,我将 设置notification data
为SharedPref
. 不要冒犯它。,我们稍后会在使用它时立即将其删除。
I used my login data
and set intent
to diffrent Activity
according to my roleID
我使用我的login data
并设置intent
为Activity
根据我的不同roleID
private void sendNotification(String messageBody, String messageTitle, HashMap<String, String> data) {
// this methods checks my notification data is null ? isNullOrEmptyExt : "simple java is null control method"
if (!isNullOrEmptyExt(data.get("data"))) {
Intent intent;
final User myInfos = getMyInfos(getApplicationContext()); // this gives me login user data.
boolean isConsumerOrVolunteer = myInfos.getRoleID() == Constants.ROLES.CONSUMER || myInfos.getRoleID() == Constants.ROLES.VOLUNTEER;
// I want to show here. You can select diffrent Activity with your data..
if (isConsumerOrVolunteer) {
// this set my notification data to SharedPref
setUserInfoByKeyAsStatic(getApplicationContext(), USER_KNOW_CREATED_EVENT_NOTIFICATION_DATA, data.get("data"));
intent = new Intent(this, EventListActivity.class);
} else {
intent = new Intent(this, ProducerActivity.class);
}
// after from here are the generally same. tricks above
intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
PendingIntent pendingIntent = PendingIntent.getActivity(this, 0 /* Request code */, intent,
PendingIntent.FLAG_ONE_SHOT);
String channelId = getString(R.string.default_notification_channel_id);
Uri defaultSoundUri = RingtoneManager.getDefaultUri(RingtoneManager.TYPE_NOTIFICATION);
NotificationCompat.Builder notificationBuilder =
new NotificationCompat.Builder(this, channelId)
.setSmallIcon(R.mipmap.ic_launcher)
.setContentTitle(messageTitle)
.setContentText(messageBody)
.setAutoCancel(true)
.setSound(defaultSoundUri)
.setContentIntent(pendingIntent);
NotificationManager notificationManager =
(NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
// Since android Oreo notification channel is needed.
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
NotificationChannel channel = new NotificationChannel(channelId,
"Channel human readable title",
NotificationManager.IMPORTANCE_DEFAULT);
notificationManager.createNotificationChannel(channel);
}
notificationManager.notify(0 /* ID of notification */, notificationBuilder.build());
}
}
When you send notification
this above two methods runs. So after that you will click the notificationon your phone.. right.. This click operation opens the Intent(ActivityName)
that you set before in sendNotification(..)
method.
当您发送notification
上述两种方法时,将运行。所以之后你会点击手机上的通知..对..这个点击操作会打开Intent(ActivityName)
你之前设置的sendNotification(..)
方法。
E.g you click the notificationand your ProducerActivity
or EventListActivity
opens..
例如,您单击通知并打开ProducerActivity
或EventListActivity
打开..
If your Role is Consumer or Volunteer( according to my app roles ) you set the notification data
to SharedPref
如果你的角色是消费者或志愿者(根据我的应用程序的角色),您将notification data
到SharedPref
boolean isConsumerOrVolunteer = myInfos.getRoleID() == Constants.ROLES.CONSUMER || myInfos.getRoleID() == Constants.ROLES.VOLUNTEER;
// I want to show here. You can select diffrent Activity with your data..
if (isConsumerOrVolunteer) {
// this set my notification data to SharedPref
setUserInfoByKeyAsStatic(getApplicationContext(), USER_KNOW_CREATED_EVENT_NOTIFICATION_DATA, data.get("data"));
intent = new Intent(this, EventListActivity.class);
} else {
intent = new Intent(this, ProducerActivity.class);
}
So you opened the EventListActivity
. Lets see what will we do in EventListActivity
所以你打开了EventListActivity
. 让我们看看我们会做什么EventListActivity
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_event_list_main);
GsonBuilder gsonBuilder = new GsonBuilder();
gson = gsonBuilder.create();
// this gives me data from `SharePref`
String notificationEventDataString = getUserInfoByKeyAsStatic(this, USER_KNOW_CREATED_EVENT_NOTIFICATION_DATA);
// then check the datastring that comes from SharedPref - simple java null check method
if(!isNullOrEmptyExt(notificationEventDataString)){
Bundle bundle = new Bundle();
bundle.putParcelable(EVENT, gson.fromJson(notificationEventDataString, Event.class));
removeUserInfoByKeyAsStatic(this, USER_KNOW_CREATED_EVENT_NOTIFICATION_DATA);
openFragmentWithoutAnimation(this, R.id.drawer_layout, bundle, EventPreviewFragment.class, EVENT_PREVIEW_FRAGMENT);
}
You get the data from SharedPref
. This will not be empty because when you get the notficationwe already set it in sendNotification(..)
method .
您从SharedPref
. 这不会是空的,因为当您收到通知时,我们已经在sendNotification(..)
method 中设置了它。
So you put your data
to bundle
and open Fragment
with bundle data
. Right after you remove the SharedPref
data that includes my notification data
所以你把你的data
tobundle
和 open Fragment
with bundle data
。在您删除SharedPref
包含我的数据后notification data
I'm ALSO SHARING MY CUSTOM METHODS WITH YOU
我也在与你分享我的自定义方法
This one is fragment open method
这是片段打开方法
public static void openFragmentWithoutAnimation(Context context, int replaceLayout, Bundle bundle, Class<?> fragment, String fragmentTag) {
Fragment dynamicFragment = null;
try {
Class<?> clazz = Class.forName(fragment.getName());
dynamicFragment = (Fragment) clazz.newInstance();
System.out.println(clazz.getSuperclass());
System.out.println(clazz.getName());
} catch (ClassNotFoundException e) {
e.printStackTrace();
} catch (InstantiationException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
}
AppCompatActivity activity = null;
if (context instanceof AppCompatActivity) {
activity = ((AppCompatActivity) context);
}
if (activity.getSupportFragmentManager().findFragmentByTag(fragmentTag) == null) {
FragmentTransaction transaction = activity.getSupportFragmentManager().beginTransaction();
if (bundle != null) {
dynamicFragment.setArguments(bundle);
}
transaction.add(replaceLayout, dynamicFragment, fragmentTag);
transaction.addToBackStack(fragmentTag);
transaction.commit();
}
}
These are SharedPref set and get methods
这些是 SharedPref set 和 get 方法
public static void setUserInfoByKeyAsStatic(Context context, String key, String value){
final SharedPreferences prefs = context.getSharedPreferences(
USER_INFO_PREFS_KEY, Context.MODE_PRIVATE);// Saved token can be accessed only from this app or other apps that shared same id with this app.
SharedPreferences.Editor editor = prefs.edit();
editor.putString(key, value);
editor.apply();
}
public static String getUserInfoByKeyAsStatic(Context context, String key){
final SharedPreferences controlPrefs = context.getSharedPreferences(
USER_INFO_PREFS_KEY, Context.MODE_PRIVATE);
return controlPrefs.getString(key,null);
}
And theese are the null check methods
这些是空检查方法
public static boolean isNullOrEmpty(String value){
if(value == null){
return true;
}else return value.isEmpty() || value.equals("null");
}
public static boolean isNullOrEmptyExt(String value){
if(value == null){
return true;
}else return value.isEmpty() || value.equals("null") || value.equals(JSON_ARRAY_EMPTY) || value.equals(JSON_OBJECT_EMPTY);
}