有 Java 编程相关的问题?

你可以在下面搜索框中键入要查询的问题!

java生成自定义通知的textView,以便为每个激发的通知记住特定字符串

问题摘要: 我有一个listView,它存储了单词记忆类、NotificationWorker类和NotificationReceiver类中的词汇表,用于处理通知。我的目标是点击listView中的一个项目(例如,一个名为“棒球”的单词),该项目将触发一个时间选择器,我将在其中设置一个特定的时间(例如,5分钟后)来触发通知。通知出现时,应该显示一个标题:“你还记得这个词吗:棒球?”。当我只发出一个通知时,通知会正常工作,但如果我立即为另一个单词(如“apple”)发出第二个通知,第一个和第二个通知的标题都会变成“你还记得这个单词吗:apple?”。我的意思是,当这两个通知出现时,第一个应该是“棒球”,第二个应该是“苹果”。问题是,当我发出第二次通知时,“棒球”已经被替换了

那么,有没有一种方法可以让通知记住它们的具体单词呢

我尝试过的事情: 我尝试为每个通知设置不同的通知id,但没有成功。我想生成一个时间标签,在点击“棒球”(或listView中的任何其他项目)时获取当前系统时间,并让通知管理器将时间标签与“棒球”配对,这样它将是“棒球”的标识符,因此通知可以记住这个词。然而,这远远高于我的编码水平,我不知道如何在代码中实现这一点

以下是我的代码供参考:

单词记忆类

    public class WordsToMemorize extends AppCompatActivity {

        static String vocabularyToBeMemorized;

        Calendar c;
        WorkManager mWorkManager;


        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.words_to_memorize);

            final ListView myVocabularyListview;
            final ArrayAdapter myVocabularyArrayAdapter;


            //findViewById
            myVocabularyListview = findViewById(R.id.my_vocabulary_listview);



            mWorkManager = WorkManager.getInstance();


            //Initialize the adapter
            myVocabularyArrayAdapter = new ArrayAdapter<>(this, 安卓.R.layout.simple_list_item_1, myVocabularyArrayList);
            myVocabularyListview.setAdapter(myVocabularyArrayAdapter);



            /**
             * Let the user click on an item and set notification timings
             */
            myVocabularyListview.setOnItemClickListener(new AdapterView.OnItemClickListener(){

                public void onItemClick(AdapterView<?> parent, View view, final int position, long id) {

                    final String selectedMyVocabularyListviewItemValue=myVocabularyListview.getItemAtPosition(position).toString();

                    AlertDialog.Builder AlertDialog = new AlertDialog.Builder(WordsToMemorize.this);
                    AlertDialog .setTitle(getString(R.string.Choose_the_timing_to_recall_a_word));
                    AlertDialog .setCancelable(false); 
                    AlertDialog .setView(R.layout.custom_alert_dialog_dictionary_providers);

                    //Time Picker Button
                    AlertDialog .setPositiveButton(getString(R.string.Customize_timing), new DialogInterface.OnClickListener() {

                        @Override
                        public void onClick(DialogInterface dialog, int which) {

//I couldn't directly fetch the values of the myVocabularyListview items so I had to pass them to a dummy texView called "wordInputView" and then fetch them from there.
MainActivity.wordInputView.setText(selectedMyVocabularyListviewItemValue);
                            setCustomizedNotificationTiming();
                        }
                    });


                    //Cancel Button
                    AlertDialog .setNegativeButton(R.string.Cancel, new DialogInterface.OnClickListener() {

                        @Override
                        public void onClick(DialogInterface dialog, int which) {
                            dialog.dismiss();
                        }
                    });

                    AlertDialog .create();
                    AlertDialog .show();

                }
            });



        @Override
        protected void onStart() {
            super.onStart();

            c = Calendar.getInstance(); 
        }




        // Helper Method

        public void setCustomizedNotificationTiming() {

            vocabularyToBeMemorized = MainActivity.wordInputView.getText().toString();

            // on Time
            new TimePickerDialog(this,
                    new TimePickerDialog.OnTimeSetListener() {
                        @Override
                        public void onTimeSet(TimePicker view, int hourOfDay,
                                              int minute) {
                            c.set(Calendar.HOUR_OF_DAY, hourOfDay);
                            c.set(Calendar.MINUTE, minute);

                            long nowMillis = System.currentTimeMillis();  
                            long millis = c.getTimeInMillis() - nowMillis; 

                            if (c.before(Calendar.getInstance())) {        
                                Toast.makeText(getApplicationContext(), getString(R.string.Hey_thats_too_early),Toast.LENGTH_LONG).show();

                            } else {                                       
                                SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss", Locale.TAIWAN);
                                Long scheduledDateInMilliSeconds=c.getTimeInMillis();
                                String FormattedScheduledDate = dateFormat.format(scheduledDateInMilliSeconds);
                                Toast.makeText(getApplicationContext(), getString(R.string.Will_send_the_notification_at) + FormattedScheduledDate + getString(R.string.blank_space),Toast.LENGTH_LONG).show();


                                OneTimeWorkRequest UserDefinedNotificationRequest = new OneTimeWorkRequest.Builder(NotificationWorker.class)
                                        .addTag("UserDefinedNotificationTag" + " for " + vocabularyToBeMemorized)
                                        .setInitialDelay(millis, TimeUnit.MILLISECONDS)
                                        .build();
                                mWorkManager.enqueue(UserDefinedNotificationRequest);

                            }

                        }
                    },
                    c.get(Calendar.HOUR_OF_DAY),
                    c.get(Calendar.MINUTE),
                    false).show();

            // on Date
            new DatePickerDialog(this,
                    new DatePickerDialog.OnDateSetListener() {
                        @Override
                        public void onDateSet(DatePicker view, int year,
                                              int monthOfYear, int dayOfMonth) {

                            c.set(Calendar.YEAR, year);
                            c.set(Calendar.MONTH, monthOfYear);
                            c.set(Calendar.DAY_OF_MONTH, dayOfMonth);

                        }
                    },
                    c.get(Calendar.YEAR),
                    c.get(Calendar.MONTH),
                    c.get(Calendar.DAY_OF_MONTH)).show();

        }


    }

通知工人阶级

public class NotificationWorker extends Worker {


    public NotificationWorker(@NonNull Context context, @NonNull WorkerParameters workerParams) {
        super(context, workerParams);
    }

    @NonNull
    @Override
    public Result doWork() {

        showNotification("Hey I'm your worker", "Work is done");

        return Result.success();

    }


    public int createID(){
        Date now = new Date();
        int id = Integer.parseInt(new SimpleDateFormat("ddHHmmssSS",  Locale.TAIWAN).format(now));
        return id;
    }


    private void showNotification(String task, String desc) {

        RemoteViews collapsedNotificationView = new RemoteViews(getApplicationContext().getPackageName(),R.layout.custom_notification_normal_view);
                    collapsedNotificationView.setTextViewText(R.id.normal_notification_title,"Do you Remember this word:" + WordsToMemorize.vocabularyToBeMemorized + "?");
        RemoteViews expandedNotificationView = new RemoteViews(getApplicationContext().getPackageName(),R.layout.custom_notification_expanded_view);
                    expandedNotificationView.setTextViewText(R.id.expanded_notification_title,"Do you Remember this word:" + WordsToMemorize.vocabularyToBeMemorized + "?");

        Intent resultIntent = new Intent(getApplicationContext(), MainActivity.class);

        TaskStackBuilder stackBuilder = TaskStackBuilder.create(getApplicationContext());

        stackBuilder.addParentStack(MainActivity.class);

        stackBuilder.addNextIntent(resultIntent);
        PendingIntent resultPendingIntent =
                stackBuilder.getPendingIntent(
                        0,
                        PendingIntent.FLAG_UPDATE_CURRENT
                );


        Intent broadcastIntent = new Intent(getApplicationContext(), NotificationReceiver.class);
        broadcastIntent.putExtra("vocabularyToBeMemorized", WordsToMemorize.vocabularyToBeMemorized);
        PendingIntent actionIntent = PendingIntent.getBroadcast(getApplicationContext(),
                0, broadcastIntent, PendingIntent.FLAG_UPDATE_CURRENT);


        NotificationManager manager = (NotificationManager) getApplicationContext().getSystemService(Context.NOTIFICATION_SERVICE);


        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {

            NotificationChannel channel = new
                    NotificationChannel("simplfiedcoding", "simplfiedcoding", NotificationManager.IMPORTANCE_DEFAULT);
            manager.createNotificationChannel(channel);
        }

        NotificationCompat.Builder builder = new NotificationCompat.Builder(getApplicationContext(), "simplfiedcoding")
                .setSmallIcon(R.mipmap.ic_launcher)
                .setLights(Color.YELLOW , 1000 , 1000) 
                .setColor(Color.BLUE)
                .setSound(Settings.System.DEFAULT_NOTIFICATION_URI)
                .setPriority(NotificationCompat.PRIORITY_DEFAULT)
                .setAutoCancel(true) 
                .setOnlyAlertOnce(true)
                .setStyle(new NotificationCompat.DecoratedCustomViewStyle())
                .setCustomContentView(collapsedNotificationView)
                .setCustomBigContentView(expandedNotificationView)
                .setContentIntent(resultPendingIntent)
                .addAction(R.mipmap.dictionary,"yes",actionIntent);


        int id = createID();
        manager.notify(id, builder.build());

    }

}

通知接收器类

public class NotificationReceiver extends BroadcastReceiver{

    @Override
    public void onReceive(final Context context, Intent intent) {
        final String vocabularyToBeMemorizedFromNotification = intent.getStringExtra("vocabularyToBeMemorized");

        Intent launchMainActivityIntent = context.getPackageManager().getLaunchIntentForPackage("com.example.安卓.dictionaryalmighty2");
        if (launchMainActivityIntent != null) {
            context.startActivity(launchMainActivityIntent);//null pointer check in case package name was not found
        }


        // This is only for null pointer errors before the app is fully launched and loaded
        Handler handler = new Handler();
        handler.postDelayed(new Runnable() {
            public void run() {

                Intent intent = new Intent(context.getApplicationContext(), ComboSearchActivity.class);
                context.startActivity(intent);


                Handler handler = new Handler();
                handler.postDelayed(new Runnable() {
                    public void run() {


                        // Just plain methods to look up dictionaries
                        loadFirstDefaultDictionaries();
                        loadSecondDefaultDictionaries();
                        loadThirdDefaultDictionaries();

                    }
                }, 1000);

            }
        }, 1000);   //1 second delay

    }

共 (3) 个答案

  1. # 1 楼答案

    我认为这可能确实与通知的ID有关。您可以尝试this solution proposed by @sagar.android

    Simple notification_id needs to be changable.

    Just create random number for notification_id.

    Random random = new Random();
    int m = random.nextInt(9999 - 1000) + 1000; 
    

    or you can use this method for creating random number as told by tieorange (this will never get repeated):

    int m = (int) ((new Date().getTime() / 1000L) % Integer.MAX_VALUE); and replace this line to add parameter for
    

    notification id as to generate random number

    notificationManager.notify(m, notification);
    

    让我知道它是否有效

  2. # 2 楼答案

    正如我在评论中所建议的,您可以使用LinkedList(将用作队列):

    替换

    static String vocabularyToBeMemorized;
    

    用你的话记住课堂上的内容:

    static LinkedList vocabulariesToBeMemorized = new LinkedList<String>(); 
    

    然后,将该值添加到列表中,而不是将静态字符串设置为值:

    vocabulariesToBeMemorized.add(MainActivity.wordInputView.getText().toString());
    

    并简单地替换

    final String vocabularyToBeMemorizedFromNotification = intent.getStringExtra("vocabularyToBeMemorized");
    

    String wordToMemorize = "";
    if (WordsToMemorize.vocabulariesToBeMemorized.peek() != null) {
         wordToMemorize = vocabulariesToBeMemorized.poll();
    }
    

    并在生成器中使用它来设置标题

    builder.setTitle(wordToMemorize);
    

    希望有帮助

    EDIT: please use

    static LinkedList<String> vocabulariesToBeMemorized = new LinkedList<>();

    Also, I actually tried to suggest you to not use any intent.putExtra() or intent.getStringExtra(), but replace it with the static LinkedList that functions as a queue. If you do so, and set the title in your showNotification() method with wordToMemorize, I think it might work.

  3. # 3 楼答案

    我试着为你制作一个小应用程序来证明我的意思。现在,我不确定发布新通知的等待时间可能有多长,例如,如果时间是一周,您可以查看AlarmManager(如建议的here),而不是像我现在这样使用处理程序

    现在,转到应用程序。这是一个至少有两个按钮的工作示例,“蝴蝶”和“棒球”:

    main使用两个按钮进行活动

    public class MainActivity extends AppCompatActivity {
    
        Handler handler;
    
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_main);
    
            final Button baseballBtn = findViewById(R.id.baseball);
            baseballBtn.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View view) {
                    postDelayedNotification(baseballBtn);
                }
            });
    
            final Button butterflyBtn = findViewById(R.id.butterfly);
            butterflyBtn.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View view) {
                    postDelayedNotification(butterflyBtn);
                }
            });
        }
    
        private void postDelayedNotification(Button button) {
            final String message = "Do you remember this word: " + button.getText();
    
            if (handler == null) {
                handler = new Handler();
            }
            handler.postDelayed(new Runnable() {
                @Override
                public void run() {
                    // Do something after 5s = 5000ms
                    MyNotificationManager.showNotification(getApplicationContext(), message);
                }
            }, 3000); // delay for how long you want (you can use the set calendar here)
        }
    }
    

    处理通知的自定义通知管理器:

    class MyNotificationManager {
    
        public static void showNotification(Context applicationContext, String message) {
            NotificationManager manager = (NotificationManager) applicationContext.getSystemService(Context.NOTIFICATION_SERVICE);
    
            if (manager != null) {
                if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
                    NotificationChannel channel = new NotificationChannel("simplfiedcoding", "simplfiedcoding", NotificationManager.IMPORTANCE_DEFAULT);
                    manager.createNotificationChannel(channel);
                }
    
                // In this builder, you could set your actionIntents etc. as you had in your application
                NotificationCompat.Builder builder = new NotificationCompat.Builder(applicationContext, "simplfiedcoding")
                        .setSmallIcon(R.mipmap.ic_launcher)
                        .setContentTitle("New Message")
                        .setContentText(message)
                        .setPriority(NotificationCompat.PRIORITY_DEFAULT);
    
                int uniqueId = (int) ((new Date().getTime() / 1000L) % Integer.MAX_VALUE);
                manager.notify(uniqueId, builder.build());
            }
        }
    
    }
    

    我测试了这个应用程序,它似乎工作得很好