จะตั้งเวลาปลุกอย่างไรในเวลาที่แน่นอนหลังจากข้อ จำกัด ใหม่ล่าสุดทั้งหมดบน Android


27

หมายเหตุ: ฉันลองใช้วิธีแก้ไขปัญหาต่าง ๆ ที่เขียนเกี่ยวกับที่นี่ใน StackOverflow (ตัวอย่างที่นี่ ) โปรดอย่าปิดสิ่งนี้โดยไม่ตรวจสอบว่าโซลูชันของคุณจากสิ่งที่คุณพบว่าทำงานได้โดยใช้แบบทดสอบที่ฉันเขียนด้านล่าง

พื้นหลัง

มีความต้องการในแอพที่ผู้ใช้ตั้งเตือนเพื่อกำหนดเวลาในเวลาที่กำหนดดังนั้นเมื่อแอพได้รับการทริกเกอร์ในเวลานี้มันจะทำสิ่งเล็ก ๆ ในพื้นหลัง (เพียงการดำเนินการแบบสอบถาม DB) และแสดง การแจ้งเตือนง่าย ๆ ที่จะบอกเกี่ยวกับการแจ้งเตือน

ในอดีตที่ผ่านมาฉันใช้รหัสง่าย ๆ เพื่อกำหนดสิ่งที่จะกำหนดเวลาค่อนข้างเฉพาะ:

            val alarmManager = context.getSystemService(Context.ALARM_SERVICE) as AlarmManager
            val pendingIntent = PendingIntent.getBroadcast(context, requestId, Intent(context, AlarmReceiver::class.java), PendingIntent.FLAG_UPDATE_CURRENT)
            when {
                VERSION.SDK_INT >= VERSION_CODES.KITKAT -> alarmManager.setExact(AlarmManager.RTC_WAKEUP, timeToTrigger, pendingIntent)
                else -> alarmManager.set(AlarmManager.RTC_WAKEUP, timeToTrigger, pendingIntent)
            }
class AlarmReceiver : BroadcastReceiver() {
    override fun onReceive(context: Context, intent: Intent) {
        Log.d("AppLog", "AlarmReceiver onReceive")
        //do something in the real app
    }
}

การใช้งาน:

            val timeToTrigger = System.currentTimeMillis() + java.util.concurrent.TimeUnit.MINUTES.toMillis(1)
            setAlarm(this, timeToTrigger, 1)

ปัญหา

ตอนนี้ฉันได้ทดสอบโค้ดนี้เกี่ยวกับอีมูเลเตอร์ใน Android รุ่นใหม่และใน Pixel 4 กับ Android 10 และดูเหมือนว่าจะไม่เปิดใช้งานหรือบางทีมันจะเริ่มทำงานหลังจากผ่านไปนานมากเนื่องจากสิ่งที่ฉันให้มา ฉันตระหนักดีถึงพฤติกรรมที่แย่มากที่ผู้ผลิต OEM บางรายเพิ่มเพื่อลบแอพออกจากงานล่าสุด แต่อันนี้มีทั้งตัวเลียนแบบและอุปกรณ์พิกเซล 4 (สต็อค)

ฉันได้อ่านเอกสารเกี่ยวกับการตั้งค่าการเตือนว่ามันถูก จำกัด สำหรับแอพเพื่อที่จะไม่เกิดขึ้นบ่อยเกินไป แต่สิ่งนี้ไม่ได้อธิบายวิธีตั้งค่าการเตือนในเวลาที่กำหนดและมันไม่ได้อธิบายแอป Clock ของ Googleมาได้อย่างไร

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

เมื่อเห็นว่าแอพนาฬิกาปลุกจำนวนมากไม่ทำงานอีกต่อไปเหมือนที่เคยเป็นมาฉันคิดว่ามีบางอย่างที่ขาดหายไปจากเอกสาร ตัวอย่างของแอพดังกล่าวเป็นแอพTimelyยอดนิยมที่ซื้อโดย Googleแต่ไม่เคยได้รับการอัพเดตใหม่เพื่อจัดการข้อ จำกัด ใหม่และตอนนี้ผู้ใช้ต้องการกลับคืนมา . แต่บางปพลิเคชันที่นิยมทำผลงานได้ดีเช่นนี้

สิ่งที่ฉันได้ลอง

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

  1. ทดสอบเมื่อแอปอยู่เบื้องหน้าผู้ใช้จะมองเห็นได้ - ใช้เวลา 1-2 นาที
  2. ทดสอบเมื่อแอปถูกส่งไปที่พื้นหลัง (เช่นใช้ปุ่มหน้าแรก) - ใช้เวลาประมาณ 1 นาที
  3. ทดสอบเมื่องานของแอพถูกลบออกจากงานล่าสุด - ฉันรอนานกว่า 20 นาทีและไม่เห็นสัญญาณเตือนที่กำลังถูกทริกเกอร์เขียนลงในบันทึก
  4. เช่น # 3 แต่ยังปิดหน้าจอ มันอาจจะเลวร้ายยิ่ง ...

ฉันพยายามใช้สิ่งต่อไปทุกอย่างใช้งานไม่ได้:

  1. alarmManager.setAlarmClock(AlarmManager.AlarmClockInfo(timeToTrigger, pendingIntent), pendingIntent)

  2. alarmManager.setExactAndAllowWhileIdle(AlarmManager.RTC_WAKEUP, timeToTrigger, pendingIntent)

  3. AlarmManagerCompat.setExactAndAllowWhileIdle(alarmManager, AlarmManager.RTC_WAKEUP, timeToTrigger, pendingIntent)

  4. การรวมกันของใด ๆ ข้างต้นด้วย:

    if (VERSION.SDK_INT >= VERSION_CODES.KITKAT) alarmManager.setWindow(AlarmManager.RTC_WAKEUP, 0, 60 * 1000L, pendingIntent)

  5. พยายามใช้บริการแทน BroadcastReceiver ยังลองในกระบวนการที่แตกต่างกัน

  6. พยายามทำให้แอพพลิเคชั่นถูกเพิกเฉยจากการปรับแต่งแบตเตอรี (ไม่ได้ช่วย) แต่เนื่องจากแอพอื่นไม่ต้องการมันฉันไม่ควรใช้มัน

  7. พยายามใช้สิ่งนี้:

            if (VERSION.SDK_INT >= VERSION_CODES.LOLLIPOP)
                alarmManager.setAlarmClock(AlarmManager.AlarmClockInfo(timeToTrigger, pendingIntent), pendingIntent)
            AlarmManagerCompat.setExactAndAllowWhileIdle(alarmManager, AlarmManager.RTC_WAKEUP, timeToTrigger, pendingIntent)
  1. พยายามมีบริการที่จะเรียกonTaskRemovedเพื่อกำหนดเวลาปลุกที่นั่นอีกครั้ง แต่สิ่งนี้ก็ไม่ได้ช่วย (บริการทำงานได้ดีแม้ว่า)

สำหรับแอพ Clock ของ Google ฉันไม่เห็นอะไรเป็นพิเศษเกี่ยวกับมันยกเว้นว่ามันจะแสดงการแจ้งเตือนก่อนที่จะถูกทริกเกอร์และฉันยังไม่เห็นมันในส่วน "ไม่เหมาะ" ในหน้าจอการตั้งค่าการเพิ่มประสิทธิภาพแบตเตอรี่

เมื่อเห็นว่านี่เป็นข้อผิดพลาดฉันได้รายงานเกี่ยวกับเรื่องนี้ที่นี่รวมถึงโครงการตัวอย่างและวิดีโอเพื่อแสดงปัญหา

ฉันตรวจสอบอีมูเลเตอร์หลายเวอร์ชันแล้วและดูเหมือนว่าพฤติกรรมนี้เริ่มต้นจาก API 27 (Android 8.1 - Oreo) ดูเอกสารฉันไม่เห็น AlarmManager ถูกกล่าวถึง แต่มันเขียนเกี่ยวกับการทำงานพื้นหลังต่างๆ

คำถาม

  1. เราจะตั้งค่าบางสิ่งให้ทำงานในเวลาที่แน่นอนในทุกวันนี้ได้อย่างไร

  2. ทำไมวิธีการแก้ปัญหาข้างต้นไม่ทำงานอีกต่อไป? ฉันไม่มีอะไรเลยหรือ ได้รับอนุญาต? บางทีฉันควรจะใช้คนงานแทน? แต่มันก็ไม่ได้หมายความว่ามันจะไม่ตรงเวลาเลยเหรอ?

  3. แอพ "นาฬิกา" ของ Google เอาชนะสิ่งเหล่านี้ทั้งหมดได้อย่างไรและเรียกใช้ในเวลาที่แน่นอนเสมอแม้ว่าจะถูกเรียกใช้เมื่อไม่กี่นาทีที่ผ่านมา เป็นเพราะแอประบบหรือไม่ จะเกิดอะไรขึ้นถ้ามันได้รับการติดตั้งเป็นแอพผู้ใช้บนอุปกรณ์ที่ไม่มีมันในตัว?

หากคุณบอกว่าเป็นเพราะแอประบบฉันพบแอปอื่นที่สามารถส่งสัญญาณเตือนได้สองครั้งใน 2 นาทีที่นี่ถึงแม้ว่าฉันคิดว่ามันอาจใช้บริการเบื้องหน้าในบางครั้ง

แก้ไข: ทำพื้นที่เก็บข้อมูล Github เล็ก ๆ ที่จะลองคิดอยู่ที่นี่


แก้ไข: ในที่สุดก็พบตัวอย่างที่มีทั้งแบบเปิดและไม่มีปัญหานี้ น่าเศร้าที่มันซับซ้อนมากและฉันยังคงพยายามหาสิ่งที่ทำให้มันแตกต่างกันมาก (และรหัสขั้นต่ำที่ฉันควรเพิ่มใน POC ของฉัน) คืออะไรที่ทำให้สัญญาณเตือนของมันยังคงอยู่หลังจากที่ลบแอพออกจากงานล่าสุด


มันเป็นเวลานานที่ฉันทำงานเกี่ยวกับการบริการ (ฉันไม่ได้เป็นนักพัฒนามืออาชีพที่จะแนะนำ) แต่ฉันสามารถแนะนำให้คุณหลีกเลี่ยง alarmManager สำหรับกรณีที่ต้องการตั้งปลุกด้านล่าง 5 นาทีเพราะเนื่องจากข้อ จำกัด ของ Android หลังจากบริการเวลาทำงานใน แบ็กเอนด์มันจะถูกเรียกหลังจากทุก 5 นาทีหรือมากกว่าไม่น้อยกว่า 5 นาที ฉันใช้ Handler แทน และสำหรับการให้บริการของฉันยังคงดำเนินต่อไปในพื้นหลังฉันเรียก [ github.com/fabcira/neverEndingAndroidService]
Blu

ดังนั้นข้อ จำกัด ที่แน่นอนคืออะไร? เวลาน้อยที่สุดที่รับประกันได้ว่าตัวกระตุ้นจะทำงานในเวลาที่กำหนดอย่างแม่นยำคืออะไร
นักพัฒนา Android

ฉันจำข้อ จำกัด ที่แน่นอนไม่ได้ แต่เมื่อฉันกำลังทำอยู่ฉันก็ทำหลายวันเพื่อเอาชนะบริการเบื้องหลังที่ถูกฆ่าโดยอัตโนมัติ และจากการสังเกตส่วนตัวฉันสังเกตเห็นปัญหาใน Samsung, Xiaomi และอื่น ๆ คุณไม่สามารถโทร alarmManger ในช่วงเวลา 5 นาทีฉันมีบริการอัปโหลดข้อมูลที่ดำเนินการโดยใช้ alarmManger ซึ่งได้รับการกระตุ้นทุก 1 นาที แต่ลูกค้าของเราที่บ่นบ่นบริการ ไม่ได้ทำงานเลย สำหรับอีมูเลเตอร์มันทำงานได้ดี
บลู

ฉันรู้ว่าคุณไม่สามารถเริ่มกิจกรรมจากพื้นหลังใน android Q แต่ดูเหมือนว่ามันไม่ใช่กรณีของคุณ
marcinj

@ greeble31 ฉันลองแล้ว โซลูชันใดที่คุณเห็นว่าทำงานอยู่ ด้วยเหตุผลบางอย่างฉันยังไม่สามารถใช้งานได้ ฉันตั้งค่าการเตือนฉันลบแอพออกจากงานล่าสุดและฉันไม่เห็นสัญญาณเตือนที่ถูกเรียกแม้ว่าหน้าจอเปิดอยู่และอุปกรณ์เชื่อมต่อกับอุปกรณ์ชาร์จ มันเกิดขึ้นได้ทั้งบนอุปกรณ์จริง (Pixel 4 กับ Android 10) และบนอีมูเลเตอร์ (เช่น API 27) มันใช้งานได้สำหรับคุณหรือไม่ คุณกรุณาแบ่งปันรหัสเต็มได้ไหม? อาจจะอยู่ใน Github?
นักพัฒนา android

คำตอบ:


4

เราไม่มีอะไรให้ทำ

เมื่อแอพของคุณไม่ได้อยู่ในรายการที่อนุญาตแล้วแอปจะถูกฆ่าเมื่อถูกลบออกจากแอพล่าสุด

เพราะผู้ผลิตอุปกรณ์ดั้งเดิม (OMEs) การละเมิดอย่างต่อเนื่องการปฏิบัติ

ดังนั้นหากแอปของคุณไม่อยู่ในรายการที่อนุญาตจากอุปกรณ์การผลิตแอปจะไม่เริ่มทำงานพื้นหลังใด ๆแม้กระทั่งสัญญาณเตือนในกรณีที่แอพของคุณถูกลบออกจากแอพล่าสุด

คุณสามารถค้นหารายการอุปกรณ์ที่มีพฤติกรรมดังกล่าวได้ที่นี่นอกจากนี้คุณอาจพบวิธีแก้ไขปัญหาด้านข้างอย่างไรก็ตามมันใช้งานไม่ได้


ฉันตระหนักดีถึงปัญหาของ OEM ของจีน แต่อย่างที่ฉันเขียนมันเกิดขึ้นแม้กระทั่งบนอีมูเลเตอร์และอุปกรณ์ Pixel 4 ไม่ใช่ OEM จากจีนที่ทำเช่นนี้ โปรดตรวจสอบอุปกรณ์จำลองและ / หรือพิกเซล ปัญหามีอยู่ที่นั่นด้วย ตั้งค่าการเตือนลบแอพออกจากงานล่าสุดและดูว่าการเตือนไม่ทำงาน ฉันเห็นสิ่งนี้เป็นข้อผิดพลาดและรายงานที่นี่ (รวมถึงวิดีโอและโครงการตัวอย่างหากคุณต้องการลอง): issuetracker.google.com/issues/149556385 ฉันได้อัปเดตคำถามของฉันเพื่อให้ชัดเจน คำถามคือแอพบางตัวประสบความสำเร็จได้อย่างไร
นักพัฒนา android

@androiddeveloper ฉันเชื่อว่ามันควรทำงานกับ Emulator .. อีมูเลเตอร์คนไหนที่คุณมี?
อิบราฮิมอาลี

ฉันก็เชื่อจนกระทั่งฉันพยายาม ลองใช้ API 29 ตัวอย่างของ Android Studio ที่มีให้ ฉันแน่ใจว่าสิ่งเดียวกันนี้จะเกิดขึ้นในรุ่นที่เก่ากว่านี้เช่นกัน
นักพัฒนา android

4

พบวิธีแก้ปัญหาแปลก ๆ (ตัวอย่างที่นี่ ) ที่ดูเหมือนจะใช้ได้กับทุกรุ่นรวมถึง Android R:

  1. ได้รับอนุญาตจาก SAW ที่ได้รับอนุญาตในรายการ:
      <uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW" />

บน Android R คุณจะต้องได้รับอนุญาตด้วย ก่อนหน้านี้ดูเหมือนจะไม่ได้รับอนุญาต แต่เพิ่งประกาศ ไม่แน่ใจว่าทำไมสิ่งนี้ถึงเปลี่ยนไปใน R แต่ฉันสามารถพูดได้ว่าอาจจำเป็นต้องใช้ SAW เป็นทางออกที่เป็นไปได้ที่จะเริ่มสิ่งต่าง ๆ ในพื้นหลังดังที่เขียนไว้ที่นี่สำหรับ Android 10

  1. มีบริการที่จะตรวจจับเมื่องานถูกลบออกและเมื่อใดให้เปิดกิจกรรมปลอมที่ปิดการทำงาน:
class OnTaskRemovedDetectorService : Service() {
    override fun onBind(intent: Intent?) = null

    override fun onStartCommand(intent: Intent?, flags: Int, startId: Int) = START_STICKY

    override fun onTaskRemoved(rootIntent: Intent?) {
        super.onTaskRemoved(rootIntent)
        Log.e("AppLog", "onTaskRemoved")
        applicationContext.startActivity(Intent(this, FakeActivity::class.java).addFlags(Intent.FLAG_ACTIVITY_NEW_TASK))
        stopSelf()
    }

}

FakeActivity.kt

class FakeActivity : AppCompatActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        Log.d("AppLog", "FakeActivity")
        finish()
    }
}

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

    <style name="AppTheme.Translucent" parent="@style/Theme.AppCompat.NoActionBar">
        <item name="android:windowBackground">@android:color/transparent</item>
        <item name="android:colorBackgroundCacheHint">@null</item>
        <item name="android:windowIsTranslucent">true</item>
    </style>

น่าเศร้านี่เป็นวิธีแก้ปัญหาแปลก ๆ ฉันหวังว่าจะหาวิธีแก้ไขที่ดีกว่านี้

ข้อ จำกัด พูดถึงการเริ่มต้นกิจกรรมดังนั้นความคิดปัจจุบันของฉันคือถ้าฉันเริ่มบริการเบื้องหน้าสักเสี้ยววินาทีก็จะช่วยได้และสำหรับสิ่งนี้ฉันไม่จำเป็นต้องได้รับอนุญาตจาก SAW

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

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

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


แก้ไข: ดูเหมือนว่าเป็นข้อบกพร่องใน Android Studio (รายงานที่นี่รวมถึงวิดีโอเปรียบเทียบรุ่น) เมื่อคุณเปิดแอพจากเวอร์ชันที่มีปัญหาที่ฉันลองมามันอาจทำให้การเตือนภัยถูกลบ

หากคุณเปิดแอปจากตัวเรียกใช้งานก็จะทำงานได้ดี

นี่คือรหัสปัจจุบันเพื่อตั้งการเตือน:

        val timeToTrigger = System.currentTimeMillis() + 10 * 1000
        val pendingShowList = PendingIntent.getActivity(this, 1, Intent(this, SomeActivity::class.java), PendingIntent.FLAG_UPDATE_CURRENT)
        val pendingIntent = PendingIntent.getBroadcast(this, 1, Intent(this, AlarmReceiver::class.java), PendingIntent.FLAG_UPDATE_CURRENT)
        manager.setAlarmClock(AlarmManager.AlarmClockInfo(timeToTrigger, pendingShowList), pendingIntent)

ฉันไม่ต้องใช้ "pendingShowList" ใช้โมฆะก็โอเค


ฉันแค่อยากทำกิจกรรมบนReceive () บน AndroidQ มีวิธีแก้ปัญหาสำหรับสิ่งนั้นโดยไม่SYSTEM_ALERT_WINDOWได้รับอนุญาตหรือไม่?
Doctorram

2
เหตุใด Google จึงทำให้นักพัฒนาซอฟต์แวร์ของ Android ใช้ชีวิตอย่างมีความสุขเหนือสิ่งง่าย ๆ !
Doctorram

@doctorram ใช่มันเขียนบนเอกสารเกี่ยวกับข้อยกเว้นต่างๆ: developer.android.com/guide/components/activities/... ฉันเพิ่งเลือก SYSTEM_ALERT_WINDOW เพราะง่ายที่สุดในการทดสอบ
นักพัฒนา android

จากการแก้ไขครั้งล่าสุดของคุณคุณหมายถึงว่าตอนนี้เราไม่ต้องใช้วิธีแก้ไขปัญหาใด ๆ ที่คุณกล่าวถึงเพื่อคงการเตือนภัยไว้หลังจากลบแอพออกจากรายการล่าสุดหรือไม่?
3410835

ฉันต้องการเรียกใช้โค้ดทุก ๆ วันระหว่างเวลา 6.00 น. ถึง 7.00 น. ในพื้นหลังแม้ว่าแอพจะถูกลบออกจากรายการล่าสุด ฉันควรใช้ WorkManager หรือ AlarmManager หรือไม่ ลองใช้รหัสต่อไปนี้สำหรับ usecase ของฉันและมันไม่ทำงาน รหัสด้านล่างมีปัญหาอะไร? calendar.setTimeInMillis (System.currentTimeMillis ()); calendar.set (Calendar.HOUR_OF_DAY, 6); alarmManager.setInexactRepeating (AlarmManager.RTC_WAKEUP, calendar.getTimeInMillis (), AlarmManager.INTERVAL_DAY รอดำเนินการ)
user3410835

1
  1. ตรวจสอบให้แน่ใจว่าเจตนาที่คุณออกอากาศชัดเจนและมีIntent.FLAG_RECEIVER_FOREGROUNDธง

https://developer.android.com/about/versions/oreo/background#broadcasts

Intent intent = new Intent(context, Receiver.class);
intent.setAction(action);
...
intent.addFlags(Intent.FLAG_RECEIVER_FOREGROUND);

PendingIntent operation = PendingIntent.getBroadcast(context, 0, intent, flags);
  1. ใช้setExactAndAllowWhileIdle()เมื่อกำหนดเป้าหมาย API 23+
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
    alarmManager.setExactAndAllowWhileIdle(AlarmManager.RTC_WAKEUP, time, operation);
} else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
    alarmManager.setExact(AlarmManager.RTC_WAKEUP, time, operation);
} else {
    alarmManager.set(AlarmManager.RTC_WAKEUP, time, operation);
}
  1. เริ่มการเตือนของคุณเป็นบริการเบื้องหน้า:

https://developer.android.com/about/versions/oreo/background#migration

if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
    context.startForegroundService(intent);
} else {
    context.startService(intent);
}
  1. และอย่าลืมสิทธิ์:
<uses-permission android:name="android.permission.FOREGROUND_SERVICE" />

ทำไมมันถึงมีความสำคัญเกี่ยวกับบริการถ้า BroadcastReceiver เองไม่ได้รับเจตนาทั้งหมด (หรือใกล้เวลา) นี่เป็นขั้นตอนแรก ... นอกจากนี้ AlarmManagerCompat ยังไม่ได้เสนอรหัสเดียวกันนี้หรือไม่ คุณลองทำสิ่งนี้โดยใช้การทดสอบที่ฉันเขียนรวมถึงการลบแอพออกจากงานล่าสุดหรือไม่? คุณกรุณาแสดงรหัสทั้งหมดได้ไหม อาจแบ่งปันกับ Github หรือไม่
นักพัฒนา android

@androiddeveloper อัปเดตคำตอบ
Maksim Ivanov

ยังดูเหมือนจะไม่ทำงาน นี่เป็นโครงการตัวอย่าง: ufile.io/6qrsor7o โปรดลองบน Android 10 (อีมูเลเตอร์ยังใช้ได้) ตั้งปลุกและลบแอพออกจากงานล่าสุด หากคุณไม่ลบงานที่เพิ่งทำออกมามันจะทำงานได้ดีและถูกเรียกใช้หลังจากผ่านไป 10 วินาที
นักพัฒนา android

ฉันได้อัปเดตคำถามเพื่อให้มีลิงก์ไปยังรายงานข้อผิดพลาดซึ่งรวมถึงโครงการตัวอย่างและวิดีโอเพราะฉันคิดว่านี่เป็นข้อผิดพลาดเนื่องจากฉันไม่เห็นเหตุผลอื่นใดที่จะเกิดขึ้น
นักพัฒนา android

0

ฉันรู้ว่านี่ไม่มีประสิทธิภาพ แต่อาจสอดคล้องกับความแม่นยำมากกว่า 60 วินาที

https://developer.android.com/reference/android/content/Intent#ACTION_TIME_TICK

หากใช้ตัวรับสัญญาณออกอากาศนี้ในบริการเบื้องหน้าคุณสามารถตรวจสอบเวลาทุกนาทีและตัดสินใจดำเนินการได้


หากฉันมีบริการเบื้องหน้าทำไมฉันต้องใช้สิ่งนี้ ฉันสามารถใช้ Handler.postDelayed หรือวิธีแก้ปัญหาอื่นที่คล้ายคลึงกันได้หากต้องการ ...
นักพัฒนา Android

0

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

นี่คือรหัสที่จะขอ:

PowerManager powerManager = (PowerManager) getApplicationContext().getSystemService(POWER_SERVICE);
            String packageName = "your Package name";
            if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
                Intent i = new Intent();
                if (!powerManager.isIgnoringBatteryOptimizations(packageName)) {
                    i.setAction(Settings.ACTION_REQUEST_IGNORE_BATTERY_OPTIMIZATIONS);
                    i.setData(Uri.parse("package:" + packageName));
                    startActivity(i);

ลองสิ่งนี้แล้วเพราะฉันสังเกตเห็นว่าไม่มีแอปอื่นทำและสงสัยว่ามันจะช่วยได้หรือไม่ ใช้งานไม่ได้ อัปเดตคำถาม
นักพัฒนา android

0

ผมเขียนของโครงการที่มาเปิดให้คุณได้กล่าวถึงในคำถามของคุณ ( นาฬิกาปลุกง่าย)

ฉันประหลาดใจที่ใช้ AlarmManager.setAlarmClock ไม่ได้ผลสำหรับคุณเพราะแอปของฉันทำสิ่งนั้นอย่างแน่นอน รหัสอยู่ในไฟล์ AlarmSetter.kt นี่คือตัวอย่าง:

  val pendingAlarm = Intent(ACTION_FIRED)
                .apply {
                    setClass(mContext, AlarmsReceiver::class.java)
                    putExtra(EXTRA_ID, id)
                    putExtra(EXTRA_TYPE, typeName)
                }
                .let { PendingIntent.getBroadcast(mContext, pendingAlarmRequestCode, it, PendingIntent.FLAG_UPDATE_CURRENT) }

            val pendingShowList = PendingIntent.getActivity(
                    mContext,
                    100500,
                    Intent(mContext, AlarmsListActivity::class.java),
                    PendingIntent.FLAG_UPDATE_CURRENT
            )

            am.setAlarmClock(AlarmManager.AlarmClockInfo(calendar.timeInMillis, pendingShowList), pendingAlarm)

โดยทั่วไปมันไม่มีอะไรพิเศษเพียงให้แน่ใจว่าเจตนามีการกระทำและคลาสเป้าหมายซึ่งเป็นตัวรับสัญญาณออกอากาศในกรณีของฉัน


น่าเศร้าที่ไม่ได้ทำงาน นั่นคือสิ่งที่ฉันพยายาม ดูไฟล์ได้ที่นี่: github.com/yuriykulikov/AlarmClock/issues/ ......
นักพัฒนาซอฟต์แวร์ Android

ฉันตรวจสอบรหัสของคุณบน GitHub แล้ว ตัวรับสัญญาณออกอากาศทำงานหลังจากลบแอพออกจากรายการล่าสุดบน Moto Z2 Play ฉันสามารถทดลองใช้กับ Pixel ได้ แต่โค้ดดูเหมือนว่าใช้ได้สำหรับฉัน การบังคับให้แอปพลิเคชั่นหยุดลบการเตือนที่กำหนดเวลาไว้ แต่สิ่งนี้จะเกิดขึ้นกับแอพใด ๆ
Yuriy Kulikov

ฉันได้แสดงหลายครั้งแล้ว: สิ่งที่ฉันทำหลังจากการตั้งเวลาคือการลบออกจากงานล่าสุด และฉันก็ทำทั้ง emulator และ Pixel 4
นักพัฒนา android

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