在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

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-20 11:58:00  来源:igfitidea点击:

How to open fragment page, when pressed a notification in android

androidandroid-fragmentsandroid-notificationsandroid-pendingintent

提问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 NavigationComponent 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 setComponentNameonly 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 notificationfrom Firebasethis methods runs first

当你notificationFirebase这个方法发送时首先运行

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 datato the SharedPref. Dont be offensive about it., we will remove it later immediately when we use it.

然后你运行上面的sendNotification(..)方法。在这种方法中,我将 设置notification dataSharedPref. 不要冒犯它。,我们稍后会在使用它时立即将其删除。

I used my login dataand set intentto diffrent Activityaccording to my roleID

我使用我的login data并设置intentActivity根据我的不同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 notificationthis 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 ProducerActivityor EventListActivityopens..

例如,您单击通知并打开ProducerActivityEventListActivity打开..

If your Role is Consumer or Volunteer( according to my app roles ) you set the notification datato SharedPref

如果你的角色是消费者或志愿者(根据我的应用程序的角色),您将notification dataSharedPref

   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 datato bundleand open Fragmentwith bundle data. Right after you remove the SharedPrefdata that includes my notification data

所以你把你的datatobundle和 open Fragmentwith 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);

}