ব্যাকগ্রাউন্ড প্রসেসগুলি মেমোরি- এবং ব্যাটারি-নিবিড় হতে পারে। উদাহরণস্বরূপ, একটি অন্তর্নিহিত সম্প্রচার অনেক ব্যাকগ্রাউন্ড প্রসেস শুরু করতে পারে যারা এটি শোনার জন্য নিবন্ধিত হয়েছে, এমনকি যদি সেই প্রসেসগুলি খুব বেশি কাজ নাও করতে পারে। এটি ডিভাইসের কর্মক্ষমতা এবং ব্যবহারকারীর অভিজ্ঞতা উভয়ের উপরই যথেষ্ট প্রভাব ফেলতে পারে।
এই সমস্যাটি দূর করতে, Android 7.0 (API লেভেল 24) নিম্নলিখিত বিধিনিষেধগুলি প্রয়োগ করে:
- Android 7.0 (API লেভেল 24) এবং উচ্চতর ভার্সনগুলিকে লক্ষ্য করে এমন অ্যাপগুলি
CONNECTIVITY_ACTIONসম্প্রচার গ্রহণ করে না যদি তারা ম্যানিফেস্টে তাদের ব্রডকাস্ট রিসিভার ঘোষণা করে। অ্যাপগুলি এখনওCONNECTIVITY_ACTIONসম্প্রচার গ্রহণ করবে যদি তারা তাদেরBroadcastReceiverContext.registerReceiver()এর সাথে নিবন্ধিত করে এবং সেই প্রসঙ্গটি এখনও বৈধ থাকে। - অ্যাপগুলি
ACTION_NEW_PICTUREবাACTION_NEW_VIDEOসম্প্রচার পাঠাতে বা গ্রহণ করতে পারে না। এই অপ্টিমাইজেশনটি সমস্ত অ্যাপকে প্রভাবিত করে, শুধুমাত্র Android 7.0 (API লেভেল 24) লক্ষ্য করে এমন অ্যাপগুলিকে নয়।
যদি আপনার অ্যাপ এইসব উদ্দেশ্য ব্যবহার করে, তাহলে যত তাড়াতাড়ি সম্ভব তাদের উপর নির্ভরতা দূর করা উচিত যাতে আপনি Android 7.0 বা তার বেশি চলমান ডিভাইসগুলিকে সঠিকভাবে লক্ষ্য করতে পারেন। এই অন্তর্নিহিত সম্প্রচারের প্রয়োজনীয়তা কমাতে Android ফ্রেমওয়ার্ক বেশ কয়েকটি সমাধান প্রদান করে। উদাহরণস্বরূপ, JobScheduler এবং নতুন WorkManager নির্দিষ্ট শর্ত পূরণ হলে নেটওয়ার্ক ক্রিয়াকলাপ নির্ধারণের জন্য শক্তিশালী প্রক্রিয়া প্রদান করে, যেমন একটি অ-মিটারযুক্ত নেটওয়ার্কের সাথে সংযোগ, পূরণ করা হয়। আপনি এখন কন্টেন্ট প্রদানকারীদের পরিবর্তনের প্রতিক্রিয়া জানাতে JobScheduler ব্যবহার করতে পারেন। JobInfo অবজেক্টগুলি আপনার কাজের সময় নির্ধারণের জন্য JobScheduler যে প্যারামিটারগুলি ব্যবহার করে তা ধারণ করে। কাজের শর্ত পূরণ হলে, সিস্টেমটি আপনার অ্যাপের JobService এ এই কাজটি সম্পাদন করে।
এই পৃষ্ঠায়, আমরা শিখব কিভাবে JobScheduler এর মতো বিকল্প পদ্ধতি ব্যবহার করে আপনার অ্যাপটিকে এই নতুন বিধিনিষেধের সাথে খাপ খাইয়ে নিতে হয়।
ব্যবহারকারী-প্রবর্তিত বিধিনিষেধ
সিস্টেম সেটিংসের মধ্যে ব্যাটারি ব্যবহার পৃষ্ঠায় , ব্যবহারকারী নিম্নলিখিত বিকল্পগুলি থেকে বেছে নিতে পারেন:
- সীমাবদ্ধতাহীন: সমস্ত ব্যাকগ্রাউন্ড কাজ করার অনুমতি দিন, যা আরও বেশি ব্যাটারি খরচ করতে পারে।
- অপ্টিমাইজড (ডিফল্ট): ব্যবহারকারী অ্যাপটির সাথে কীভাবে ইন্টারঅ্যাক্ট করে তার উপর ভিত্তি করে ব্যাকগ্রাউন্ডে কাজ করার জন্য একটি অ্যাপের ক্ষমতা অপ্টিমাইজ করুন।
- সীমাবদ্ধ: কোনও অ্যাপকে ব্যাকগ্রাউন্ডে চলতে সম্পূর্ণরূপে বাধা দেয়। অ্যাপগুলি প্রত্যাশা অনুযায়ী কাজ নাও করতে পারে।
যদি কোনও অ্যাপ অ্যান্ড্রয়েড ভাইটালসে বর্ণিত কিছু খারাপ আচরণ প্রদর্শন করে, তাহলে সিস্টেম ব্যবহারকারীকে সেই অ্যাপের সিস্টেম রিসোর্সে অ্যাক্সেস সীমিত করতে অনুরোধ করতে পারে।
যদি সিস্টেম লক্ষ্য করে যে কোনও অ্যাপ অতিরিক্ত রিসোর্স ব্যবহার করছে, তাহলে এটি ব্যবহারকারীকে অবহিত করে এবং ব্যবহারকারীকে অ্যাপের ক্রিয়াকলাপ সীমাবদ্ধ করার বিকল্প দেয়। যেসব আচরণের কারণে নোটিশটি ট্রিগার হতে পারে তার মধ্যে রয়েছে:
- অতিরিক্ত ওয়েক লক: স্ক্রিন বন্ধ থাকা অবস্থায় ১টি আংশিক ওয়েক লক এক ঘন্টা ধরে রাখা হয়
- অতিরিক্ত ব্যাকগ্রাউন্ড পরিষেবা: যদি অ্যাপটি ২৬-এর কম API লেভেলের লক্ষ্যবস্তু করে এবং অতিরিক্ত ব্যাকগ্রাউন্ড পরিষেবা প্রদান করে
আরোপিত সুনির্দিষ্ট বিধিনিষেধগুলি ডিভাইস প্রস্তুতকারক দ্বারা নির্ধারিত হয়। উদাহরণস্বরূপ, Android 9 (API লেভেল 28) বা তার বেশি চালিত AOSP বিল্ডগুলিতে, ব্যাকগ্রাউন্ডে চলমান "সীমাবদ্ধ" অবস্থায় থাকা অ্যাপগুলির নিম্নলিখিত সীমাবদ্ধতা রয়েছে:
- ফোরগ্রাউন্ড পরিষেবা চালু করা যাচ্ছে না
- বিদ্যমান ফোরগ্রাউন্ড পরিষেবাগুলি ফোরগ্রাউন্ড থেকে সরানো হয়েছে
- অ্যালার্মগুলি চালু হয় না
- কাজগুলি সম্পন্ন হয় না
এছাড়াও, যদি কোনও অ্যাপ অ্যান্ড্রয়েড ১৩ (এপিআই লেভেল ৩৩) বা তার উচ্চতর সংস্করণকে লক্ষ্য করে এবং "সীমাবদ্ধ" অবস্থায় থাকে, তাহলে অন্যান্য কারণে অ্যাপটি শুরু না হওয়া পর্যন্ত সিস্টেমটি BOOT_COMPLETED সম্প্রচার বা LOCKED_BOOT_COMPLETED সম্প্রচার সরবরাহ করে না।
নির্দিষ্ট বিধিনিষেধগুলি পাওয়ার ম্যানেজমেন্ট বিধিনিষেধগুলিতে তালিকাভুক্ত করা হয়েছে।
নেটওয়ার্ক কার্যকলাপ সম্প্রচার গ্রহণের উপর বিধিনিষেধ
অ্যান্ড্রয়েড ৭.০ (এপিআই লেভেল ২৪) অপারেটিং সিস্টেমের অ্যাপগুলো যদি তাদের ম্যানিফেস্টে CONNECTIVITY_ACTION ব্রডকাস্ট গ্রহণের জন্য নিবন্ধিত হয়, তাহলে তারা তা গ্রহণ করে না এবং এই ব্রডকাস্টের উপর নির্ভরশীল প্রক্রিয়াগুলি শুরু হবে না। এটি এমন অ্যাপগুলির জন্য সমস্যা তৈরি করতে পারে যারা নেটওয়ার্ক পরিবর্তন শুনতে চায় অথবা ডিভাইসটি যখন একটি অ-মিটারযুক্ত নেটওয়ার্কের সাথে সংযুক্ত হয় তখন বাল্ক নেটওয়ার্ক কার্যকলাপ সম্পাদন করতে চায়। এই সীমাবদ্ধতা এড়াতে অ্যান্ড্রয়েড ফ্রেমওয়ার্কে ইতিমধ্যেই বেশ কয়েকটি সমাধান রয়েছে, তবে সঠিকটি নির্বাচন করা আপনার অ্যাপটি কী অর্জন করতে চায় তার উপর নির্ভর করে।
দ্রষ্টব্য: Context.registerReceiver() এর সাথে নিবন্ধিত একটি BroadcastReceiver অ্যাপটি চলাকালীন এই সম্প্রচারগুলি গ্রহণ করতে থাকে।
মিটারবিহীন সংযোগে নেটওয়ার্ক কাজ নির্ধারণ করুন
JobInfo.Builder ক্লাস ব্যবহার করে আপনার JobInfo অবজেক্ট তৈরি করার সময়, setRequiredNetworkType() পদ্ধতিটি প্রয়োগ করুন এবং JobInfo.NETWORK_TYPE_UNMETERED একটি জব প্যারামিটার হিসেবে পাস করুন। নিম্নলিখিত কোড নমুনাটি ডিভাইসটি একটি অ-মিটারযুক্ত নেটওয়ার্কের সাথে সংযুক্ত হলে এবং চার্জিং করার সময় একটি পরিষেবা চালানোর সময়সূচী নির্ধারণ করে:
কোটলিন
const val MY_BACKGROUND_JOB = 0 ... fun scheduleJob(context: Context) { val jobScheduler = context.getSystemService(Context.JOB_SCHEDULER_SERVICE) as JobScheduler val job = JobInfo.Builder( MY_BACKGROUND_JOB, ComponentName(context, MyJobService::class.java) ) .setRequiredNetworkType(JobInfo.NETWORK_TYPE_UNMETERED) .setRequiresCharging(true) .build() jobScheduler.schedule(job) }
জাভা
public static final int MY_BACKGROUND_JOB = 0; ... public static void scheduleJob(Context context) { JobScheduler js = (JobScheduler) context.getSystemService(Context.JOB_SCHEDULER_SERVICE); JobInfo job = new JobInfo.Builder( MY_BACKGROUND_JOB, new ComponentName(context, MyJobService.class)) .setRequiredNetworkType(JobInfo.NETWORK_TYPE_UNMETERED) .setRequiresCharging(true) .build(); js.schedule(job); }
যখন আপনার কাজের শর্তাবলী পূরণ করা হয়, তখন আপনার অ্যাপটি নির্দিষ্ট JobService.class এ onStartJob() পদ্ধতি চালানোর জন্য একটি কলব্যাক পায়। JobScheduler বাস্তবায়নের আরও উদাহরণ দেখতে, JobScheduler নমুনা অ্যাপটি দেখুন।
JobScheduler এর একটি নতুন বিকল্প হল WorkManager, একটি API যা আপনাকে ব্যাকগ্রাউন্ডের কাজগুলি নির্ধারণ করতে দেয় যা নিশ্চিতভাবে সম্পন্ন করার প্রয়োজন হয়, অ্যাপ প্রক্রিয়াটি আসন্ন থাকুক বা না থাকুক। WorkManager ডিভাইস API স্তরের মতো বিষয়গুলির উপর ভিত্তি করে কাজটি চালানোর জন্য উপযুক্ত উপায় বেছে নেয় (আপনার অ্যাপ প্রক্রিয়ার একটি থ্রেডে সরাসরি এবং JobScheduler, FirebaseJobDispatcher, অথবা AlarmManager ব্যবহার করে)। অতিরিক্তভাবে, WorkManager-এর জন্য Play পরিষেবার প্রয়োজন হয় না এবং এটি বেশ কয়েকটি উন্নত বৈশিষ্ট্য প্রদান করে, যেমন কাজগুলিকে একসাথে চেইন করা বা কোনও কাজের স্থিতি পরীক্ষা করা। আরও জানতে, WorkManager দেখুন।
অ্যাপটি চলাকালীন নেটওয়ার্ক সংযোগ পর্যবেক্ষণ করুন
চলমান অ্যাপগুলি এখনও একটি নিবন্ধিত BroadcastReceiver দিয়ে CONNECTIVITY_CHANGE শুনতে পারে। তবে, ConnectivityManager API শুধুমাত্র নির্দিষ্ট নেটওয়ার্ক শর্ত পূরণ হলেই কলব্যাকের অনুরোধ করার জন্য আরও শক্তিশালী পদ্ধতি প্রদান করে।
NetworkRequest অবজেক্টগুলি NetworkCapabilities এর পরিপ্রেক্ষিতে নেটওয়ার্ক কলব্যাকের প্যারামিটারগুলি সংজ্ঞায়িত করে। আপনি NetworkRequest.Builder ক্লাস ব্যবহার করে NetworkRequest অবজেক্ট তৈরি করেন। registerNetworkCallback() তারপর NetworkRequest অবজেক্টটি সিস্টেমে প্রেরণ করে। নেটওয়ার্কের শর্ত পূরণ হলে, অ্যাপটি তার ConnectivityManager.NetworkCallback ক্লাসে সংজ্ঞায়িত onAvailable() পদ্ধতিটি কার্যকর করার জন্য একটি কলব্যাক পায়।
অ্যাপটি কলব্যাক পেতে থাকে যতক্ষণ না অ্যাপটি প্রস্থান করে অথবা unregisterNetworkCallback() কল করে।
ছবি এবং ভিডিও সম্প্রচার গ্রহণের উপর বিধিনিষেধ
অ্যান্ড্রয়েড ৭.০ (এপিআই লেভেল ২৪) তে, অ্যাপগুলি ACTION_NEW_PICTURE বা ACTION_NEW_VIDEO সম্প্রচার পাঠাতে বা গ্রহণ করতে সক্ষম হয় না। এই সীমাবদ্ধতা কর্মক্ষমতা এবং ব্যবহারকারীর অভিজ্ঞতার প্রভাব কমাতে সাহায্য করে যখন একটি নতুন ছবি বা ভিডিও প্রক্রিয়া করার জন্য বেশ কয়েকটি অ্যাপকে সক্রিয় করতে হয়। অ্যান্ড্রয়েড ৭.০ (এপিআই লেভেল ২৪) বিকল্প সমাধান প্রদানের জন্য JobInfo এবং JobParameters প্রসারিত করে।
কন্টেন্ট URI পরিবর্তনের ক্ষেত্রে কাজ ট্রিগার করুন
কন্টেন্ট URI পরিবর্তনের ক্ষেত্রে কাজ শুরু করতে, Android 7.0 (API লেভেল 24) নিম্নলিখিত পদ্ধতিগুলি ব্যবহার করে JobInfo API প্রসারিত করে:
-
JobInfo.TriggerContentUri() - কন্টেন্ট URI পরিবর্তনের উপর একটি কাজ ট্রিগার করার জন্য প্রয়োজনীয় প্যারামিটারগুলিকে এনক্যাপসুলেট করে।
-
JobInfo.Builder.addTriggerContentUri() - একটি
TriggerContentUriঅবজেক্টJobInfoতে পাস করে। একটিContentObserverএনক্যাপসুলেটেড কন্টেন্ট URI পর্যবেক্ষণ করে। যদি কোনও কাজের সাথে একাধিকTriggerContentUriঅবজেক্ট যুক্ত থাকে, তাহলে সিস্টেমটি শুধুমাত্র একটি কন্টেন্ট URI-তে পরিবর্তনের রিপোর্ট করলেও কলব্যাক প্রদান করে। - প্রদত্ত URI-এর কোনও ডিসেন্ডেন্ট পরিবর্তন হলে কাজটি ট্রিগার করতে
TriggerContentUri.FLAG_NOTIFY_FOR_DESCENDANTSফ্ল্যাগ যোগ করুন। এই ফ্ল্যাগটিregisterContentObserver()এ পাস করাnotifyForDescendantsপ্যারামিটারের সাথে সঙ্গতিপূর্ণ।
দ্রষ্টব্য: TriggerContentUri() setPeriodic() অথবা setPersisted() এর সাথে একত্রে ব্যবহার করা যাবে না। কন্টেন্ট পরিবর্তনের জন্য ক্রমাগত নজরদারি করার জন্য, অ্যাপের JobService সাম্প্রতিকতম কলব্যাক পরিচালনা শেষ করার আগে একটি নতুন JobInfo নির্ধারণ করুন।
নিম্নলিখিত নমুনা কোডটি একটি কাজকে ট্রিগার করার সময়সূচী করে যখন সিস্টেম কন্টেন্ট URI, MEDIA_URI তে কোনও পরিবর্তনের রিপোর্ট করে:
কোটলিন
const val MY_BACKGROUND_JOB = 0 ... fun scheduleJob(context: Context) { val jobScheduler = context.getSystemService(Context.JOB_SCHEDULER_SERVICE) as JobScheduler val job = JobInfo.Builder( MY_BACKGROUND_JOB, ComponentName(context, MediaContentJob::class.java) ) .addTriggerContentUri( JobInfo.TriggerContentUri( MediaStore.Images.Media.EXTERNAL_CONTENT_URI, JobInfo.TriggerContentUri.FLAG_NOTIFY_FOR_DESCENDANTS ) ) .build() jobScheduler.schedule(job) }
জাভা
public static final int MY_BACKGROUND_JOB = 0; ... public static void scheduleJob(Context context) { JobScheduler js = (JobScheduler) context.getSystemService(Context.JOB_SCHEDULER_SERVICE); JobInfo.Builder builder = new JobInfo.Builder( MY_BACKGROUND_JOB, new ComponentName(context, MediaContentJob.class)); builder.addTriggerContentUri( new JobInfo.TriggerContentUri(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, JobInfo.TriggerContentUri.FLAG_NOTIFY_FOR_DESCENDANTS)); js.schedule(builder.build()); }
যখন সিস্টেম নির্দিষ্ট কন্টেন্ট URI(গুলি) তে পরিবর্তনের রিপোর্ট করে, তখন আপনার অ্যাপটি একটি কলব্যাক পায় এবং একটি JobParameters অবজেক্ট MediaContentJob.class এর onStartJob() পদ্ধতিতে পাস করা হয়।
কোন কন্টেন্ট কর্তৃপক্ষ একটি কাজ শুরু করেছে তা নির্ধারণ করুন
অ্যান্ড্রয়েড ৭.০ (এপিআই লেভেল ২৪) JobParameters প্রসারিত করে যাতে আপনার অ্যাপটি কোন কন্টেন্ট কর্তৃপক্ষ এবং ইউআরআই দ্বারা কাজটি শুরু হয়েছিল সে সম্পর্কে দরকারী তথ্য পেতে পারে:
-
Uri[] getTriggeredContentUris() - কাজটি ট্রিগার করেছে এমন URI-এর একটি অ্যারে ফেরত পাঠায়। যদি কোনও URI কাজটি ট্রিগার না করে থাকে (উদাহরণস্বরূপ, কাজটি একটি নির্দিষ্ট সময়সীমার কারণে বা অন্য কোনও কারণে ট্রিগার করা হয়েছে), অথবা পরিবর্তিত URI-এর সংখ্যা 50-এর বেশি হয় তবে এটি
nullহবে। -
String[] getTriggeredContentAuthorities() - কাজটি ট্রিগার করা কন্টেন্ট অথরিটির একটি স্ট্রিং অ্যারে রিটার্ন করে। যদি রিটার্ন করা অ্যারে
nullনা হয়, তাহলে কোন URI গুলি পরিবর্তিত হয়েছে তার বিবরণ পুনরুদ্ধার করতেgetTriggeredContentUris()ব্যবহার করুন।
নিম্নলিখিত নমুনা কোডটি JobService.onStartJob() পদ্ধতিকে ওভাররাইড করে এবং কাজটি ট্রিগারকারী কন্টেন্ট কর্তৃপক্ষ এবং URI গুলি রেকর্ড করে:
কোটলিন
override fun onStartJob(params: JobParameters): Boolean { StringBuilder().apply { append("Media content has changed:\n") params.triggeredContentAuthorities?.also { authorities -> append("Authorities: ${authorities.joinToString(", ")}\n") append(params.triggeredContentUris?.joinToString("\n")) } ?: append("(No content)") Log.i(TAG, toString()) } return true }
জাভা
@Override public boolean onStartJob(JobParameters params) { StringBuilder sb = new StringBuilder(); sb.append("Media content has changed:\n"); if (params.getTriggeredContentAuthorities() != null) { sb.append("Authorities: "); boolean first = true; for (String auth : params.getTriggeredContentAuthorities()) { if (first) { first = false; } else { sb.append(", "); } sb.append(auth); } if (params.getTriggeredContentUris() != null) { for (Uri uri : params.getTriggeredContentUris()) { sb.append("\n"); sb.append(uri); } } } else { sb.append("(No content)"); } Log.i(TAG, sb.toString()); return true; }
আপনার অ্যাপটি আরও অপ্টিমাইজ করুন
কম মেমোরি ডিভাইসে অথবা কম মেমোরি অবস্থায় চালানোর জন্য আপনার অ্যাপগুলিকে অপ্টিমাইজ করলে কর্মক্ষমতা এবং ব্যবহারকারীর অভিজ্ঞতা উন্নত হতে পারে। ব্যাকগ্রাউন্ড পরিষেবা এবং ম্যানিফেস্ট-রেজিস্টার্ড ইমপ্লিসিট ব্রডকাস্ট রিসিভারের উপর নির্ভরতা অপসারণ করলে আপনার অ্যাপটি এই ধরনের ডিভাইসগুলিতে আরও ভালোভাবে চলতে সাহায্য করতে পারে। যদিও অ্যান্ড্রয়েড 7.0 (API লেভেল 24) এই সমস্যাগুলির কিছু কমাতে পদক্ষেপ নেয়, তবুও এই ব্যাকগ্রাউন্ড প্রক্রিয়াগুলি সম্পূর্ণরূপে ব্যবহার না করেই চালানোর জন্য আপনার অ্যাপটিকে অপ্টিমাইজ করার পরামর্শ দেওয়া হচ্ছে।
নিম্নলিখিত অ্যান্ড্রয়েড ডিবাগ ব্রিজ (ADB) কমান্ডগুলি আপনাকে ব্যাকগ্রাউন্ড প্রক্রিয়াগুলি অক্ষম থাকা অবস্থায় অ্যাপ আচরণ পরীক্ষা করতে সাহায্য করতে পারে:
- অন্তর্নিহিত সম্প্রচার এবং পটভূমি পরিষেবা অনুপলব্ধ এমন পরিস্থিতি অনুকরণ করতে, নিম্নলিখিত কমান্ডটি প্রবেশ করান:
$ adb shell cmd appops set <package_name> RUN_IN_BACKGROUND ignore- অন্তর্নিহিত সম্প্রচার এবং পটভূমি পরিষেবা পুনরায় সক্ষম করতে, নিম্নলিখিত কমান্ডটি প্রবেশ করান:
$ adb shell cmd appops set <package_name> RUN_IN_BACKGROUND allow- ব্যাকগ্রাউন্ড ব্যাটারি ব্যবহারের জন্য ব্যবহারকারী আপনার অ্যাপটিকে "সীমাবদ্ধ" অবস্থায় রেখে সিমুলেট করতে পারেন। এই সেটিংটি আপনার অ্যাপটিকে ব্যাকগ্রাউন্ডে চলতে বাধা দেয়। এটি করার জন্য, একটি টার্মিনাল উইন্ডোতে নিম্নলিখিত কমান্ডটি চালান:
$ adb shell cmd appops set <PACKAGE_NAME> RUN_ANY_IN_BACKGROUND deny