บริการเบื้องหน้าถูกฆ่าโดย Android


86

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

ฉันมีปัญหาเดียวกันกับในคำถามนี้: บริการถูกฆ่าในขณะที่กด Wake Lock และหลังจากเรียก startForegroundรวมถึงอุปกรณ์ (Asus Transformer) ระยะเวลาก่อนหยุดให้บริการ (30-45 นาที) การใช้งาน ล็อคการปลุกการใช้ startForeground () และความจริงที่ว่าปัญหาจะไม่เกิดขึ้นหากแอปเปิดอยู่เมื่อหน้าจอดับลง

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

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

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

ฉันเห็นสิ่งนี้ในบันทึกของฉันเมื่อใดก็ตามที่บริการหยุด:

ActivityManager: No longer want com.howettl.textab (pid 32321): hidden #16
WindowManager: WIN DEATH: Window{40e2d968 com.howettl.textab/com.howettl.textab.TexTab paused=false
ActivityManager: Scheduling restart of crashed service com.howettl.textab/.TexTabService in 5000ms

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

แก้ไข: นี่คือผลลัพธ์ของadb shell dumpsys activity services:

* ServiceRecord{40f632e8 com.howettl.textab/.TexTabService}

intent={cmp=com.howettl.textab/.TexTabService}

packageName=com.howettl.textab

processName=com.howettl.textab

baseDir=/data/app/com.howettl.textab-1.apk

resDir=/data/app/com.howettl.textab-1.apk

dataDir=/data/data/com.howettl.textab

app=ProcessRecord{40bb0098 2995:com.howettl.textab/10104}

isForeground=true foregroundId=2 foregroundNoti=Notification(contentView=com.howettl.textab/0x1090087 vibrate=null,sound=null,defaults=0x0,flags=0x6a)

createTime=-25m42s123ms lastActivity=-25m42s27ms

 executingStart=-25m42s27ms restartTime=-25m42s124ms

startRequested=true stopIfKilled=false callStart=true lastStartId=1

Bindings:

* IntentBindRecord{40a02618}:

  intent={cmp=com.howettl.textab/.TexTabService}

  binder=android.os.BinderProxy@40a9ff70

  requested=true received=true hasBound=true doRebind=false

  * Client AppBindRecord{40a3b780 ProcessRecord{40bb0098 2995:com.howettl.textab/10104}}

    Per-process Connections:

      ConnectionRecord{40a76920 com.howettl.textab/.TexTabService:@40b998b8}

All Connections:

  ConnectionRecord{40a76920 com.howettl.textab/.TexTabService:@40b998b8}

และผลลัพธ์ของadb shell dumpsys activity:

* TaskRecord{40f5c050 #23 A com.howettl.textab}

numActivities=1 rootWasReset=false

affinity=com.howettl.textab

intent={act=android.intent.action.MAIN cat=[android.intent.category.LAUNCHER] flg=0x10000000 cmp=com.howettl.textab/.TexTab}

realActivity=com.howettl.textab/.TexTab

lastActiveTime=4877757 (inactive for 702s)

* Hist #1: ActivityRecord{40a776c8 com.howettl.textab/.TexTab}

    packageName=com.howettl.textab processName=com.howettl.textab

    launchedFromUid=2000 app=ProcessRecord{40bb0098 2995:com.howettl.textab/10104}

    Intent { act=android.intent.action.MAIN cat=[android.intent.category.LAUNCHER] flg=0x10000000 cmp=com.howettl.textab/.TexTab }

    frontOfTask=true task=TaskRecord{40f5c050 #23 A com.howettl.textab}

    taskAffinity=com.howettl.textab

    realActivity=com.howettl.textab/.TexTab

    base=/data/app/com.howettl.textab-1.apk/data/app/com.howettl.textab-1.apk data=/data/data/com.howettl.textab

    labelRes=0x7f060000 icon=0x7f020000 theme=0x0

    stateNotNeeded=false componentSpecified=true isHomeActivity=false

    configuration={ scale=1.0 imsi=0/0 loc=en_CA touch=3 keys=2/1/1 nav=1/2 orien=L layout=0x10000014 uiMode=0x11 seq=6}

    launchFailed=false haveState=true icicle=Bundle[mParcelledData.dataSize=1644]

    state=STOPPED stopped=true delayedResume=false finishing=false

    keysPaused=false inHistory=true visible=false sleeping=true idle=true

    fullscreen=true noDisplay=false immersive=false launchMode=2

    frozenBeforeDestroy=false thumbnailNeeded=false

    connections=[ConnectionRecord{40a76920 com.howettl.textab/.TexTabService:@40b998b8}]

...

Proc #15: adj=prcp /F 40e75070 959:android.process.acore/10006 (provider)

          com.android.providers.contacts/.ContactsProvider2<=Proc{40bb0098 2995:com.howettl.textab/10104}

Proc #16: adj=bak+2/F 40bb0098 2995:com.howettl.textab/10104 (foreground-service)

สิ่งเหล่านี้ดูเหมือนจะแสดงบริการกำลังทำงานอยู่เบื้องหน้า


ลองดูคำตอบนี้ - อาจได้ผลสำหรับคุณstackoverflow.com/a/21157035/624109
Muzikant

คำตอบ:


223

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

เพื่อสรุปว่าสิ่งต่างๆควรจะทำงานอย่างไร บริการที่ทำงานอยู่จะถูกกำจัดเป็นประจำและยุติทุก ๆ 30 นาทีหรือมากกว่านั้น บริการที่ต้องการมีชีวิตอยู่นานกว่านี้ต้องโทรไปที่ Service.startForeground ซึ่งจะแจ้งเตือนบนแถบการแจ้งเตือนเพื่อให้ผู้ใช้ทราบว่าบริการของคุณกำลังทำงานอย่างถาวรและอาจทำให้อายุการใช้งานแบตเตอรี่หมดไป มีกระบวนการบริการเพียง 3 ขั้นตอนเท่านั้นที่สามารถเสนอชื่อตัวเองเป็นบริการเบื้องหน้าในช่วงเวลาใดก็ได้ หากมีบริการเบื้องหน้ามากกว่าสามบริการ Android จะเสนอชื่อบริการที่เก่าแก่ที่สุดเป็นตัวเลือกในการกำจัดและยุติ

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

โปรดทราบว่าบริการจำนวนน้อยมากที่ต้องเป็นบริการเบื้องหน้า โดยทั่วไปคุณจะต้องเป็นบริการเบื้องหน้าก็ต่อเมื่อคุณมีการเชื่อมต่ออินเทอร์เน็ตที่ใช้งานอยู่ตลอดเวลาหรือใช้งานได้ยาวนานซึ่งผู้ใช้สามารถเปิดและปิดหรือยกเลิกได้ ตัวอย่างบริการที่ต้องการสถานะเบื้องหน้า: เซิร์ฟเวอร์ UPNP, การดาวน์โหลดไฟล์ขนาดใหญ่มากเป็นเวลานาน, การซิงค์ระบบไฟล์ด้วย Wi-Fi และการเล่นเพลง

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

เมื่อทำเครื่องหมายในช่องตามข้อกำหนดที่รู้จักกันดี (เช่นการเรียก Service.startForeground) สถานที่ถัดไปที่จะดูคือแฟล็กที่คุณใช้ในการเรียก Context.bindService แฟล็กที่ใช้ในการผูกมีผลต่อลำดับความสำคัญของกระบวนการเซอร์วิสเป้าหมายในหลาย ๆ วิธีที่ไม่คาดคิด โดยเฉพาะอย่างยิ่งการใช้แฟล็กการผูกบางอย่างอาจทำให้ Android ปรับลดรุ่นบริการเบื้องหน้าของคุณเป็นบริการปกติไม่ถูกต้อง รหัสที่ใช้ในการกำหนดลำดับความสำคัญของกระบวนการถูกปั่นป่วนค่อนข้างมาก โดยเฉพาะอย่างยิ่งมีการแก้ไขใน API 14+ ที่อาจทำให้เกิดข้อบกพร่องเมื่อใช้แฟล็กการผูกแบบเก่า และมีข้อบกพร่องแน่นอนใน 4.2.1

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

adb shell ทิ้งกระบวนการกิจกรรม> tmp.txt

ใช้ notepad (ไม่ใช่ wordpad / write) เพื่อตรวจสอบเนื้อหา

ขั้นแรกให้ตรวจสอบว่าคุณจัดการเพื่อเรียกใช้บริการของคุณในสถานะเบื้องหน้าได้สำเร็จ ส่วนแรกของไฟล์ dumpsys มีคำอธิบายคุณสมบัติของ ActivityManager สำหรับแต่ละกระบวนการ มองหาบรรทัดต่อไปนี้ที่ตรงกับแอปพลิเคชันของคุณในส่วนแรกของไฟล์ dumpsys:

APP UID 10068 ProcessRecord {41937d40 2205: tunein.service / u0a10068}

ตรวจสอบว่า ForeServices = true ในส่วนต่อไปนี้ ไม่ต้องกังวลกับการตั้งค่าที่ซ่อนอยู่และว่างเปล่า พวกเขาอธิบายสถานะของกิจกรรมในกระบวนการและดูเหมือนจะไม่เกี่ยวข้องโดยเฉพาะอย่างยิ่งสำหรับกระบวนการที่มีบริการในนั้น หาก ForeService ไม่เป็นจริงคุณต้องเรียกใช้ Service.startForeground เพื่อทำให้เป็นจริง

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

ลองดูบรรทัดในตารางนี้:

  Proc #31: adj=prcp /FS trm= 0 2205:tunein.service/u0a10068 (fg-service)

นี่คือตัวอย่างของบริการเบื้องหน้าที่ทำทุกอย่างถูกต้อง ฟิลด์คีย์ในที่นี้คือฟิลด์ "adj =" นั่นแสดงถึงลำดับความสำคัญที่กระบวนการของคุณได้รับมอบหมายโดย ActivityManagerService หลังจากที่ทุกอย่างเสร็จสิ้น คุณต้องการให้เป็น "adj = prcp" (บริการเบื้องหน้าที่มองเห็นได้); หรือ "adj = vis" (กระบวนการที่มองเห็นได้พร้อมกับกิจกรรม) หรือ "fore" (กระบวนการที่มีกิจกรรมเบื้องหน้า) หากเป็น "adj = svc" (กระบวนการบริการ) หรือ "adj = svcb" (บริการเดิม?) หรือ "adj = bak" (กระบวนการพื้นหลังว่างเปล่า) แสดงว่ากระบวนการของคุณมีแนวโน้มที่จะยุติและจะถูกยุติ ไม่น้อยกว่าทุก ๆ 30 นาทีแม้ว่าจะไม่มีแรงกดดันในการเรียกคืนหน่วยความจำก็ตาม แฟล็กที่เหลือในบรรทัดส่วนใหญ่เป็นข้อมูลการแก้ปัญหาการวินิจฉัยสำหรับวิศวกรของ Google การตัดสินใจในการยกเลิกจะขึ้นอยู่กับฟิลด์ adj สั้น ๆ / FS หมายถึงบริการเบื้องหน้า / FA ระบุกระบวนการเบื้องหน้าที่มีกิจกรรม / B หมายถึงบริการเบื้องหลัง ป้ายกำกับในตอนท้ายระบุกฎทั่วไปที่กระบวนการถูกกำหนดลำดับความสำคัญ โดยปกติควรตรงกับฟิลด์ adj =; แต่ค่า adj = สามารถปรับขึ้นหรือลงได้ในบางกรณีเนื่องจากการผูกแฟล็กบนการผูกที่ใช้งานอยู่กับบริการหรือกิจกรรมอื่น ๆ

หากคุณสะดุดจุดบกพร่องที่มีแฟล็กที่ผูกไว้เส้นทิ้งจะมีลักษณะดังนี้:

  Proc #31: adj=bak /FS trm= 0 2205:tunein.service/u0a10068 (fg-service)

โปรดสังเกตว่าค่าของฟิลด์ adj ถูกตั้งค่าเป็น "adj = bak" อย่างไม่ถูกต้อง (กระบวนการพื้นหลังว่างเปล่า) ซึ่งแปลประมาณว่า "ได้โปรดยุติฉันเดี๋ยวนี้เพื่อที่ฉันจะได้ยุติการดำรงอยู่อย่างไร้จุดหมายนี้" เพื่อจุดประสงค์ในการกำจัดกระบวนการ นอกจากนี้โปรดสังเกตแฟล็ก (fg-service) ที่ท้ายบรรทัดซึ่งระบุว่า "forground service rules ถูกใช้เพื่อกำหนดการตั้งค่า" adj "แม้ว่าจะมีการใช้กฎ fg-service แต่กระบวนการนี้ก็ได้รับการกำหนดการตั้งค่า adj "บัก" แล้วมันจะอยู่ได้ไม่นานพูดธรรมดานี่คือบั๊ก

ดังนั้นเป้าหมายคือเพื่อให้แน่ใจว่ากระบวนการของคุณได้รับ "adj = prcp" (หรือดีกว่า) เสมอ และวิธีการในการบรรลุเป้าหมายนั้นคือการปรับแต่งแฟล็กการผูกจนกว่าคุณจะจัดการเพื่อหลีกเลี่ยงจุดบกพร่องในการกำหนดลำดับความสำคัญ

นี่คือข้อบกพร่องที่ฉันรู้ (1) หากบริการหรือกิจกรรมใด ๆ เคยผูกมัดกับบริการโดยใช้ Context.BIND_ABOVE_CLIENT คุณจะเสี่ยงที่การตั้งค่า adj = จะถูกลดระดับเป็น "bak" แม้ว่าการผูกนั้นจะไม่ทำงานอีกต่อไปก็ตาม โดยเฉพาะอย่างยิ่งหากคุณมีการเชื่อมโยงระหว่างบริการ ข้อบกพร่องที่ชัดเจนในแหล่งที่มา 4.2.1 (2) ห้ามใช้ BIND_ABOVE_CLIENT สำหรับการผูกบริการกับบริการโดยเด็ดขาด อย่าใช้สำหรับการเชื่อมต่อระหว่างกิจกรรมกับบริการ แฟล็กที่ใช้ในการปรับใช้ลักษณะการทำงาน BIND_ABOVE_CLIENT ดูเหมือนว่าจะถูกตั้งค่าแบบต่อกระบวนการแทนที่จะเป็นแบบต่อการเชื่อมต่อดังนั้นจึงทริกเกอร์จุดบกพร่องด้วยการเชื่อมระหว่างบริการกับบริการแม้ว่าจะไม่มีกิจกรรมกับบริการ ผูกพันกับชุดธง นอกจากนี้ยังดูเหมือนจะมีปัญหาในการกำหนดลำดับความสำคัญเมื่อมีบริการหลายอย่างในกระบวนการโดยมีการผูกบริการกับบริการ การใช้ Context.BIND_WAIVE_PRIORITY (API 14) ในการผูกบริการกับบริการดูเหมือนจะช่วยได้ Context.BIND_IMPORTANT น่าจะเป็นความคิดที่ดีไม่มากก็น้อยเมื่อเชื่อมโยงจากกิจกรรมกับบริการ การทำเช่นนี้จะทำให้ลำดับความสำคัญของกระบวนการของคุณสูงขึ้นหนึ่งระดับเมื่อกิจกรรมอยู่ในส่วนหน้าโดยไม่ทำอันตรายใด ๆ เมื่อหยุดกิจกรรมชั่วคราวหรือเสร็จสิ้น

แต่โดยรวมแล้วกลยุทธ์คือการปรับแฟล็ก bindService ของคุณจนกว่า sysdump จะระบุว่ากระบวนการของคุณได้รับลำดับความสำคัญที่ถูกต้อง

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

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

การดำเนินการตามกฎสำหรับกระบวนการกวาดล้าง (และซอร์สโค้ดที่ใช้สร้างเนื้อหาของไฟล์ sysdump) สามารถพบได้ในไฟล์ Android หลัก

frameworks\base\services\java\com\android\server\am\ActivityManagerService.java.

โอกาสบอน.

PS: นี่คือการตีความสตริง sysdump สำหรับ Android 5.0 ฉันไม่ได้ทำงานกับพวกเขาดังนั้นจงสร้างสิ่งที่คุณต้องการ ฉันเชื่อว่าคุณต้องการให้ 4 เป็น "A" หรือ "S" และ 5 เป็น "IF" หรือ "IB" และ 1 ให้ต่ำที่สุดเท่าที่จะเป็นไปได้ (อาจต่ำกว่า 3 เนื่องจากมีการใช้งานกระบวนการบริการเบื้องหน้าเพียง 3 สามขั้นตอนเท่านั้น ในการกำหนดค่าเริ่มต้น)

Example:
   Proc # : prcp  F/S/IF trm: 0 31719: neirotech.cerebrum.attention:blePrcs/u0a77 (fg-service)

Format:
   Proc # {1}: {2}  {3}/{4}/{5} trm: {6} {7}: {8}/{9} ({10}

1: Order in list: lower is less likely to get trimmed.

2: Not sure.

3:
    B: Process.THREAD_GROUP_BG_NONINTERACTIVE
    F: Process.THREAD_GROUP_DEFAULT

4:
    A: Foreground Activity
    S: Foreground Service
    ' ': Other.

5:
    -1: procState = "N ";
        ActivityManager.PROCESS_STATE_PERSISTENT: procState = "P ";
    ActivityManager.PROCESS_STATE_PERSISTENT_UI:procState = "PU";
    ActivityManager.PROCESS_STATE_TOP: procState = "T ";
    ActivityManager.PROCESS_STATE_IMPORTANT_FOREGROUND: procState = "IF";
    ActivityManager.PROCESS_STATE_IMPORTANT_BACKGROUND: procState = "IB";
    ActivityManager.PROCESS_STATE_BACKUP:procState = "BU";
    ActivityManager.PROCESS_STATE_HEAVY_WEIGHT: procState = "HW";
    ActivityManager.PROCESS_STATE_SERVICE: procState = "S ";
    ActivityManager.PROCESS_STATE_RECEIVER: procState = "R ";
    ActivityManager.PROCESS_STATE_HOME: procState = "HO";
    ActivityManager.PROCESS_STATE_LAST_ACTIVITY: procState = "LA";
    ActivityManager.PROCESS_STATE_CACHED_ACTIVITY: procState = "CA";
    ActivityManager.PROCESS_STATE_CACHED_ACTIVITY_CLIENT: procState = "Ca";
    ActivityManager.PROCESS_STATE_CACHED_EMPTY: procState = "CE";

{6}: trimMemoryLevel

{8} Process ID.
{9} process name
{10} appUid 

4
@ โรบินเดวีส์ฉันมีคำถามเล็ก ๆ ฉันจำเป็นต้องโทรหาจริงๆbindService()หรือไม่ถ้าฉันต้องการเรียกใช้บริการอยู่ตลอดเวลา? แค่โทรstartForeground()เข้าบริการยังไม่พอเหรอ? สำหรับการสื่อสารกับเซิร์ฟเวอร์ฉันใช้ EventBus
ar-g

คุณเรียกใช้ Context.bindService จากกิจกรรมเพื่อให้บริการทำงานตั้งแต่แรก เมธอด Service.startService ถูกเรียกโดยรหัสในบริการเพื่อย้ายบริการที่เริ่มต้นเข้าสู่สถานะ "พื้นหน้า" ฉันคิดว่าไลบรารี EventBus เรียกใช้ Context.bindService ในนามของคุณในบางจุดเพื่อให้บริการเริ่มต้น หากมีวิธีอื่นในการเริ่มบริการฉันไม่คุ้นเคยกับมัน
Robin Davies

3
โพสต์ยอดเยี่ยม! โหวตแล้ว มีชิ้นหนึ่งที่ฉันต้องการเพิ่มในความคิดเห็นนี้ซึ่งฉันเชื่อว่าเกี่ยวข้อง หากคุณต้องการบริการที่ทำงานอยู่ตลอดเวลาดังที่โรบินกล่าวไว้คุณต้องเริ่มใช้บริการนี้ เป็นไปได้ที่จะเรียก startService (Intent service) โดยตรงภายในกิจกรรมของคุณแทนที่จะเป็น bindService () จากนั้นเมื่อบริการของคุณเริ่มต้นขึ้นคุณสามารถเรียกใช้เมธอด startForeground () ได้ ฉันเรียกสิ่งนี้ใน onStartCommand () ของคลาสบริการ เท่าที่ฉันทราบสิ่งนี้ควรทำให้บริการของคุณไม่ถูกผูกไว้ แต่ให้ใช้งานปัญหาทรัพยากรที่รอดำเนินการอยู่ หวังว่านี่จะช่วยใครบางคนได้
Dave

การทำงานที่ดี!! ฉันต้องการเพิ่มการอัปเดตในสิ่งนี้ ก่อนอื่นรูปแบบผลลัพธ์ของ adb มีการเปลี่ยนแปลงเล็กน้อย (ม.ค. 2016) ฉันได้ทดสอบกระบวนการนี้กับอุปกรณ์สองเครื่อง LG Volt 4.4.2 และ Nexus 5x 6.0.1 อุปกรณ์ทั้งสองยังคงประสบกับข้อบกพร่อง ฉันสามารถสร้างปัญหาซ้ำได้โดยใช้ Context.BIND_ABOVE_CLIENT: Proc # 4: cch F / S / SF trm: 0 12354: com.test / u0a78 (fg-service) การใช้แฟล็กที่มีปัญหาจะทำให้ฆ่าทันทีเกือบตลอดเวลาในรุ่นเก่า อุปกรณ์หลังจากออกจากกิจกรรม แฟล็กอื่น ๆ ทั้งหมดดูเหมือนจะใช้ได้กับ Android ทั้งสองเวอร์ชัน
user3259330

1
@ Dave เฮ้ Dave ฉันใช้วิธีนั้นทุกประการและส่งคืน START_STICKY แต่บริการของฉันมักจะตายหลังจากผ่านไปหนึ่งชั่วโมงเมื่ออุปกรณ์ไม่ได้ใช้งาน คุณมีความคิดว่าจะเกิดอะไรขึ้น
บ้างไหม

7

หากมีการพูดว่า "ไม่ต้องการอีกต่อไป ... " แสดงว่ากระบวนการนั้นไม่มีบริการที่ใช้งานอยู่ซึ่งปัจจุบันอยู่ในสถานะ startForeground () ตรวจสอบให้แน่ใจว่าการโทรของคุณประสบความสำเร็จจริง - คุณเห็นการแจ้งเตือนที่โพสต์ไม่มีข้อความในบันทึก ณ จุดนั้นบ่นเกี่ยวกับสิ่งใด ๆ ฯลฯ นอกจากนี้ยังใช้ "adb shell dumpsys activity services" เพื่อดู สถานะของบริการของคุณและตรวจสอบให้แน่ใจว่ามีการทำเครื่องหมายเป็นเบื้องหน้า นอกจากนี้หากอยู่เบื้องหน้าอย่างถูกต้องในผลลัพธ์ของ "adb shell dumpsys activity" คุณจะเห็นในส่วนที่แสดงการปรับ OOM ของกระบวนการที่กระบวนการของคุณอยู่ในระดับเบื้องหน้าเนื่องจากบริการนั้น


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

มีส่วนของโค้ดที่ฉันสามารถโพสต์ที่อาจช่วยในการวินิจฉัยได้หรือไม่?
howettl

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

1
เป็นไปได้ไหมว่าการอัปเดตการแจ้งเตือนที่กำลังดำเนินอยู่โดยการโทรแจ้ง () แทนการโทร startForeground () อีกครั้งอาจทำให้การแจ้งเตือนออกจากสถานะเบื้องหน้าได้ ฉันยังเปิดใช้งาน FLAG_ALERT_ONLY_ONCE ในการแจ้งเตือนหากเป็นเรื่องสำคัญ
howettl

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