จะ startForeground () โดยไม่แสดงการแจ้งเตือนได้อย่างไร?


90

ฉันต้องการสร้างบริการและให้มันทำงานในส่วนหน้า

โค้ดตัวอย่างส่วนใหญ่มีการแจ้งเตือนอยู่ แต่ฉันไม่ต้องการแสดงการแจ้งเตือนใด ๆ เป็นไปได้หรือไม่

ช่วยยกตัวอย่างหน่อยได้ไหม มีทางเลือกอื่นหรือไม่?

บริการแอพของฉันกำลังทำมีเดียเพลเยอร์ วิธีทำให้ระบบไม่ฆ่าบริการของฉันยกเว้นแอพจะฆ่ามันเอง (เช่นหยุดชั่วคราวหรือหยุดเพลงทีละปุ่ม)


11
คุณไม่สามารถมีบริการ "เบื้องหน้า" โดยไม่มีการแจ้งเตือน ระยะเวลา
Jug6ernaut

1
แล้วการแจ้งเตือน "ปลอม" ล่ะ? นั่นคือเคล็ดลับ?
Muhammad Resna Rizki Pratama

เมื่อการแจ้งเตือนเบื้องหน้าคือการติดตั้งคุณสามารถลบ "ทำงานในการแจ้งเตือนพื้นหลัง" โดยใช้แอพพลิเคยาง
Laurent

1
@MuhammadResnaRizkiPratama คุณจะพิจารณาเปลี่ยนคำตอบที่ยอมรับหรือไม่ คำถามนี้ได้รับความนิยมอย่างมาก แต่คำตอบที่ได้รับการยอมรับนั้นล้าสมัยโดยสิ้นเชิงหนักเกินไปและตั้งสมมติฐานว่าทำไมนักพัฒนาจึงต้องการสิ่งนี้ ฉันขอแนะนำคำตอบนี้เนื่องจากเชื่อถือได้ไม่ใช้ประโยชน์จากข้อบกพร่องของระบบปฏิบัติการและใช้ได้กับอุปกรณ์ Android ส่วนใหญ่
แซม

คำตอบ:


95

ในฐานะคุณลักษณะด้านความปลอดภัยของแพลตฟอร์ม Android คุณไม่สามารถมีบริการเบื้องหน้าได้โดยไม่ต้องแจ้งเตือนไม่ว่าในกรณีใด ๆ เนื่องจากบริการเบื้องหน้าใช้ทรัพยากรเป็นจำนวนมากและอยู่ภายใต้ข้อ จำกัด ของการจัดตารางเวลาที่แตกต่างกัน (กล่าวคือไม่ได้รับการฆ่าอย่างรวดเร็ว) กว่าบริการพื้นหลังและผู้ใช้จำเป็นต้องรู้ว่าอะไรที่อาจกินแบตเตอรี่ ดังนั้นอย่าทำเช่นนี้

อย่างไรก็ตามมีความเป็นไปได้ที่จะมีการแจ้งเตือน "ปลอม" กล่าวคือคุณสามารถสร้างไอคอนการแจ้งเตือนแบบโปร่งใส (iirc) ได้ สิ่งนี้ไม่เป็นประโยชน์ต่อผู้ใช้ของคุณอย่างมากและคุณไม่มีเหตุผลที่จะทำเช่นนั้นนอกจากการฆ่าแบตเตอรีและสร้างมัลแวร์


3
ขอบคุณ. นั่นทำให้ฉันชัดเจนว่าทำไม setForeground จึงต้องการการแจ้งเตือน
Muhammad Resna Rizki Pratama

21
ดูเหมือนว่าคุณมีเหตุผลที่จะทำผู้ใช้ถามหา แม้ว่าอาจจะดูไม่เด่นชัดอย่างที่คุณพูด แต่ก็มีการร้องขอผลิตภัณฑ์ที่ฉันกำลังดำเนินการโดยกลุ่มทดสอบ บางที Android ควรมีตัวเลือกในการซ่อนการแจ้งเตือนจากบริการบางอย่างที่คุณทราบว่าทำงานอยู่ตลอดเวลา มิฉะนั้นแถบการแจ้งเตือนของคุณจะดูเหมือนต้นคริสต์มาส
Radu

3
@Radu จริงๆแล้วคุณไม่ควรมีแอพมากมายขนาดนั้นอยู่ข้างหน้านั่นจะทำให้อายุการใช้งานแบตเตอรี่ของคุณหมดไปเพราะพวกมันมีกำหนดการแตกต่างกัน (โดยพื้นฐานแล้วพวกมันจะไม่ตาย) สิ่งนี้อาจเป็นที่ยอมรับสำหรับตัวดัดแปลง แต่ฉันไม่เห็นตัวเลือกนั้นที่ทำให้มันกลายเป็นวานิลลา Android ในเร็ว ๆ นี้ "ผู้ใช้" มักไม่รู้ว่าอะไรดีที่สุดสำหรับพวกเขา ..
Kristopher Micinski

2
@Radu ที่ไม่สนับสนุนการโต้แย้งของคุณ "แอปที่ได้รับรางวัล" มักเป็นแอปที่ "แก้ไข" ช่องโหว่ของ Android ผ่านความไม่สอดคล้องกันของระบบ (เช่นตัวฆ่างาน) ไม่มีเหตุผลที่คุณควรต้องใช้บริการเบื้องหน้าเพียงเพราะ "แอปที่ได้รับรางวัล" ทำ: หากคุณยอมรับว่ากำลังจะฆ่าแบตเตอรี่ของผู้ใช้
Kristopher Micinski

2
เห็นได้ชัดว่าวิธีนี้จะใช้ไม่ได้อีกต่อไปโดยเริ่มใน 4.3 plus.google.com/u/0/105051985738280261832/posts/MTinJWdNL8t
erbi

79

อัปเดต:นี่ได้รับการ "แก้ไข" บน Android 7.1 https://code.google.com/p/android/issues/detail?id=213309

ตั้งแต่การอัปเดต 4.3 โดยพื้นฐานแล้วเป็นไปไม่ได้เลยที่จะเริ่มบริการstartForeground()โดยไม่ต้องแสดงการแจ้งเตือน

อย่างไรก็ตามคุณสามารถซ่อนไอคอนโดยใช้ API อย่างเป็นทางการ ... ไม่จำเป็นต้องมีไอคอนโปร่งใส: (ใช้NotificationCompatเพื่อรองรับเวอร์ชันเก่ากว่า)

NotificationCompat.Builder builder = new NotificationCompat.Builder(context);
builder.setPriority(Notification.PRIORITY_MIN);

ฉันได้สร้างสันติภาพกับความจริงที่ว่าการแจ้งเตือนนั้นยังคงต้องอยู่ที่นั่น แต่สำหรับใครก็ตามที่ยังต้องการซ่อนมันฉันอาจพบวิธีแก้ปัญหานี้เช่นกัน:

  1. เริ่มบริการปลอมstartForeground()ด้วยการแจ้งเตือนและทุกอย่าง
  2. เริ่มบริการจริงที่คุณต้องการเรียกใช้ด้วยstartForeground()(ID การแจ้งเตือนเดียวกัน)
  3. หยุดบริการแรก (ปลอม) (คุณสามารถโทรstopSelf()และในการโทร onDestroy stopForeground(true))

โวล่า! ไม่มีการแจ้งเตือนใด ๆ และบริการที่สองของคุณยังคงทำงานต่อไป


23
ขอบคุณสำหรับสิ่งนี้. ฉันคิดว่าบางคนไม่ทราบว่ามีการพัฒนา Android ที่ดำเนินต่อไปเพื่อใช้ในธุรกิจภายใน (นั่นคือไม่ได้ตั้งใจที่จะปรากฏในตลาดหรือขายให้กับ Joe Blow) บางครั้งผู้คนถามหาสิ่งต่างๆเช่น "หยุดแสดงการแจ้งเตือนบริการ" และเป็นการดีที่จะดูวิธีแก้ปัญหาแม้ว่าจะไม่ใช่โคเชอร์สำหรับการบริโภคทั่วไปก็ตาม
JamieB

5
@JamieB ฉันไม่เห็นด้วยมากกว่านี้ ... ฉันแนะนำให้ Dianne Hackborn พวกเขาต้องทบทวนแนวคิดทั้งหมดของบริการพื้นหลังและอาจเพิ่มการอนุญาตให้เรียกใช้บริการในพื้นหลังโดยไม่มีการแจ้งเตือน มันไม่สำคัญกับเราสำหรับนักพัฒนาหากมีการแจ้งเตือนหรือไม่ - USER ขอให้ลบออก :) อย่างไรก็ตามคุณสามารถตรวจสอบได้ว่าใช้ได้กับคุณเช่นกันหรือไม่?
Lior Iluz

1
@JamieB user875707 แจ้งว่าให้ตั้งค่าพารามิเตอร์ไอคอน (รหัสทรัพยากรของไอคอน) เป็น 0 ไม่ใช่รหัสการแจ้งเตือน (หากเป็นเช่นนั้นตามที่เอกสารระบุว่า "startForeground" จะไม่ทำงาน)
wangqi060934

9
แน่นอนคุณควรคิดว่าสิ่งนี้จะใช้ไม่ได้กับแพลตฟอร์มเวอร์ชันอนาคต
hackbod

1
@JamieB ฉันทดสอบสิ่งนี้จริงตอนนี้บน Android 5.0.1 และยังใช้งานได้
Lior Iluz

20

นี้ไม่ได้ทำงานเป็นของ Android 7.1 และมันอาจละเมิดนโยบายนักพัฒนาของ Google Play

แต่มีการแจ้งเตือนบล็อกผู้ใช้บริการ


นี่คือการดำเนินงานของฉันของเทคนิคในคำตอบโดยLior Iluz

รหัส

ForegroundService.java

public class ForegroundService extends Service {

    static ForegroundService instance;

    @Override
    public void onCreate() {
        super.onCreate();

        instance = this;

        if (startService(new Intent(this, ForegroundEnablingService.class)) == null)
            throw new RuntimeException("Couldn't find " + ForegroundEnablingService.class.getSimpleName());
    }

    @Override
    public void onDestroy() {
        super.onDestroy();

        instance = null;
    }

    @Override
    public IBinder onBind(Intent intent) {
        return null;
    }

}

ForegroundEnablingService.java

public class ForegroundEnablingService extends Service {

    @Override
    public int onStartCommand(Intent intent, int flags, int startId) {
        if (ForegroundService.instance == null)
            throw new RuntimeException(ForegroundService.class.getSimpleName() + " not running");

        //Set both services to foreground using the same notification id, resulting in just one notification
        startForeground(ForegroundService.instance);
        startForeground(this);

        //Cancel this service's notification, resulting in zero notifications
        stopForeground(true);

        //Stop this service so we don't waste RAM.
        //Must only be called *after* doing the work or the notification won't be hidden.
        stopSelf();

        return START_NOT_STICKY;
    }

    private static final int NOTIFICATION_ID = 10;

    private static void startForeground(Service service) {
        Notification notification = new Notification.Builder(service).getNotification();
        service.startForeground(NOTIFICATION_ID, notification);
    }

    @Override
    public IBinder onBind(Intent intent) {
        return null;
    }

}

AndroidManifest.xml

<service android:name=".ForegroundEnablingService" />
<service android:name=".ForegroundService" />

ความเข้ากันได้

ผ่านการทดสอบและทำงานบน:

  • Emulator อย่างเป็นทางการ
    • 4.0.2
    • 4.1.2
    • 4.2.2
    • 4.3.1
    • 4.4.2
    • 5.0.2
    • 5.1.1
    • 6.0
    • 7.0
  • Sony Xperia M
    • 4.1.2
    • 4.3
  • ซัมซุงกาแล็กซี ?
    • 4.4.2
    • 5.X
  • Genymotion
    • 5.0
    • 6.0
  • CyanogenMod
    • 5.1.1

ไม่ทำงานเหมือน Android 7.1 อีกต่อไป


2
ยังไม่ได้ทดสอบ แต่อย่างน้อยก็น่าจะได้รับอนุญาต !!! +1 สำหรับส่วน "ถึง Google" ผู้ใช้ของฉันบ่นเกี่ยวกับการแจ้งเตือนที่จำเป็นเพื่อให้แอปทำงานในพื้นหลังฉันยังบ่นเกี่ยวกับการแจ้งเตือนที่จำเป็นสำหรับ skype / llama และแอปอื่น ๆ อีกด้วย
Rami Dabain

ขออภัยที่สามารถใช้ตัวอย่างนี้เพื่อฟังสัญญาณเตือนได้ ฉันกำลังพัฒนาแอพที่ตั้งปลุกด้วย alarmManager และปัญหาที่ฉันมีคือเมื่อฉันปิดแอพ (แอพล่าสุด -> ล้าง) สัญญาณเตือนทั้งหมดจะถูกลบออกไปด้วยและฉันกำลังติดตามหาวิธีป้องกันสิ่งนี้
Ares91

@ Ares91 ลองตั้งคำถาม StackOverflow แยกต่างหากและอย่าลืมใส่ข้อมูลให้มากที่สุดรวมถึงรหัสที่เกี่ยวข้องด้วย ฉันไม่รู้เรื่องสัญญาณเตือนมากนักและคำถามนี้เกี่ยวกับบริการเท่านั้น
แซม

@Sam ควรเรียกใช้บริการใดก่อน ForegroundEnablingService หรือ Forground
Kamran Majeed

@AndroidManForegroundService
Sam

14

คุณสามารถใช้สิ่งนี้ (ตามที่แนะนำโดย @Kristopher Micinski):

Notification note = new Notification( 0, null, System.currentTimeMillis() );
note.flags |= Notification.FLAG_NO_CLEAR;
startForeground( 42, note );

อัพเดท:

โปรดทราบว่าสิ่งนี้ไม่ได้รับอนุญาตอีกต่อไปกับรุ่น Android KitKat + และโปรดทราบว่านี่เป็นการละเมิดหลักการออกแบบใน Android ไม่มากก็น้อยซึ่งทำให้ผู้ใช้สามารถมองเห็นการทำงานเบื้องหลังได้ดังที่กล่าวโดย @Kristopher Micinski


2
โปรดทราบว่าสิ่งนี้ดูเหมือนจะไม่ได้รับการยอมรับอีกต่อไปด้วย SDK 17 บริการจะไม่ไปที่เบื้องหน้าหากสิ่งที่เบิกได้ส่งผ่านไปยังการแจ้งเตือนเป็น 0
Snicolas

มันเป็นข้อบกพร่องและหวังว่าจะได้รับการแก้ไข แนวคิดของบริการ Foreground คือบริการเหล่านี้มีแนวโน้มที่จะถูกฆ่าน้อยกว่าและนี่เป็นวิธีที่ทำให้ผู้ใช้ทราบถึงการมีอยู่ของมัน
Martin Marconcini

4
ด้วย Android 18 การแจ้งเตือนจะไม่มองไม่เห็นอีกต่อไป แต่แสดงว่า "แอปกำลังทำงานแตะเพื่อดูข้อมูลเพิ่มเติมหรือหยุดแอป"
Emanuel Moecklin

1
ภาพหน้าจอจากหนึ่งในลูกค้าของฉัน: 1gravity.com/k10/Screenshot_2013-07-25-12-35-49.jpg ฉันมีอุปกรณ์ 4.3 ด้วยและสามารถยืนยันการค้นหานั้นได้
Emanuel Moecklin

2
คำเตือน: ฉันได้รับรายงานข้อขัดข้องจาก Sony Ericsson LT26i (Xperia S) พร้อม Android 4.1.2 (SDK 16): android.app.RemoteServiceException: การแจ้งเตือนที่ไม่ถูกต้องที่โพสต์จากแพ็คเกจ ... : ไม่สามารถสร้างไอคอน: StatusBarIcon (pkg = ... id = 0x7f020052 ระดับ = 0 มองเห็นได้ = true num = 0) ฉันได้ตั้งค่ารหัสไอคอนเป็น 0 จนถึง SDK 17 ด้วย จาก SDK 18 ฉันได้ตั้งค่าเป็นทรัพยากรที่เบิกได้ที่ถูกต้อง บางทีคุณอาจต้องมีรหัสไอคอนที่ถูกต้องจาก SDK 16!
almisoft

13

คำเตือน : ถึงแม้ว่าคำตอบนี้ดูเหมือนจะทำงานก็เงียบในความเป็นจริงจะช่วยป้องกันการบริการของคุณจากการเป็นผู้ให้บริการเบื้องหน้า

คำตอบเดิม:


เพียงตั้งค่า ID การแจ้งเตือนของคุณเป็นศูนย์:

// field for notification ID
private static final int NOTIF_ID = 0;

    ...
    startForeground(NOTIF_ID, mBuilder.build());
    NotificationManager mNotificationManager = (NotificationManager) getSystemService(NOTIFICATION_SERVICE);
    mNotificationManager.cancel(NOTIF_ID);
    ...

ประโยชน์ที่คุณจะได้รับคือ a Serviceจะสามารถทำงานในลำดับความสำคัญสูงได้โดยไม่ถูกทำลายโดยระบบ Android เว้นแต่ในหน่วยความจำที่มีความกดดันสูง

แก้ไข

เพื่อให้ทำงานร่วมกับ Pre-รังผึ้งและ Android 4.4 และสูงกว่าให้แน่ใจว่าคุณใช้NotificationCompat.Builderซึ่งให้บริการโดยสนับสนุนห้องสมุด v7 Notification.Builderแทน


1
สิ่งนี้ใช้งานได้ดีสำหรับฉันใน 4.3 (18) @vlad sol ทำไมยังไม่มีการโหวตอื่น ๆ สำหรับคำตอบนี้ฉันสงสัย?
Rob McFeely

1
ฉันลองสิ่งนี้ใน Android N Preview 4 แล้วก็ไม่ได้ผล ฉันลองNotification.BuilderSupport Library v4 NotificationCompat.Builderและ Support Library v7 NotificationCompat.Builderแล้ว การแจ้งเตือนไม่ปรากฏในลิ้นชักการแจ้งเตือนหรือสถานะบาร์ แต่บริการที่ไม่ได้ทำงานในโหมดเบื้องหน้าเมื่อตรวจสอบโดยใช้และgetRunningServices() dumpsys
แซม

@ แซมข้อผิดพลาดนี้ไม่ปรากฏในเวอร์ชันก่อนหน้าใช่ไหม
Anggrayudi H

@AnggrayudiH โดย "ข้อบกพร่องนี้" คุณหมายถึงการแจ้งเตือนไม่ปรากฏหรือไม่ หรือคุณหมายถึงบริการไม่เข้าสู่โหมดเบื้องหน้า?
แซม

1
สิ่งนี้ไม่ได้ผลสำหรับฉัน กระบวนการนี้เริ่มต้นเป็นเบื้องหน้าเมื่อส่ง id! = 0 แต่ไม่ได้เริ่มต้นเป็นส่วนหน้าเมื่อ id = 0 ใช้adb shell dumpsys activity servicesเพื่อยืนยัน
บีทรี

10

คุณสามารถซ่อนการแจ้งเตือนบนAndroid 9+ ได้โดยใช้รูปแบบที่กำหนดเองด้วย layout_height = "0dp"

NotificationCompat.Builder builder = new NotificationCompat.Builder(context, NotificationUtils.CHANNEL_ID);
RemoteViews remoteViews = new RemoteViews(context.getPackageName(), R.layout.custom_notif);
builder.setContent(remoteViews);
builder.setPriority(NotificationCompat.PRIORITY_LOW);
builder.setVisibility(Notification.VISIBILITY_SECRET);

custom_notif.xml

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="0dp">
</LinearLayout>

ทดสอบบน Pixel 1, android 9 โซลูชันนี้ใช้ไม่ได้กับ Android 8 หรือน้อยกว่า


1
วิธีแก้ปัญหาที่ดี นอกจากนี้ฉันคิดว่ามันต้องใช้ไอคอนบน Android 10 การใช้ภาพตัวยึดแบบโปร่งใสสำหรับไอคอนช่วยแก้ปัญหาได้
shyos

7

อัปเดต: สิ่งนี้ใช้ไม่ได้ใน Android 4.3 ขึ้นไปอีกต่อไป


มีวิธีแก้ปัญหาหนึ่งวิธี ลองสร้างการแจ้งเตือนโดยไม่มีไอคอนการตั้งค่าแล้วการแจ้งเตือนจะไม่แสดง ไม่รู้ว่ามันทำงานอย่างไร แต่มันทำได้ :)

    Notification notification = new NotificationCompat.Builder(this)
            .setContentTitle("Title")
            .setTicker("Title")
            .setContentText("App running")
            //.setSmallIcon(R.drawable.picture)
            .build();
    startForeground(101,  notification);

3
ใน Android N Preview 4 จะไม่ทำงาน Android จะแสดงการ(YourServiceName) is runningแจ้งเตือนแทนการแจ้งเตือนของคุณเองเมื่อคุณไม่ได้ระบุไอคอน ตาม CommonsWare เป็นเช่นนี้มาตั้งแต่ Android 4.3: commonsware.com/blog/2013/07/30/…
แซม

1
วันนี้ฉันทำการทดสอบและยืนยันว่าสิ่งนี้ใช้ไม่ได้ใน Android 4.3 ขึ้นไป
แซม

5

อัปเดต: สิ่งนี้ใช้ไม่ได้ใน Android 4.3 ขึ้นไปอีกต่อไป


ฉันตั้งค่าพารามิเตอร์ไอคอนเป็นตัวสร้างสำหรับการแจ้งเตือนเป็นศูนย์จากนั้นส่งการแจ้งเตือนที่เป็นผลลัพธ์ไปยัง startForeground () ไม่มีข้อผิดพลาดในบันทึกและไม่มีการแจ้งเตือนปรากฏขึ้น ฉันไม่รู้ว่าบริการนั้นประสบความสำเร็จในเบื้องหน้าหรือไม่ - มีวิธีใดในการตรวจสอบหรือไม่?

แก้ไข: ตรวจสอบด้วยการทิ้งและบริการนี้อยู่เบื้องหน้าในระบบ 2.3 ของฉัน ยังไม่ได้ตรวจสอบกับ OS เวอร์ชันอื่น


9
ใช้คำสั่ง "adb shell dumpsys activity services" เพื่อตรวจสอบว่า "isForeground" ถูกตั้งค่าเป็นจริงหรือไม่
ดำ

1
หรือเพียงแค่เรียกตัวNotification()สร้างที่ว่างเปล่า
johsin18

สิ่งนี้ได้ผลสำหรับฉัน ครั้งแรกที่ฉันได้รับบริการของฉันเพื่อทำงานในชั่วข้ามคืนดังนั้นมันจึงอยู่เบื้องหน้าอย่างแน่นอน (บวกกับขยะบอกว่าเป็น) และไม่มีการแจ้ง
JamieB

โปรดทราบว่าสิ่งนี้ใช้ไม่ได้ใน Android 4.3 (API 18) อีกต่อไป ระบบปฏิบัติการจะใส่การแจ้งเตือนตัวยึดตำแหน่งไว้ในลิ้นชักการแจ้งเตือน
แซม

4

บล็อกการแจ้งเตือนบริการเบื้องหน้า

คำตอบส่วนใหญ่ที่นี่จะทำไม่ได้ทำงานทำลายบริการเบื้องหน้าหรือละเมิดนโยบายของ Google Play

วิธีเดียวที่จะซ่อนการแจ้งเตือนได้อย่างน่าเชื่อถือและปลอดภัยคือให้ผู้ใช้บล็อก

Android 4.1 - 7.1

วิธีเดียวคือปิดกั้นการแจ้งเตือนทั้งหมดจากแอปของคุณ:

  1. ส่งผู้ใช้ไปยังหน้าจอรายละเอียดของแอพ:

    Uri uri = Uri.fromParts("package", getPackageName(), null);
    Intent intent = new Intent(Settings.ACTION_APPLICATION_DETAILS_SETTINGS).setData(uri);
    startActivity(intent);
    
  2. ให้ผู้ใช้บล็อกการแจ้งเตือนของแอป

โปรดทราบว่าสิ่งนี้บล็อกขนมปังปิ้งของแอปด้วย

Android 8.0 - 8.1

การบล็อกการแจ้งเตือนบน Android O ไม่คุ้มค่าเพราะระบบปฏิบัติการจะแทนที่ด้วยการแจ้งเตือน" ทำงานอยู่เบื้องหลัง " หรือ " ใช้แบตเตอรี่ "

Android 9+

ใช้ช่องทางการแจ้งเตือนเพื่อปิดกั้นการแจ้งเตือนบริการโดยไม่ส่งผลต่อการแจ้งเตือนอื่น ๆ ของคุณ

  1. กำหนดการแจ้งเตือนบริการให้กับช่องทางการแจ้งเตือน
  2. ส่งผู้ใช้ไปยังการตั้งค่าช่องการแจ้งเตือน

    Intent intent = new Intent(Settings.ACTION_CHANNEL_NOTIFICATION_SETTINGS)
        .putExtra(Settings.EXTRA_APP_PACKAGE, getPackageName())
        .putExtra(Settings.EXTRA_CHANNEL_ID, myNotificationChannel.getId());
    startActivity(intent);
    
  3. ให้ผู้ใช้บล็อกการแจ้งเตือนของช่อง


2

เวอร์ชัน 4.3 (18) ขึ้นไปไม่สามารถซ่อนการแจ้งเตือนบริการได้ แต่คุณสามารถปิดใช้งานไอคอนเวอร์ชัน 4.3 (18) และต่ำกว่าได้เพื่อซ่อนการแจ้งเตือน

Notification noti = new Notification();
if (Build.VERSION.SDK_INT > Build.VERSION_CODES.JELLY_BEAN) {
    noti.priority = Notification.PRIORITY_MIN;
}
startForeground(R.string.app_name, noti);

แม้ว่าคำตอบนี้อาจจะถูกต้องและมีประโยชน์ แต่ก็เป็นที่ต้องการหากคุณใส่คำอธิบายไว้ด้วยเพื่ออธิบายว่าจะช่วยแก้ปัญหาได้อย่างไร สิ่งนี้จะมีประโยชน์อย่างยิ่งในอนาคตหากมีการเปลี่ยนแปลง (อาจไม่เกี่ยวข้อง) ที่ทำให้หยุดทำงานและผู้ใช้ต้องเข้าใจว่าครั้งหนึ่งเคยทำงานอย่างไร
Kevin Brown

ฉันคิดว่า Android 4.3 เป็น API 18 จริงๆแล้ววิธีนี้จะซ่อนไอคอนจากแถบสถานะเท่านั้น ไอคอนยังคงอยู่ในการแจ้งเตือน
แซม

สำหรับการซ่อนไอคอนจากการแจ้งเตือนคุณสามารถเพิ่มรูปภาพเปล่า mBuilder.setSmallIcon (R.drawable.blank);
vlad sol

1
ฉันกำลังดูแหล่งที่มาของ kitkat และดูเหมือนว่าวิธี zero ID จะไม่สามารถใช้งานได้ ถ้า ID เป็นศูนย์บันทึกบริการจะถูกอัพเดตเป็นไม่ใช่เบื้องหน้า
Jeffrey Blattman

2

ฉันพบใน Android 8.0 ยังคงเป็นไปได้โดยไม่ใช้ช่องทางการแจ้งเตือน

public class BootCompletedIntentReceiver extends BroadcastReceiver {
    @Override
    public void onReceive(Context context, Intent intent) {
        if ("android.intent.action.BOOT_COMPLETED".equals(intent.getAction())) {

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

                Intent notificationIntent = new Intent(context, BluetoothService.class);    
                context.startForegroundService(notificationIntent);

            } else {
                //...
            }

        }
    }
}

และใน BluetoothService.class:

 @Override
    public void onCreate(){    
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {

            Intent notificationIntent = new Intent(this, BluetoothService.class);

            PendingIntent pendingIntent = PendingIntent.getActivity(this, 0, notificationIntent, 0);

            Notification notification = new Notification.Builder(this)
                    .setContentTitle("Title")
                    .setContentText("App is running")
                    .setSmallIcon(R.drawable.notif)
                    .setContentIntent(pendingIntent)
                    .setTicker("Title")
                    .setPriority(Notification.PRIORITY_DEFAULT)
                    .build();

            startForeground(15, notification);

        }

    }

ไม่แสดงการแจ้งเตือนต่อเนื่อง แต่คุณจะเห็นการแจ้งเตือน 'x แอพของ Android กำลังทำงานอยู่เบื้องหลัง'


1
ใน Android 8.1: "การแจ้งเตือนไม่ถูกต้องสำหรับ startForeground: java.lang.RuntimeException: ช่องทางที่ไม่ถูกต้องสำหรับการแจ้งเตือนบริการ"
T-igra

โดยส่วนตัวแล้วฉันคิดว่าการapps are running in the backgroundแจ้งเตือนนั้นแย่กว่าการแจ้งเตือนเฉพาะแอปด้วยซ้ำดังนั้นฉันจึงไม่แน่ใจว่าวิธีนี้คุ้มค่า
แซม

-2

อัปเดต: สิ่งนี้ใช้ไม่ได้ใน Android 7.1 ขึ้นไปอีกต่อไป


นี่คือวิธีทำให้ oom_adj ของแอปของคุณเป็น 1 (ทดสอบในโปรแกรมจำลอง ANDROID 6.0 SDK).startForgroundService(NOTIFICATION_ID, notificion)เพิ่มบริการชั่วคราวในบริการโทรหลักของคุณ จากนั้นเริ่มการเรียกใช้บริการชั่วคราวstartForgroundService(NOTIFICATION_ID, notificion)โดยใช้รหัสการแจ้งเตือนเดียวกันอีกครั้งหลังจากนั้นสักครู่ในการเรียกใช้บริการชั่วคราว stopForgroundService (true) เพื่อยกเลิกการสร้าง ontification


นี่เป็นวิธีการแก้ปัญหาเดียวที่ฉันทราบ แต่ก็เป็นที่กล่าวมาแล้วโดยคำตอบอื่น
แซม

-3

คุณยังสามารถประกาศว่าแอปพลิเคชันของคุณเป็นแบบถาวร

<application
    android:icon="@drawable/icon"
    android:label="@string/app_name"
    android:theme="@style/Theme"
    *android:persistent="true"* >
</application>

ซึ่งโดยพื้นฐานแล้วแอปของคุณจะมีลำดับความสำคัญของหน่วยความจำที่สูงขึ้นซึ่งจะช่วยลดโอกาสที่แอปจะถูกฆ่า


5
สิ่งนี้ไม่ถูกต้องเฉพาะแอประบบเท่านั้นที่สามารถคงอยู่ได้: groups.google.com/forum/?fromgroups=#!topic/android-developers/…
Snicolas

-6

ฉันพัฒนาโปรแกรมเล่นสื่ออย่างง่ายเมื่อสองสามเดือนก่อน ดังนั้นสิ่งที่ฉันเชื่อคือถ้าคุณกำลังทำสิ่งที่ชอบ:

Intent i = new Intent(this, someServiceclass.class);

startService (ผม);

จากนั้นระบบจะไม่สามารถฆ่าบริการของคุณได้

อ้างอิง : อ่านย่อหน้าที่กล่าวถึงเมื่อระบบหยุดให้บริการ


ฉันอ่านในบางบทความ หากเพียงแค่ startService () แสดงว่าระบบต้องการหน่วยความจำเพิ่มเติม ดังนั้นระบบจะฆ่าบริการนั้น ถูกแล้ว? ฉันไม่มีเวลาทดลองให้บริการ
Muhammad Resna Rizki Pratama

1
มูฮัมหมัดนั่นเป็นความจริง - จุดประสงค์ของ startForeground () คือการให้บริการ "ลำดับความสำคัญของหน่วยความจำ" ที่สูงกว่าบริการเบื้องหลังอย่างมีประสิทธิภาพ startForeground () ควรใช้การแจ้งเตือนเพื่อให้ผู้ใช้ตระหนักถึงบริการที่ต่อเนื่อง / ยากต่อการฆ่ามากขึ้นซึ่งกำลังทำงานอยู่
DustinB

นี้เป็นเพียงไม่เป็นความจริง; แทบจะเป็นไปไม่ได้เลยที่จะสร้างบริการที่ไม่สามารถฆ่าได้บน Android Android พร้อมฆ่าบริการที่ไม่ใช่เบื้องหน้าเพื่อเพิ่มหน่วยความจำ
แซม
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.