android - অ্যান্ড্রয়েড 8.0: java.lang.IllegalStateException: পরিষেবা ইন্টেন্ট শুরু করার অনুমতি নেই




android-service android-8.0-oreo (11)

ওরিওতে অ্যান্ড্রয়েড ব্যাকগ্রাউন্ড পরিষেবাদির সীমাবদ্ধ

ব্যবহারকারীর অভিজ্ঞতা উন্নত করতে, অ্যান্ড্রয়েড 8.0 (এপিআই স্তর 26) পটভূমিতে চলাকালীন অ্যাপগুলি কী করতে পারে তার সীমাবদ্ধতা আরোপ করে।

তবুও যদি আপনার সর্বদা চলমান পরিষেবা প্রয়োজন হয় তবে আপনি অগ্রভাগ পরিষেবাটি ব্যবহার করতে পারেন।

পটভূমি পরিষেবা সীমাবদ্ধতা: একটি অ্যাপ্লিকেশন অলস থাকা অবস্থায়, ব্যাকগ্রাউন্ড পরিষেবাদির ব্যবহারের সীমাবদ্ধতা রয়েছে। এটি অগ্রভাগের পরিষেবাগুলিতে প্রযোজ্য নয় যা ব্যবহারকারীর কাছে আরও লক্ষণীয়।

সুতরাং আপনি একটি অগ্রভাগ পরিষেবা করতে পারেন। আপনার পরিষেবাটি চলমান থাকলে আপনাকে ব্যবহারকারীকে একটি বিজ্ঞপ্তি দেখাতে হবে। এই উত্তরটি দেখুন (আরও অনেকে আছেন)

একটি সমাধান যদি -

আপনি আপনার পরিষেবার জন্য একটি বিজ্ঞপ্তি চান না?

আপনি পর্যায়ক্রমিক কাজটি করতে পারেন, ১. এটি আপনার পরিষেবা শুরু করে, ২. পরিষেবাটি তার কাজ করবে এবং ৩. নিজেই থামবে s এটির মাধ্যমে আপনার অ্যাপ্লিকেশনটি ব্যাটারি নিকাশ হিসাবে বিবেচিত হবে না।

আপনি অ্যালার্ম ম্যানেজার , জব শিডিউলার , Evernote-Jobs বা developer.android.com/topic/libraries/architecture/workmanager সাথে পর্যায়ক্রমে টাস্ক ব্যবহার করতে পারেন।

আমি ওয়ার্ক-ম্যানেজারের সাথে চিরতরে চলমান পরিষেবাটি পরীক্ষা করেছি।

অ্যাপ্লিকেশন আরম্ভের সময়, অ্যাপ্লিকেশন পরিষেবাটি শুরু করে যা কিছু নেটওয়ার্ক টাস্ক করা উচিত। এপিআই স্তরের 26 টি লক্ষ্যবস্তু করার পরে, আমার অ্যাপ্লিকেশন ব্যাকগ্রাউন্ডে অ্যান্ড্রয়েড 8.0 এ পরিষেবা শুরু করতে ব্যর্থ।

এর দ্বারা তৈরি: java.lang.IllegalStateEception: পরিষেবা শুরু করার অনুমতি নেই ইনটেন্ট {সিএমপি = my.app.tt / com.my.service}: অ্যাপ্লিকেশনটি UidRecord এর পটভূমিতে রয়েছে {90372b1 u0a136 সিইএম নিষ্ক্রিয় প্রকস: 1 সেক (0,0 , 0)}

যেহেতু আমি এটি সম্পর্কিত বুঝতে পারি: পটভূমি সম্পাদনের সীমা

স্টার্ট সার্ভিস () পদ্ধতিটি এখন একটি ইলিজালস্টেটএক্সেপশন ছুড়ে দেয় যদি অ্যানড্রয়েড 8.0 টার্গেট করে এমন একটি অ্যাপ এমন পরিস্থিতিতে এমন পদ্ধতিটি ব্যবহার করার চেষ্টা করে যখন এটি ব্যাকগ্রাউন্ড পরিষেবাগুলি তৈরি করার অনুমতি না পায়।

" এমন পরিস্থিতিতে যখন এর অনুমতি নেই " - এর আসলে কী বোঝায় ?? এবং কীভাবে এটি ঠিক করবেন। আমি আমার পরিষেবাটিকে "অগ্রভাগ" হিসাবে সেট করতে চাই না


@ কোসেভ তার উত্তরে যেমন বলেছিলেন আপনি জবআইন্টেন্ট সার্ভিস ব্যবহার করতে পারেন। তবে আমি একটি বিকল্প সমাধান ব্যবহার করি - আমি IllegalStateException ধরি এবং অগ্রভাগ হিসাবে পরিষেবাটি শুরু করি। উদাহরণস্বরূপ, এই ফাংশনটি আমার পরিষেবা শুরু করে:

public class CompressWorker extends Worker {

    public CompressWorker(
        @NonNull Context context,
        @NonNull WorkerParameters params) {
        super(context, params);
    }

    @Override
    public Worker.Result doWork() {

        // Do the work here--in this case, compress the stored images.
        // In this example no parameters are passed; the task is
        // assumed to be "compress the whole library."
        myCompress();

        // Indicate success or failure with your return value:
        return Result.SUCCESS;

        // (Returning RETRY tells WorkManager to try this task again
        // later; FAILURE says not to try again.)
    }
}

এবং যখন আমি অভিপ্রায় প্রক্রিয়াকরণ করি তখন আমি এ জাতীয় কাজটি করি:

    OneTimeWorkRequest compressionWork = 
        new OneTimeWorkRequest.Builder(CompressWorker.class)
            .build();
    WorkManager.getInstance().enqueue(compressionWork);

অনুমোদিত পরিস্থিতি হ'ল অস্থায়ী শ্বেতলিস্ট যেখানে ব্যাকগ্রাউন্ড পরিষেবা অ্যান্ড্রয়েড ও এর আগের মতো আচরণ করে where

নির্দিষ্ট পরিস্থিতিতে, একটি পটভূমি অ্যাপ্লিকেশনটি বেশ কয়েক মিনিটের জন্য অস্থায়ী শ্বেত তালিকাতে রাখা হয়। কোনও অ্যাপ শ্বেতলিস্টে থাকা অবস্থায়, এটি সীমাবদ্ধতা ছাড়াই পরিষেবা চালু করতে পারে এবং এর পটভূমি পরিষেবাগুলি চালনার অনুমতি দেওয়া হয়। কোনও অ্যাপ্লিকেশন শ্বেতলিস্টে রাখা হয় যখন এটি কোনও ব্যবহারকারীর কাছে দৃশ্যমান কোনও কাজ পরিচালনা করে যেমন:

  • একটি উচ্চ-অগ্রাধিকার ফায়ারবেস ক্লাউড মেসেজিং (এফসিএম) বার্তা হ্যান্ডলিং।
  • একটি সম্প্রচার যেমন কোনও এসএমএস / এমএমএস বার্তা গ্রহণ করা।
  • একটি বিজ্ঞপ্তি থেকে একটি পেন্ডিং ইন্টেন্ট কার্যকর করা হচ্ছে।
  • ভিপিএন অ্যাপ্লিকেশনটি নিজেকে অগ্রভাগে প্রচার করার আগে একটি ভিপিএন সার্ভিস শুরু করা।

উত্স: https://developer.android.com/about/versions/oreo/background.html

সুতরাং অন্য কথায় যদি আপনার ব্যাকগ্রাউন্ড পরিষেবাটি যদি হোয়াইটলিস্টের প্রয়োজনীয়তা পূরণ করে না তবে আপনাকে নতুন JobScheduler ব্যবহার করতে হবে। এটি মূলত একটি পটভূমি পরিষেবা হিসাবে একই, তবে এটি ধারাবাহিকভাবে ব্যাকগ্রাউন্ডে চালানোর পরিবর্তে বলা হয়ে থাকে।

আপনি যদি কোনও ইনসেন্ট সার্ভিস ব্যবহার করছেন তবে আপনি একটি জবআইন্টেন্ট সার্ভিসে পরিবর্তন করতে পারেন। নীচে @ কোসেভের উত্তর দেখুন ।


অন্যান্য উত্তরগুলি সমস্ত সঠিক, তবে আমি এটি উল্লেখ করতে চাই যে এটিকে ঘুরিয়ে নেওয়ার আরেকটি উপায় হ'ল ব্যবহারকারীকে আপনার অ্যাপের জন্য ব্যাটারি অপ্টিমাইজেশন অক্ষম করতে বলা (আপনার অ্যাপটি সিস্টেম সম্পর্কিত না হলে এটি সাধারণত একটি ভাল ধারণা নয়)। গুগল প্লেতে আপনার অ্যাপ্লিকেশনটিকে নিষিদ্ধ না করে কীভাবে ব্যাটারি অপ্টিমাইজেশানগুলি থেকে বেরিয়ে আসার অনুরোধ করবেন এই উত্তরটি দেখুন।

এর মাধ্যমে ক্র্যাশগুলি রোধ করতে আপনার রিসিভারে ব্যাটারি অপ্টিমাইজেশন বন্ধ আছে কিনা তাও আপনার পরীক্ষা করা উচিত:

if (Build.VERSION.SDK_INT < 26 || getSystemService<PowerManager>()
        ?.isIgnoringBatteryOptimizations(packageName) != false) {
    startService(Intent(context, MyService::class.java))
} // else calling startService will result in crash

আপনি যদি 8.0 তে আপনার কোড চালাচ্ছেন তবে অ্যাপ্লিকেশনটি ক্রাশ হবে। তাই অগ্রভাগে পরিষেবাটি শুরু করুন। 8.0 এর নীচে থাকলে এটি ব্যবহার করুন:

Intent serviceIntent = new Intent(context, RingtonePlayingService.class);
context.startService(serviceIntent);

যদি উপরে বা 8.0 থাকে তবে এটি ব্যবহার করুন:

Intent serviceIntent = new Intent(context, RingtonePlayingService.class);
ContextCompat.startForegroundService(context, serviceIntent );

আপনি যদি ইন্টিগ্রেটেড ফায়ারবেস মেসেজিং পুশ নোটিফিকেশন পেয়ে থাকেন তবে,

https://developer.android.com/about/versions/oreo/background.html কারণে অ্যান্ড্রয়েড ও (অ্যান্ড্রয়েড 8.0) এর জন্য নতুন / আপডেট ফায়ারবেস মেসেজিং নির্ভরতা যুক্ত করুন।

compile 'com.google.firebase:firebase-messaging:11.4.0'

প্রয়োজনে গুগল প্লে পরিষেবাদি এবং গুগল সংগ্রহস্থলগুলি আপগ্রেড করুন।

হালনাগাদ:

 compile 'com.google.firebase:firebase-messaging:11.4.2'

আমি মনে করি এটির সর্বোত্তম উপায়টি রান টাইমে বিল্ড সংস্করণটি পরীক্ষা করা এবং তার উপর নির্ভর করে যদি এটি এপি স্তরের চেয়ে কম 21 হয় তবে স্টার্ট সার্ভিস () ব্যবহার চালিয়ে যান। তবে এটি বেশি হলে আপনার একটি কাজের শিডিয়ুলার ব্যবহার করা উচিত। আমার ধারণা আপনি কাজ পরিচালকের পাশাপাশি ব্যবহার করতে পারেন তবে এটি এখনও বিটা পর্যায়ে রয়েছে


আমি সমাধান পেয়েছি। প্রাক startService() ডিভাইসগুলির জন্য, আপনাকে কেবল startService() ব্যবহার করতে হবে, কিন্তু 7.0-পরবর্তী ডিভাইসের জন্য আপনাকে startForgroundService() ব্যবহার করতে হবে। পরিষেবাটি শুরু করার জন্য কোডের নমুনা এখানে।

if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
        context.startForegroundService(new Intent(context, ServedService.class));
    } else {
        context.startService(new Intent(context, ServedService.class));
    }

এবং পরিষেবা শ্রেণিতে, দয়া করে নীচের কোডটি বিজ্ঞপ্তির জন্য যুক্ত করুন:

@Override
public void onCreate() {
    super.onCreate();
    startForeground(1,new Notification());
}

যেখানে হে অ্যান্ড্রয়েড সংস্করণ 26।


সর্বোত্তম উপায় হ'ল JobIntentService ব্যবহার করা যা ওরিওর জন্য নতুন জবশেডুলার ব্যবহার করে বা না পাওয়া গেলে পুরানো পরিষেবাদি ব্যবহার করে।

আপনার ম্যানিফেস্টে ঘোষণা করুন:

<service android:name=".YourService"
         android:permission="android.permission.BIND_JOB_SERVICE"/>

এবং আপনার পরিষেবাতে আপনাকে হ্যান্ডলআইরেক্টকে হ্যান্ডল ওয়ার্কের সাথে প্রতিস্থাপন করতে হবে:

public class YourService extends JobIntentService {

    public static final int JOB_ID = 1;

    public static void enqueueWork(Context context, Intent work) {
        enqueueWork(context, YourService.class, JOB_ID, work);
    }

    @Override
    protected void onHandleWork(@NonNull Intent intent) {
        // your code
    }

}

তারপরে আপনি আপনার পরিষেবাটি দিয়ে শুরু করবেন:

YourService.enqueueWork(context, new Intent());

হ্যাঁ, কারণ আপনি এপিআই 26-তে আর কোনও পটভূমিতে পরিষেবা শুরু করতে পারবেন না So

আপনি ব্যবহার করতে হবে

ContextCompat.startForegroundService(...)

এবং ফাঁস প্রক্রিয়া করার সময় একটি বিজ্ঞপ্তি পোস্ট করুন।


startForegroundService() পরিবর্তে startForegroundService() ব্যবহার করুন এবং startForeground(1,new Notification()); তৈরি করতে ভুলবেন না startForeground(1,new Notification()); পরিষেবাটি শুরু করার 5 সেকেন্ডের মধ্যে আপনার পরিষেবাতে।





android-8.0-oreo