Android 4.1: Bagaimana cara memeriksa notifikasi dinonaktifkan untuk aplikasi?

98

Android 4.1 menawarkan pengguna kotak centang untuk menonaktifkan pemberitahuan untuk aplikasi tertentu.

Namun, sebagai pengembang kami tidak memiliki cara untuk mengetahui apakah panggilan untuk memberi tahu itu efektif atau tidak.

Saya benar-benar perlu memeriksa apakah pemberitahuan dinonaktifkan untuk aplikasi saat ini tetapi saya tidak dapat menemukan pengaturan apa pun untuk itu di API.

Apakah ada cara untuk memeriksa pengaturan ini di dalam kode?

Guillaume Perrot
sumber
1
Anda seharusnya tidak menyibukkan diri dengan itu. Anggap saja notifikasi Anda berhasil. Jika pengguna telah secara eksplisit menonaktifkan notifikasi Anda, maka dia mungkin memiliki alasan yang tepat untuk melakukannya, dan aplikasi Anda tidak akan peduli apakah notifikasi itu ditampilkan atau tidak.
Kevin Coppock
Saya menjelaskan alasannya di komentar jawaban pertama.
Guillaume Perrot
1
Berikut adalah masalah untuk membintangi / melacak code.google.com/p/android/issues/detail?id=38482 Benar-benar membutuhkan ini ....
brandall

Jawaban:

147

Anda tidak bisa 100% tidak bisa.

Hal ini ditanyakan dalam video Google I / O 2012 ini dan pimpinan Proyek untuk pemberitahuan baru menyatakan bahwa Anda tidak bisa.


Edit

Pembaruan 2016: Sekarang Anda dapat memeriksanya, seperti yang dikatakan dalam video Google I / O 2016 ini .

Gunakan NotificationManagerCompat.areNotificationsEnabled(), dari pustaka dukungan, untuk memeriksa apakah pemberitahuan diblokir di API 19+. Versi di bawah API 19 akan mengembalikan true (pemberitahuan diaktifkan).

masukkan deskripsi gambar di sini

Blundell
sumber
2
Tidak ada dalam video yang menunjukkan kami tidak dapat membaca pengaturan ini. Hanya untuk memperjelas: Saya hanya ingin dapat membaca status saat ini dari kotak centang, bukan mengubahnya. Saya khawatir Anda tidak memahami pertanyaan saya.
Guillaume Perrot
2
Kami membutuhkan ini karena kami menampilkan 1 pemberitahuan pada satu waktu (yang bisa dalam aplikasi atau di bilah sistem). Jika pemberitahuan sistem ditampilkan, kami tidak menampilkan spanduk dalam aplikasi dan sebaliknya. Jika kami tidak dapat mengetahui apakah pemberitahuan ditampilkan atau tidak, kami tidak dapat mengelola siklus hidupnya lagi. Saya kira kita harus sepenuhnya mengubah cara kita mengelola pemberitahuan sekarang ...
Guillaume Perrot
9
FYI, pertanyaan ditanyakan (dan dijawab) pada pukul 48:05 dalam video (selama Q&A) dengan satu kata pendek ... Tidak. youtube.com/…
Devunwired
2
@Stavros_S memperbarui jawaban dengan tautan lengkap. NotificationManagerCompat.areNotificationsEnabled () .
Sufian
16
@Stavros_S Anda perlu menggunakanNotificationManagerCompat.from(ctx).areNotificationsEnabled()
AlexAndro
38

Sebenarnya ini cukup mudah dilakukan:

/**
 * Created by desgraci on 5/7/15.
*/
public class NotificationsUtils {

    private static final String CHECK_OP_NO_THROW = "checkOpNoThrow";
    private static final String OP_POST_NOTIFICATION = "OP_POST_NOTIFICATION";

    public static boolean isNotificationEnabled(Context context) {

        AppOpsManager mAppOps = (AppOpsManager) context.getSystemService(Context.APP_OPS_SERVICE);

        ApplicationInfo appInfo = context.getApplicationInfo();

        String pkg = context.getApplicationContext().getPackageName();

        int uid = appInfo.uid;

        Class appOpsClass = null; /* Context.APP_OPS_MANAGER */

        try {

            appOpsClass = Class.forName(AppOpsManager.class.getName());

            Method checkOpNoThrowMethod = appOpsClass.getMethod(CHECK_OP_NO_THROW, Integer.TYPE, Integer.TYPE, String.class);

            Field opPostNotificationValue = appOpsClass.getDeclaredField(OP_POST_NOTIFICATION);
            int value = (int)opPostNotificationValue.get(Integer.class);

            return ((int)checkOpNoThrowMethod.invoke(mAppOps,value, uid, pkg) == AppOpsManager.MODE_ALLOWED);

        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        } catch (NoSuchMethodException e) {
            e.printStackTrace();
        } catch (NoSuchFieldException e) {
            e.printStackTrace();
        } catch (InvocationTargetException e) {
            e.printStackTrace();
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        }
        return false;
    }
}
desgraci.dll
sumber
3
Pada saat pertanyaan diposting, Android 4.1 adalah yang terbaru, ini hanya untuk Android 4.4+ dan tampaknya menggunakan refleksi dan dokumentasi tidak menyarankan menggunakannya untuk aplikasi non sistem.
Guillaume Perrot
@GuillaumePerrot sebenarnya, Anda benar tentang refleksi, tetapi sekali lagi, dokumentasi dan pernyataan resmi dari android mengatakan bahwa Anda tidak dapat melakukannya, Anda juga dapat tetap berpegang pada itu. Maaf tentang masalah versi, saya tidak dapat membantu Anda. Jika klien / solusi Anda membutuhkannya, maka Anda mungkin ingin mempertimbangkan untuk meningkatkan sedikit versi yang diperlukan karena SDK yang membatasi Anda pada saat itu. Beri tahu saya jika Anda menemukan cara alternatif.
desgraci
1
Cukup adil tetapi Anda harus menganggap pengembalian benar jika Anda tidak bisa mendapatkan informasi. Setidaknya dalam kasus penggunaan saya, ini lebih masuk akal. Atau gunakan nilai default sebagai parameter dalam fungsi statis agar lebih dapat digunakan kembali.
Guillaume Perrot
1
@Rahul Matte, GlobalContext hanyalah kelas utilitas yang saya gunakan untuk menyimpan referensi ke Konteks, Anda dapat mengirimkan Konteks melalui metode jika Anda tidak menggunakan / atau ingin menggunakan struktur itu. Semoga ini membantu!
desgraci
1
Saya harap mereka tidak: p tetapi berasal dari google XD, karena ini menggunakan refleksi, OP_POST_NOTIFICATION membaca kode di grep setelah menemukan diri saya berjuang dengan masalah yang sama.
desgraci
37

Jawaban dari @blundell benar tetapi ada perubahan kecil di versi yang lebih baru.

NotificationManagerCompat.from(context).areNotificationsEnabled()
Prakash
sumber
5

Jika Anda menggunakan Xamarin dan membutuhkan jawaban ini, Anda dapat menggunakan kode ini:

//return true if this option is not supported.
public class NotificationsUtils 
{
    private const String CHECK_OP_NO_THROW = "checkOpNoThrow";
    private const String OP_POST_NOTIFICATION = "OP_POST_NOTIFICATION";

    public static bool IsNotificationEnabled(global::Android.Content.Context context) {

        AppOpsManager mAppOps = (AppOpsManager) context.GetSystemService(global::Android.Content.Context.AppOpsService);

        ApplicationInfo appInfo = context.ApplicationInfo;

        String pkg = context.ApplicationContext.PackageName;

        int uid = appInfo.Uid;

        try {

            var appOpsClass = Java.Lang.Class.ForName("android.app.AppOpsManager");
            var checkOpNoThrowMethod = appOpsClass.GetMethod(CHECK_OP_NO_THROW,Java.Lang.Integer.Type,Java.Lang.Integer.Type,new Java.Lang.String().Class);//need to add String.Type

            var opPostNotificationValue = appOpsClass.GetDeclaredField (OP_POST_NOTIFICATION);
            var value = (int)opPostNotificationValue.GetInt(Java.Lang.Integer.Type);
            var mode = (int)checkOpNoThrowMethod.Invoke(mAppOps,value, uid, pkg);
            return (mode == (int)AppOpsManagerMode.Allowed);

        } catch (Exception) 
        {
            System.Diagnostics.Debug.WriteLine  ("Notification services is off or not supported");
        } 
        return true;
    }
}
pengguna3030630
sumber
@AdamPedley AreNotificationsEnabled () ditambahkan di API 24 developer.android.com/reference/android/app/…
Sune Kjærgård
Anda benar, pasti salah membaca sebelumnya. Saya menghapus komentar asli saya, agar tidak membingungkan siapa pun.
Adam Pedley
5

Sepertinya tidak ada cara untuk menanyakan status pemberitahuan.

Saya merekomendasikan ini:

  • Rancang aplikasi Anda dengan notifikasi.
  • Izinkan pengguna untuk menonaktifkan pemberitahuan dari pengaturan aplikasi.
  • Periksa apakah pemberitahuan diklik. Jika pengguna mengklik notifikasi, simpan ini ke preferensi.
  • Di aplikasi Anda, jika setelan notifikasi aktif, dan jika pengguna Android 4.1+ (API 16), tetapi jika pengguna tidak mengklik notifikasi selama beberapa hari / minggu, asumsikan bahwa pengguna menonaktifkan notifikasi.

Tidak 100% benar. Tapi ini memberi pendapat.
Misalnya jika pengguna tidak mengklik notifikasi aplikasi apa pun selama 10-15 hari, mungkin dia menonaktifkannya

trante
sumber
1
Ini adalah pendekatan yang sangat luas dan abstrak.
IgorGanapolsky
Ini adalah pendekatan terbaik! Kami melakukan ini di aplikasi kami dan Anda dapat mengatakan dengan tepat, jika notifikasi dinonaktifkan. PendingIndent untuk SETIAP tindakan dan simpan ke preferensi. Jangan lupa untuk mengatur ulang jika smartphone di-restart.
JacksOnF1re
1

Saya menggunakan metode ini untuk memeriksa apakah notifikasi diaktifkan atau tidak, metode yang disebutkan di atas akan berfungsi untuk memeriksa apakah notifikasi diaktifkan atau tidak. Tapi dari Android 8 dan seterusnya untuk membuat notifikasi kita harus membuat channel dulu , jadi dari Oreo, kita harus mengecek apakah channel notifikasi kamu sudah aktif atau belum .

    /**
     * Checking Whether notifications are enabled or not
     * @return true if notifications are enabled otherwise false
     */
    public static final String CHANNEL_ID = your_channel_id";

    private boolean isNotificationChannelEnabled(){
        if(NotificationManagerCompat.from(this).areNotificationsEnabled()) {
            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
                NotificationManager manager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
                NotificationChannel channel = manager.getNotificationChannel(CHANNEL_ID);
                if (channel == null)
                    return true; //channel is not yet created so return boolean
                // by only checking whether notifications enabled or not
                return channel.getImportance() != NotificationManager.IMPORTANCE_NONE;
            }
            return true;
        }
        return false;
    }

sai Pavan Kumar
sumber