Cách kiểm tra xem AlarmManager đã có bộ báo thức chưa?


182

Khi ứng dụng của tôi bắt đầu, tôi muốn nó kiểm tra xem một báo thức cụ thể (đã đăng ký qua AlarmManager) đã được thiết lập và đang chạy chưa. Kết quả từ google dường như chỉ ra rằng không có cách nào để làm điều này. Điều này vẫn đúng không? Tôi cần thực hiện việc kiểm tra này để tư vấn cho người dùng trước khi thực hiện bất kỳ hành động nào để tạo báo thức mới.

  0

Vui lòng xác nhận câu trả lời rằng giải quyết vấn đề của bạn hoặc gửi giải pháp của riêng bạn. 16 jan. 172017-01-16 22:13:53

-3

Bạn đang nói về đồng hồ báo thức - mà nguồn bạn có thể tải về từ đây - https://android.googlesource.com/platform/packages/apps/AlarmClock

Hoặc bạn đang nói về thiết lập thời gian khi nhiệm vụ nhất định phải được thực hiện - http://developer.android.com/reference/android/app/AlarmManager.html

  0

họ đổi tên thành DeskClock: http://android.git.kernel.org/?p=platform/packages/apps/DeskClock.git;a=summary 29 dec. 102010-12-29 18:41:20

  0

Tôi đang đề cập đến một báo thức được đặt trong mã của tôi bằng cách sử dụng AlarmManager. Tôi không thể tìm thấy bất kỳ phương pháp nào để kiểm tra xem báo thức đã được đặt cho một mục đích cụ thể hay chưa. Vì chương trình cho phép người dùng đặt báo thức và sau đó đóng ứng dụng tôi muốn biết khi nào ứng dụng được mở cho dù báo thức được đặt và đang chạy 'ngoài tầm nhìn'. 29 dec. 102010-12-29 19:41:19

  0

Có vẻ như lớp AlarmManager không cung cấp chức năng như vậy. Tại đây, bạn có thể xem nguồn của AlarmManager - http://grepcode.com/file/repository.grepcode.com/java/ext/com.google.android/android/2.1_r2/android/app/AlarmManager.java Nếu bạn đang thực sự tuyệt vọng, bạn có thể mở rộng nó (hoặc thực hiện lại IAlarmManager) và tạo trình quản lý báo thức của riêng bạn. Quá mức cần thiết. 29 dec. 102010-12-29 20:18:28

  0

Cập nhật: Tôi phát hiện ra từ một chuỗi khác mà sau đây dường như thực hiện công việc: - 30 dec. 102010-12-30 13:27:22

+6

báo động = (AlarmManager) getSystemService (Context.ALARM_SERVICE); \t Chuỗi ALARM_ACTION; ALARM_ACTION = AAAlarmReceiver.ACTION_LOAD_LISTVIEW; Intent intentToFire = new Intent (ALARM_ACTION); boolean alarmUp = (PendingIntent.getBroadcast (cText, 0, intentToFire, PendingIntent.FLAG_NO_CREATE)! = Null); 30 dec. 102010-12-30 13:27:40

  0

Vui lòng chỉ trả lời câu trả lời cụ thể trong câu trả lời của bạn. Nếu bạn muốn đặt câu hỏi hoặc bất kỳ câu hỏi nào khác, hãy giữ nó trong phần bình luận. 01 dec. 172017-12-01 10:39:08

  0

@RahatZaman Bạn đang nói về cái gì? Một trong những triết lý tràn ngăn xếp chính là 'Cung cấp cho một người đàn ông một con cá và bạn nuôi anh ta trong một ngày. Dạy một người đàn ông để câu cá và bạn nuôi sống anh ta suốt đời '. Vì vậy, chỉ ra nguồn của lib là thực tế khá phổ biến ở đây. 05 dec. 172017-12-05 10:06:25


1

Im theo ấn tượng rằng theres không có cách nào để làm điều này, nó sẽ là tốt đẹp mặc dù.

Bạn có thể đạt được kết quả tương tự bằng cách có Alarm_last_set_time được ghi ở đâu đó và có điều Onabo_starter BroadcastReciever: BOOT_COMPLETED.


277

Theo dõi nhận xét được đăng, đây là giải pháp chi tiết. Hãy nói rằng bạn đã đăng ký một báo động lặp đi lặp lại với một ý định cấp phát như thế này:

Intent intent = new Intent("com.my.package.MY_UNIQUE_ACTION"); 
PendingIntent pendingIntent = PendingIntent.getBroadcast(context, 0, 
             intent, PendingIntent.FLAG_UPDATE_CURRENT); 
Calendar calendar = Calendar.getInstance(); 
calendar.setTimeInMillis(System.currentTimeMillis()); 
calendar.add(Calendar.MINUTE, 1); 

AlarmManager alarmManager = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE); 
alarmManager.setRepeating(AlarmManager.RTC_WAKEUP, calendar.getTimeInMillis(), 1000 * 60, pendingIntent); 

Cách bạn sẽ kiểm tra để xem nếu nó đang hoạt động là:

boolean alarmUp = (PendingIntent.getBroadcast(context, 0, 
     new Intent("com.my.package.MY_UNIQUE_ACTION"), 
     PendingIntent.FLAG_NO_CREATE) != null); 

if (alarmUp) 
{ 
    Log.d("myTag", "Alarm is already active"); 
} 

Mấu chốt ở đây là FLAG_NO_CREATE mà như được mô tả trong javadoc: if the described PendingIntent **does not** already exists, then simply return null (thay vì tạo hình mới)

+8

Liệu nó có phải sử dụng Intent chỉ với một Chuỗi hành động không? Tôi đã cố gắng xác định một lớp, Intent mới (context, MyClass.class) nhưng nó dường như không hoạt động. Nó luôn trả về null ngay cả khi báo thức đang chạy. 04 apr. 122012-04-04 08:39:49

+5

toc777, không cần phải là Chuỗi phù hợp với hành động được khai báo trong bộ lọc ý định trong tệp kê khai của bạn.xml 11 apr. 122012-04-11 08:27:24

+4

Chris, Đó là một vấn đề khác gây ra sự cố của tôi. Ý định tôi đã đề cập ở trên thực sự không hoạt động :) 12 apr. 122012-04-12 12:25:50

  0

Một vấn đề tôi đã không được gọi là hủy bỏ trên CẢ alarmManager và pendingIntent. I.E ~ alarmMgr.cancel (alarmIntent); alarmIntent.cancel(); 29 may. 142014-05-29 12:01:21

  0

@ChrisKnight: Điều này sẽ vẫn hoạt động nếu tôi kiểm tra từ một ứng dụng nói app1 nếu báo thức được đặt và chạy trong app2? và đồng thời, báo thức sẽ chết trong khi cập nhật ứng dụng và chúng tôi cần phải đặt lại báo thức lại (đối với trường hợp cập nhật ứng dụng)? 08 jul. 142014-07-08 03:25:46

+1

Luôn trả về TRUE cho biết mục đích đang chờ xử lý đã tồn tại. Ngay cả sau khi gỡ cài đặt ứng dụng và cài đặt lại. Mục đích đang chờ xử lý tồn tại trong bao lâu? 13 aug. 142014-08-13 20:33:24

+30

Lưu ý rằng bạn sẽ cần phải gọi cả hai '' 'alarmManager.cancel (pendingIntent)' '' và '' 'pendingIntent.cancel()' '' để giải pháp này trả về false. 29 sep. 142014-09-29 20:00:44

+1

cho người dùng sử dụng Intent mới (context, YourService.class), bạn có thể sử dụng .setAction ("ACTIONNAME") để xác định hành động theo ý định 28 nov. 142014-11-28 20:11:13

+1

Lifesaver. Xin lưu ý rằng bạn sẽ cần phải tạo chính xác ý định giống như cách bạn đã tạo trước đó, ngoại trừ các cờ. 26 feb. 152015-02-26 10:07:31

+22

Trường hợp không rõ ràng, mã trong câu trả lời này không xác minh rằng mục đích đang chờ xử lý đã được đăng ký với trình quản lý cảnh báo. Mã này chỉ xác minh rằng PendingIntent đã được tạo thông qua getBroadcast với một mục đích tương đương. Bạn có thể chứng minh điều này bằng cách chạy mã alarmUp sau getBroadcast tất cả, nhưng trước tất cả các công cụ quản lý lịch và báo động. Nó sẽ trở lại đúng sự thật. Thực tế này giải thích lý do tại sao bạn phải PendingIntent.cancel để lấy giá trị để quay trở lại false. Nói đúng, điều này không trả lời được câu hỏi. 21 apr. 152015-04-21 21:09:49

+1

Xin lỗi. Tôi muốn hỏi MY_UNIQUE_ACTION là gì? Nó đến từ đâu? 23 jul. 152015-07-23 01:14:26

+1

@LeonardFebrianto tôi nghĩ rằng đó là một câu trả lời dài quá hạn nhưng tôi khá chắc chắn bạn có lý do. Đó chỉ là tên hành động, nó có thể là bất kỳ hành động nào liên quan đến người nhận trong tệp kê khai của bạn 15 dec. 152015-12-15 05:49:51

  0

không hoạt động nếu báo động bị giết bởi 'force stop' vv .. Nó phải được hủy trước khi sử dụng mã này 17 dec. 152015-12-17 13:55:17

+1

Tôi đã cố ý Intent intent = new Intent (ctx, MyReceiver.class); thay vì truyền unique_action và nó hoạt động :) 22 dec. 152015-12-22 11:24:16

  0

ohh cảm ơn công việc của nó! 23 dec. 152015-12-23 03:46:33

+1

mẹo cho người đọc trong tương lai - Hãy chắc chắn rằng bạn không nhầm PendingIntent.getBroadcast (...) với PendingIntent.getService (...) - tự lưu một số rắc rối! :) 18 apr. 162016-04-18 04:33:00

+2

đây là lần đầu tiên tôi thấy câu trả lời được đánh giá cao như vậy. Xem nhận xét của bigh_29. 03 jan. 172017-01-03 20:29:37


7

Tôi có 2 báo thức. Tôi đang sử dụng ý định với các tính năng bổ sung thay vì hành động để xác định các sự kiện:

Intent i = new Intent(context, AppReciever.class); 
i.putExtra("timer", "timer1"); 

có điều là với mục đích bổ sung (và báo thức) sẽ không độc đáo. Vì vậy, để có thể xác định được báo động đang hoạt động hay không, tôi phải xác định diff requestCode -s:

boolean alarmUp = (PendingIntent.getBroadcast(context, MyApp.TIMER_1, i, 
        PendingIntent.FLAG_NO_CREATE) != null); 

và đây là làm thế nào báo động đã được tạo ra:

public static final int TIMER_1 = 1; 
public static final int TIMER_2 = 2; 

PendingIntent pending = PendingIntent.getBroadcast(context, TIMER_1, i, 
      PendingIntent.FLAG_CANCEL_CURRENT); 
setInexactRepeating(AlarmManager.RTC_WAKEUP, 
      cal.getTimeInMillis(), AlarmManager.INTERVAL_DAY, pending); 
pending = PendingIntent.getBroadcast(context, TIMER_2, i, 
      PendingIntent.FLAG_CANCEL_CURRENT); 
setInexactRepeating(AlarmManager.RTC_WAKEUP, 
      cal.getTimeInMillis(), AlarmManager.INTERVAL_DAY, pending); 
  0

Sử dụng mục đích bổ sung và giải pháp này làm việc cho tôi. Chỉ có một thay đổi là tôi đang sử dụng dịch vụ vì vậy tôi đã thay đổi nó thành 'PendingIntent.getService' 27 aug. 162016-08-27 10:07:25


92

Đối với người khác có thể cần điều này, đây là một câu trả lời.

Sử dụng adb shell dumpsys alarm

Bạn có thể biết báo động đã được thiết lập và khi nào họ sẽ báo động và khoảng thời gian. Cũng bao nhiêu lần báo động này đã được gọi.

+4

đây phải là câu trả lời đúng 04 oct. 142014-10-04 22:07:13

+1

Đây là chính xác 09 dec. 142014-12-09 12:43:14

+24

Không thực sự là một câu trả lời có lập trình cho OP, nhưng là một mẹo hay. Rất tốt để biết. 06 may. 152015-05-06 17:38:12

+1

nối thêm grep để lọc danh sách báo thức thường dài: 'adb shell dumpsys alarm | grep <ví dụ: tên gói ứng dụng của bạn> 'Cũng hoạt động trên các Hệ thống Windows mới (Tôi sử dụng Win10) 08 aug. 162016-08-08 10:51:30

+2

grep được thực thi trên thiết bị di động, không phải trên PC của bạn. Vì vậy, nếu grep hoạt động phụ thuộc vào hệ điều hành Android. Điện thoại cũ không đi kèm với grep. 07 mar. 172017-03-07 13:15:26


36

Ví dụ làm việc với người nhận (câu trả lời hàng đầu chỉ là với hành động).

//starting 
AlarmManager alarmManager = (AlarmManager) getActivity().getSystemService(Context.ALARM_SERVICE); 
Intent intent = new Intent(getActivity(), MyReceiver.class); 
intent.setAction(MyReceiver.ACTION_ALARM_RECEIVER);//my custom string action name 
PendingIntent pendingIntent = PendingIntent.getBroadcast(getActivity(), 1001, intent, PendingIntent.FLAG_CANCEL_CURRENT);//used unique ID as 1001 
alarmManager.setRepeating(AlarmManager.RTC_WAKEUP, System.currentTimeMillis(), aroundInterval, pendingIntent);//first start will start asap 

//and stopping 
Intent intent = new Intent(getActivity(), MyReceiver.class);//the same as up 
intent.setAction(MyReceiver.ACTION_ALARM_RECEIVER);//the same as up 
PendingIntent pendingIntent = PendingIntent.getBroadcast(getActivity(), 1001, intent, PendingIntent.FLAG_CANCEL_CURRENT);//the same as up 
alarmManager.cancel(pendingIntent);//important 
pendingIntent.cancel();//important 

//checking if alram is working with pendingIntent 
Intent intent = new Intent(getActivity(), MyReceiver.class);//the same as up 
intent.setAction(MyReceiver.ACTION_ALARM_RECEIVER);//the same as up 
boolean isWorking = (PendingIntent.getBroadcast(getActivity(), 1001, intent, PendingIntent.FLAG_NO_CREATE) != null);//just changed the flag 
Log.d(TAG, "alarm is " + (isWorking ? "" : "not") + " working..."); 

tôi đã mô tả cũng trên tôi blog

+1

Tôi không chắc rằng điều này là đủ. Trong trường hợp PendingIntent được đăng ký với AlarmManager và sau đó bị dừng bởi cả hai phương thức hủy, 'isWorking' ở trên sẽ vẫn đúng. PendingIntent dường như chưa được gỡ bỏ khỏi AlarmManager, và sẽ tiếp tục trả về một cá thể. Làm thế nào để chúng ta có thể biết khi nào báo động đã được bật/tắt? 10 jun. 162016-06-10 07:36:29

  0

Điều này thực sự làm việc hoàn hảo. Những điều cần lưu ý: setAction() và requestCode() cần phải giống hệt nhau trong tất cả getBroadcast() và giá trị của nó gỡ cài đặt ứng dụng khỏi thiết bị của bạn. Điều đó khiến tôi hiểu. Cảm ơn 11 jun. 162016-06-11 10:12:42

  0

Hoạt động tuyệt vời. Cảm ơn! 01 sep. 162016-09-01 12:59:48

  0

Ví dụ hay nhưng tôi sẽ không sử dụng 1001 làm mã yêu cầu riêng tư ở đó. Chỉ cần 0 để làm cho ví dụ rõ ràng hơn. 09 jul. 172017-07-09 08:12:57


29

Note trích dẫn này từ các tài liệu cho người quản lý báo động:

Nếu có đã là một báo động cho Ý định này dự kiến ​​(với sự bình đẳng của hai ý định được xác định bởi Intent.filterEquals), sau đó nó sẽ bị xóa và thay thế bằng cái này.

Đừng bận tâm hỏi liệu báo thức có tồn tại không nếu bạn đang cố gắng quyết định có tạo báo thức hay không. Chỉ cần tạo nó mỗi lần khởi động ứng dụng của bạn. Bạn sẽ thay thế bất kỳ báo thức nào trong quá khứ mà bạn đã định cấu hình.

Bạn cần một cách tiếp cận khác nếu bạn đang cố gắng tính toán thời gian còn lại trên báo thức đã tạo trước đó, hoặc nếu bạn thực sự cần biết liệu báo thức đó có tồn tại hay không. Để trả lời các câu hỏi đó, hãy cân nhắc lưu dữ liệu đã được chia sẻ vào lúc bạn tạo báo thức. Bạn có thể lưu dấu thời gian đồng hồ tại thời điểm báo thức được đặt, thời gian bạn mong đợi báo thức sẽ tắt và thời gian lặp lại (nếu bạn cài đặt báo thức lặp lại).

  0

Theo tôi, đây là câu trả lời được chấp nhận. Trừ khi OP có tình huống đặc biệt để biện minh cho việc không đặt lại báo động 19 may. 162016-05-19 16:11:12

  0

Trong trường hợp của tôi, tôi muốn biết liệu báo thức đã được cài đặt chưa và nếu tôi không muốn tạo báo thức mới hoặc đặt lại báo thức hiện có. 21 jul. 172017-07-21 14:00:12


3

Tôi đã tạo một tập lệnh bash đơn giản (ngu ngốc hoặc không), trích xuất các thời gian từ vỏ adb, chuyển đổi chúng thành dấu thời gian và hiển thị màu đỏ.

echo "Please set a search filter" 
read search 

adb shell dumpsys alarm | grep $search | (while read i; do echo $i; _DT=$(echo $i | grep -Eo 'when\s+([0-9]{10})' | tr -d '[[:alpha:][:space:]]'); if [ $_DT ]; then echo -e "\e[31m$(date -d @$_DT)\e[0m"; fi; done;) 

thử nó;)


2
Intent intent = new Intent("com.my.package.MY_UNIQUE_ACTION"); 
      PendingIntent pendingIntent = PendingIntent.getBroadcast(
        sqlitewraper.context, 0, intent, 
        PendingIntent.FLAG_NO_CREATE); 

FLAG_NO_CREATE không được tạo cấp phát ý định để nó mang lại giá trị boolean false.

  boolean alarmUp = (PendingIntent.getBroadcast(sqlitewraper.context, 0, 
        new Intent("com.my.package.MY_UNIQUE_ACTION"), 
        PendingIntent.FLAG_NO_CREATE) != null); 

      if (alarmUp) { 
       System.out.print("k"); 

      } 

      AlarmManager alarmManager = (AlarmManager) sqlitewraper.context 
        .getSystemService(Context.ALARM_SERVICE); 
      alarmManager.setRepeating(AlarmManager.RTC_WAKEUP, 
        System.currentTimeMillis(), 1000 * 60, pendingIntent); 

Sau khi bộ kiểm tra cảnh báo kiểm tra giá trị của mục đích đang chờ nó thực hiện đúng vì Cập nhật báo động.

  boolean alarmUp1 = (PendingIntent.getBroadcast(sqlitewraper.context, 0, 
        new Intent("com.my.package.MY_UNIQUE_ACTION"), 
        PendingIntent.FLAG_UPDATE_CURRENT) != null); 
      if (alarmUp1) { 
       System.out.print("k"); 

      } 

5

Chỉ cần tìm thấy một giải pháp khác, có vẻ như để làm việc cho tôi

Intent myIntent = new Intent(MainActivity.this, MyReceiver.class); 

boolean isWorking = (PendingIntent.getBroadcast(MainActivity.this, 0, myIntent, PendingIntent.FLAG_NO_CREATE) != null); 
if (isWorking) {Log.d("alarm", "is working");} else {Log.d("alarm", "is not working");} 

if(!isWorking) { 
    pendingIntent = PendingIntent.getBroadcast(MainActivity.this, 0, myIntent, PendingIntent.FLAG_UPDATE_CURRENT); 
    alarmManager = (AlarmManager) getSystemService(ALARM_SERVICE); 
    int timeNotif = 5 * 60 * 1000;//time in ms, 7*24*60*60*1000 for 1 week 
    Log.d("Notif", "Notification every (ms): " + timeNotif); 
    alarmManager.setRepeating(AlarmManager.RTC_WAKEUP, calendar.getTimeInMillis(), timeNotif, pendingIntent); 
    } 
  0

Đôi khi, trên Marshmallow, sau khi bạn buộc dừng một ứng dụng, getBroadcast() sẽ trả về không null, nhưng báo thức không được thiết lập. 15 feb. 182018-02-15 20:14:10