एंड्रॉइड एसडीके: बैटरी मैनेजर को नियंत्रित करना
एंड्रॉइड पृष्ठभूमि सेवाओं को आक्रामक तरीके से ख़त्म करने के लिए कुख्यात है। चीनी ओईएम (जैसे Xiaomi, Huawei) के पास कस्टम पावर मैनेजर भी हैं जो मानक एंड्रॉइड पृष्ठभूमि निष्पादन सीमाओं को पूरी तरह से तोड़ देते हैं।
यह पृष्ठ बताता है कि क्यों एंड्रॉइड आपके ऐप को बंद कर देता है और कैसे ट्रैसलेट की विशिष्ट एंड्रॉइड कॉन्फ़िगरेशन वास्तविक दुनिया में इसे हल करती है।
वैकल्पिक निर्भरता: उच्च सटीकता वाला जीएमएस स्थान
ट्रैसलेट का एंड्रॉइड एसडीके Google Play Services Location - FusedLocationProviderClient का उपयोग कर सकता है
(बेहतर सटीकता और बैटरी), हार्डवेयर गतिविधि पहचान (चलना/ड्राइविंग/स्थिर),
और हार्डवेयर जियोफेंसिंग। एसडीके को हल्का और Google-रहित उपकरणों पर उपयोग योग्य बनाए रखने के लिए, यह
निर्भरता बंडल नहीं है। आप इसे केवल तभी जोड़ें यदि आप उच्च-सटीकता पथ चाहते हैं:
// android/app/build.gradle.kts
dependencies {
implementation("com.google.android.gms:play-services-location:21.3.0")
}यह वैकल्पिक है, और SDK शानदार तरीके से ख़राब हो जाता है। play-services-location के बिना, ट्रैसलेट
मानक AOSP LocationManager (सादा जीपीएस) पर वापस आ जाता है। ट्रैकिंग अभी भी काम करती है - बस आप
फ़्यूज्ड प्रदाता की सटीकता/बैटरी लाभ, हार्डवेयर गतिविधि पहचान और हार्डवेयर खो देते हैं
जियोफेंसिंग। अनुशंसित: इसे तब तक जोड़ें जब तक कि आप विशेष रूप से Google-रहित / AOSP उपकरणों को लक्षित न करें
(उदाहरण के लिए जीएमएस के बिना हुआवेई, या डी-गूगल रोम)।
न्यूनतम संस्करण: 21.2.0. ट्रैसलेट का एंड्रॉइड कोड इंटरफ़ेस-आधारित कॉल करता है
FusedLocationProviderClient और ActivityRecognitionClient API, जो केवल बन गए
play-services-location 21.2.0 में इंटरफ़ेस। पुरानी रिलीज़ (जैसे 19.0.0) इन्हें शिप करती हैं
ठोस वर्गों के रूप में, इसलिए उनमें आह्वान करना फेंकता है
रनटाइम पर java.lang.IncompatibleClassChangeError। ट्रैसलेट ने एक ग्रैडल प्रकाशित किया
निर्भरता बाधा जो स्वचालित रूप से play-services-location को 21.2.0+ तक बढ़ा देती है
कोई अन्य निर्भरता पुराने संस्करण को खींचती है, लेकिन यदि आप स्वयं संस्करण को पिन करते हैं, तो इसे चालू रखें
21.2.0 या नया (हम 21.3.0 की अनुशंसा करते हैं)।
play-services-location के साथ | इसके बिना (AOSP फ़ॉलबैक) |
|---|---|
| फ़्यूज्ड स्थान (सर्वोत्तम सटीकता + बैटरी) | LocationManager के माध्यम से कच्चा जीपीएस/नेटवर्क |
हार्डवेयर गतिविधि पहचान (onActivityChange) | एक्सेलेरोमीटर-केवल गति का पता लगाना |
| हार्डवेयर जियोफेंसिंग | सॉफ्टवेयर (इन-एसडीके) जियोफेंस मूल्यांकन |
वैकल्पिक निर्भरता: प्ले इंटीग्रिटी (डिवाइस सत्यापन)
यदि आप ट्रैसलेट की डिवाइस सत्यापन सुविधा (AttestationConfig) का उपयोग करते हैं, तो Android
साइड Google Play इंटीग्रिटी के माध्यम से अपना क्रिप्टोग्राफ़िक टोकन उत्पन्न करता है। ठीक वैसा
play-services-location, यह निर्भरता बंडल नहीं है - आप इसे तभी जोड़ते हैं जब आप
सत्यापन सक्षम करें:
// android/app/build.gradle.kts
dependencies {
implementation("com.google.android.play:integrity:1.6.0")
}यह वैकल्पिक है, और सत्यापन शालीनता से ख़राब हो जाता है। प्ले की सत्यनिष्ठा के बिना
निर्भरता, ट्रैसलेट में बाकी सब कुछ सामान्य रूप से काम करता है - केवल सत्यापन प्रभावित होता है:
AttestationConfig(enabled: true) एक चेतावनी लॉग करता है और Tracelet.getAttestationToken()
क्रैश होने के बजाय, टोकन के बजाय null लौटाता है। निर्भरता तभी जोड़ें जब आप
सत्यापन सक्षम करें और एंड्रॉइड पर प्ले इंटीग्रिटी फैसले की आवश्यकता है। देखें
डिवाइस सत्यापन गाइड
संपूर्ण वर्कफ़्लो और सर्वर-साइड सत्यापन के लिए।
यह implementation होना चाहिए, compileOnly नहीं। प्ले इंटीग्रिटी अंदर compileOnly है
ट्रैसलेट एसडीके (इसलिए इसे कभी भी शिप नहीं किया जाता है या उन ऐप्स पर मजबूर नहीं किया जाता है जो सत्यापन का उपयोग नहीं करते हैं)। अगर
आप अपने ऐप मॉड्यूल में निर्भरता जोड़े बिना सत्यापन सक्षम करते हैं
implementation, कक्षाएं रनटाइम पर अनुपस्थित हैं और सत्यापन चुपचाप null लौटाता है।
अनुमतियाँ एवं प्रकट सेटअप
जब आप अपना ऐप संकलित करते हैं तो ट्रैसलेट स्वचालित रूप से आपके AndroidManifest.xml में आवश्यक अनुमतियाँ इंजेक्ट कर देता है। डिफ़ॉल्ट रूप से, यह अनुरोध करता है:
ACCESS_COARSE_LOCATIONऔरACCESS_FINE_LOCATION(ट्रैकिंग के लिए आवश्यक)ACCESS_BACKGROUND_LOCATION(ऐप बंद होने पर ट्रैकिंग के लिए आवश्यक)FOREGROUND_SERVICEऔरFOREGROUND_SERVICE_LOCATION(निरंतर पृष्ठभूमि निष्पादन के लिए आवश्यक)ACTIVITY_RECOGNITION(स्मार्ट मोशन-डिटेक्शन इंजन के लिए आवश्यक)POST_NOTIFICATIONS(Android 13+ फ़ोरग्राउंड सेवा UI के लिए आवश्यक)SCHEDULE_EXACT_ALARM(सटीक आवधिक मोड ट्रैकिंग के लिए आवश्यक)
अप्रयुक्त अनुमतियाँ हटाना (प्रकट विलय)
यदि आपके ऐप को किसी विशिष्ट सुविधा की आवश्यकता नहीं है (उदाहरण के लिए, आपके क्लाइंट को गति पहचान की आवश्यकता नहीं है, या आप आवधिक मोड का उपयोग नहीं करते हैं), तो आप अपने ऐप-स्तर AndroidManifest.xml (android/app/src/main/AndroidManifest.xml) में एंड्रॉइड के मेनिफेस्ट विलय tools:node="remove" निर्देश का उपयोग करके अनुमति को बलपूर्वक हटा सकते हैं।
ट्रैसलेट का मूल कोड checkSelfPermission() से पूरी तरह सुरक्षित है। अनुपलब्ध अनुमतियाँ शानदार फ़ॉलबैक को ट्रिगर करेंगी, क्रैश नहीं।
| अनुमति | हटाए जाने पर प्रभाव (tools:node="remove") |
|---|---|
ACTIVITY_RECOGNITION | सुरक्षित। केवल बुनियादी एक्सेलेरोमीटर गति पहचान पर वापस आता है। onActivityChange स्ट्रीम चालू नहीं होगी (कोई चलना/दौड़ना/ड्राइविंग वर्गीकरण नहीं)। |
ACCESS_BACKGROUND_LOCATION | सुरक्षित। जब ऐप पूरी तरह से बैकग्राउंड में हो या स्वाइप हो जाए तो एंड्रॉइड 10+ ट्रैकिंग को प्रतिबंधित कर देगा। |
SCHEDULE_EXACT_ALARM | सुरक्षित। आवधिक मोड बैटरी-अनुकूल, लेकिन सटीक, वर्कमैनेजर टाइमर का उपयोग करने के लिए वापस आता है। |
POST_NOTIFICATIONS | सुरक्षित। एंड्रॉइड 13+ पर अग्रभूमि सेवा लगातार अधिसूचना छिपी हुई है। सेवा अभी भी चलती है. |
REQUEST_IGNORE_BATTERY_OPTIMIZATIONS | सुरक्षित। आप ओएस से बैटरी अनुकूलन छूट का अनुरोध नहीं कर पाएंगे। |
FOREGROUND_SERVICE / FOREGROUND_SERVICE_LOCATION | जियोफ़ेंसिंग-केवल / आवधिक-केवल ऐप्स के लिए सुरक्षित। उन्हें हटाने से निरंतर अग्रभूमि ट्रैकिंग (start()) अक्षम हो जाती है, लेकिन मानक जियोफ़ेंसिंग और आवधिक मोड काम करते रहते हैं। निरंतर पृष्ठभूमि ट्रैकिंग के लिए आवश्यक। |
ACCESS_FINE_LOCATION / COARSE | असुरक्षित। किसी भी स्थान की अनुमति के बिना, ट्रेसलेट स्थान प्राप्त नहीं कर सकता। |
Google Play अग्रभूमि-सेवा नीति (28 अक्टूबर, 2026 से प्रभावी)। जियोफेंसिंग है
अग्रभूमि सेवा स्थान के लिए अब अनुमत उपयोग का मामला नहीं है। यदि आपका ऐप a का उपयोग करता है
अग्रभूमि सेवा केवल जियोफेंसिंग के लिए, आपको हटाना होगा
आपके मर्ज से FOREGROUND_SERVICE_LOCATION (और FOREGROUND_SERVICE)।
घोषणापत्र। ट्रैसलेट का मानक जियोफ़ेंस मोड मूल जियोफ़ेंस एपीआई का उपयोग करता है और करता है
नहीं एक फ़ोरग्राउंड सेवा प्रारंभ करें, इसलिए केवल जियोफ़ेंस ऐप्स अनुपालन योग्य हैं - बस
नीचे दी गई अनुमतियाँ छीन लें और foregroundService.enabled = false रखें। देखें
जियोफेंसिंग गाइड
जानकारी के लिए।
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools">
<!-- Geofence-only / periodic-only app: no continuous foreground tracking -->
<uses-permission android:name="android.permission.FOREGROUND_SERVICE_LOCATION" tools:node="remove" />
<uses-permission android:name="android.permission.FOREGROUND_SERVICE" tools:node="remove" />
</manifest>उदाहरण: मोशन और पृष्ठभूमि अनुमतियाँ हटाना
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools">
<!-- Client doesn't want Activity/Motion tracking -->
<uses-permission android:name="android.permission.ACTIVITY_RECOGNITION" tools:node="remove" />
<!-- Client only wants foreground tracking -->
<uses-permission android:name="android.permission.ACCESS_BACKGROUND_LOCATION" tools:node="remove" />
<!-- Remove Exact Alarms -->
<uses-permission android:name="android.permission.SCHEDULE_EXACT_ALARM" tools:node="remove" />
</manifest>स्वचालित प्रोगार्ड/आर8 नियम
ट्रैसलेट बैकग्राउंड कोटलिन सेवाओं, रस्ट कोर के लिए जेएनए बाइंडिंग और रिफ्लेक्टिव पिजन चैनलों का भारी उपयोग करता है। यदि ये अस्पष्ट हैं या गलत तरीके से सिकुड़े हुए हैं, तो जब आपका ऐप रिलीज़ के लिए संकलित किया जाएगा तो पृष्ठभूमि ट्रैकिंग चुपचाप विफल हो जाएगी।
आपको ट्रैसलेट के लिए प्रोगार्ड को मैन्युअल रूप से कॉन्फ़िगर करने की आवश्यकता नहीं है।
tracelet_android प्लगइन स्वचालित रूप से एम्बेडेड consumer-rules.pro के साथ शिप होता है। जब आप अपने फ़्लटर ऐप को रिलीज़ मोड में बनाते हैं, तो एंड्रॉइड का R8 श्रिंकर स्वचालित रूप से इन नियमों को निकालता है और यह सुनिश्चित करता है कि सभी आवश्यक कक्षाएं (जैसे HeadlessTaskService, BootReceiver, और रस्ट uniffi बाइंडिंग) सिकुड़ती रहें।
परिदृश्य 1: डिलीवरी ड्राइवर (निरंतर ट्रैकिंग)
अवधारणाओं की खोज: डोज़ मोड, फ़ोरग्राउंड सेवाएँ, वेकलॉक
समस्या
आपका उपयोगकर्ता पिज़्ज़ा डिलीवरी ड्राइवर है. उन्होंने स्क्रीन बंद करके फोन अपनी जेब में रख लिया। 15 मिनट के बाद, एंड्रॉइड डोज़ मोड में प्रवेश करता है। यह नेटवर्क एक्सेस को बंद कर देता है, पृष्ठभूमि नौकरियों को स्थगित कर देता है, और बैटरी बचाने के लिए सीपीयू वेक-अप को गंभीर रूप से सीमित कर देता है। यदि आपका ऐप जीपीएस प्राप्त करने के लिए एक साधारण टाइमर पर निर्भर है, तो एंड्रॉइड आपके टाइमर को चलाने से इंकार कर देगा।
ट्रैसलेट इसे कैसे हल करता है: फ़ोरग्राउंड सेवा
एक फ़ोरग्राउंड सेवा एंड्रॉइड को बताती है: “अरे, मैं अभी कुछ अविश्वसनीय रूप से महत्वपूर्ण काम कर रहा हूं, और उपयोगकर्ता इसके बारे में पूरी तरह से अवगत है। मुझे मत मारो।”
android: tl.AndroidConfig(
foregroundService: tl.ForegroundServiceConfig(
enabled: true,
channelName: 'Delivery Tracking',
notificationText: 'Tracking your route to the customer',
notificationOngoing: true, // User cannot swipe it away
showNotificationOnPauseOnly: false, // Auto-hides when app is open
actions: ['Pause', 'Complete'], // Adds interactive buttons to the notification
),
)स्टेटस बार में लगातार अधिसूचना दिखाकर, ट्रैसलेट आपके ऐप की प्राथमिकता को लगभग अग्रभूमि यूआई के स्तर तक बढ़ा देता है। एंड्रॉइड डोज़ मोड प्रतिबंधों को दरकिनार करते हुए ट्रेसलेट को अनिश्चित काल तक चलने देगा।
अधिसूचना उपस्थिति को अनुकूलित करना
लगातार अधिसूचना को अपने ऐप की ब्रांडिंग से मेल खाने के लिए, आप आइकन और रंगों को कस्टमाइज़ कर सकते हैं:
android: tl.AndroidConfig(
foregroundService: tl.ForegroundServiceConfig(
enabled: true,
notificationTitle: 'Delivery Mode',
notificationText: 'Tracking your route...',
notificationColor: '#0F9D58', // Your brand hex color
notificationSmallIcon: 'ic_tracelet_icon', // The icon name
notificationLargeIcon: 'ic_large_logo',
),
)महत्वपूर्ण चिह्न नियम:
- फ़ाइल स्थान: छवि फ़ाइल को आपके एंड्रॉइड प्रोजेक्ट के ड्रॉएबल फ़ोल्डर (
android/app/src/main/res/drawable/ic_tracelet_icon.png) में रखा जाना चाहिए। - छोटे आइकन की बाधाएं: एंड्रॉइड के लिए आवश्यक है कि
notificationSmallIconपूरी तरह से सपाट, पारदर्शी और केवल सफेद हो। यदि आप रंगीन लोगो का उपयोग करते हैं, तो एंड्रॉइड इसे केवल एक ठोस ग्रे या सफेद वर्ग के रूप में प्रस्तुत करेगा। - रंग संपत्ति:
notificationColorसंपत्ति आपके ब्रांड से मेल खाने के लिए आपके छोटे आइकन की पृष्ठभूमि को रंग देगी।
एंड्रॉइड 13+ नोट: आपको सेवा शुरू करने से पहले POST_NOTIFICATIONS अनुमति का अनुरोध करना होगा, अन्यथा अधिसूचना ओएस द्वारा चुपचाप दबा दी जाएगी। अपने डार्ट कोड से इसका अनुरोध कैसे करें, इसके लिए फ़्लटर एसडीके: अनुमतियाँ पृष्ठ देखें।
ट्रैकिंग करते समय अधिसूचना को ताज़ा करना (updateNotification())
ट्रैकिंग शुरू होने के बाद में अधिसूचना बदलने की आवश्यकता है - उदाहरण के लिए। शीर्षक को “रास्ते में” से “आ रहा हूँ” में अपडेट करें, टेक्स्ट को स्वैप करें, या यात्रा के बीच में एक्शन बटन बदलें? एक नए ForegroundServiceConfig के साथ setConfig() को कॉल करने से मान बने रहते हैं, लेकिन केवल अधिसूचना परिवर्तन उस अधिसूचना को नहीं करता है जो एंड्रॉइड पहले से ही दिखा रहा है - नई सामग्री केवल एक असंबंधित सेवा पुनरारंभ या अग्रभूमि संक्रमण के बाद ही दिखाई देगी।
चूँकि v3.6.8, Tracelet.updateNotification() लाइव अधिसूचना को उसी स्थान पर ताज़ा करता है, ट्रैकिंग पाइपलाइन को पुनरारंभ किए बिना:
// 1. Apply the new notification content.
await Tracelet.setConfig(
const tl.Config(
android: tl.AndroidConfig(
foregroundService: tl.ForegroundServiceConfig(
notificationTitle: 'Arriving',
notificationText: 'Your driver is 2 minutes away',
),
),
),
);
// 2. Repost the active notification with the new content.
await Tracelet.updateNotification();डिज़ाइन द्वारा सुरक्षित। updateNotification() कभी भी ट्रैकिंग को पुनरारंभ नहीं करता है, और जब अग्रभूमि सेवा वर्तमान में नहीं चल रही है (ताज़ा करने के लिए कुछ भी नहीं है) तो यह एक नो-ऑप है। iOS पर यह इसके बजाय चल रही लाइव एक्टिविटी को रीफ्रेश करता है (जब आपने liveActivityConfig के माध्यम से किसी एक को चुना है); वेब पर यह नो-ऑप है - इसलिए हर प्लेटफ़ॉर्म पर एक ही कॉल सुरक्षित है।
परिदृश्य 2: मौसम ऐप (आवधिक ट्रैकिंग)
अवधारणाओं की खोज: कार्य प्रबंधक बनाम सटीक अलार्म
समस्या
आपके उपयोगकर्ता ने आपका स्थानीय मौसम ऐप डाउनलोड किया है। आप हर 4 घंटे में एक बार पृष्ठभूमि में जागना चाहते हैं, उनका स्थान प्राप्त करना चाहते हैं, और स्थानीय पूर्वानुमान डाउनलोड करना चाहते हैं।
आप स्थायी फ़ोरग्राउंड सेवा अधिसूचना नहीं चाहते हैं। उपयोगकर्ता को अपने दराज में स्थायी “मौसम ट्रैकिंग” अधिसूचना देखना पसंद नहीं आएगा।
ट्रेसलेट इसे कैसे हल करता है: आवधिक मोड
निरंतर सेवा के बजाय, ट्रैसलेट थोड़े समय के लिए जागने, ठीक होने और फिर से सो जाने के लिए एंड्रॉइड के जॉब शेड्यूलर का उपयोग कर सकता है।
android: tl.AndroidConfig(
periodicUseForegroundService: false,
periodicUseExactAlarms: true, // Uses AlarmManager instead of WorkManager
)दो अनुसूचक
-
कार्यप्रबंधक (देर से अनुवाद नहीं) डिफ़ॉल्ट। यह बहुत बैटरी फ्रेंडली है. हालाँकि, एंड्रॉइड यह तय करता है कि उसे कब चलाना है। यदि आप इसे हर 15 मिनट में चलाने के लिए कहते हैं, तो एंड्रॉइड 45 मिनट तक प्रतीक्षा कर सकता है और जब उपयोगकर्ता इंस्टाग्राम (जिसे “बैचिंग” कहा जाता है) की जांच करने के लिए अपने फोन को अनलॉक करता है, तब इसे चलाया जा सकता है। यह अत्यधिक अचूक है.
-
अलार्म मैनेजर (ट्रांस0 लेट) यदि आपको किसी विशिष्ट समय पर डिवाइस को जगाना ही है, तो इसका उपयोग करें। इसके लिए आपको अपने
android/app/src/main/AndroidManifest.xmlमेंSCHEDULE_EXACT_ALARMअनुमति की घोषणा करनी होगी:<uses-permission android:name="android.permission.SCHEDULE_EXACT_ALARM" />
ध्यान दें: Google Play इस अनुमति की कड़ाई से समीक्षा करता है। इसका उपयोग केवल तभी करें जब आपका ऐप एक अलार्म घड़ी, कैलेंडर हो, या बिल्कुल सटीक समय की आवश्यकता हो।
परिदृश्य 3: ओईएम आक्रामकता
अवधारणाओं की खोज: सेटिंग्स स्वास्थ्य एपीआई
समस्या
आपने सब कुछ ठीक किया. आपके पास एक फ़ोरग्राउंड सेवा है. लेकिन यूजर के पास Xiaomi फोन है। MIUI में एक मालिकाना “बैटरी सेवर” है जो 5 मिनट के स्क्रीन-ऑफ समय के बाद फ़ोरग्राउंड सेवाओं को भी बंद कर देता है।
ट्रैसलेट इसे कैसे हल करता है: ऑटो-शमन और संकेत
जहां संभव हो वहां ट्रैसलेट स्वचालित रूप से आंतरिक शमन लागू करता है, लेकिन कभी-कभी उपयोगकर्ता को भौतिक रूप से OEM के मालिकाना सेटिंग्स मेनू में आपके ऐप को श्वेतसूची में डालना पड़ता है।
final health = await tl.Tracelet.getSettingsHealth();
if (health['isAggressiveOem'] == true) {
// Automatically opens the manufacturer-specific settings screen
// (e.g. Xiaomi Autostart, Huawei App Launch, Samsung Sleeping Apps)
await tl.Tracelet.showPowerManager();
}अपने फ़्लटर यूआई में इसे कैसे कार्यान्वित करें इसके विस्तृत उदाहरण के लिए, डायग्नोस्टिक टूल्स एंड पावर मैनेजमेंट पृष्ठ देखें।