android - অ্যান্ড্রয়েড 9.0: পরিষেবা শুরু করার অনুমতি নেই: অ্যাপ্লিকেশনটি পটভূমিতে রয়েছে... অন রেসুমির পরে()




android-service android-9.0-pie (4)

আমার কাছে এমন একটি মিউজিক প্লেয়ার রয়েছে যা একটি Activity onResume() Service শুরু করার চেষ্টা করে। আমি স্পষ্টতার জন্য কয়েকটি লাইন সরিয়েছি, তবে কোডটি কার্যকরভাবে রয়েছে:

@Override
protected void onResume() {
    super.onResume();

    startService(new Intent(this, MusicService.class));
}

ক্র্যাশ লগগুলির মতে, এটি অ্যান্ড্রয়েড পি চালিত কিছু ডিভাইসে ব্যতিক্রম ছুঁড়ে ফেলছে:

Caused by java.lang.IllegalStateException: Not allowed to start service Intent { cmp=another.music.player/com.simplecity.amp_library.playback.MusicService }: app is in background uid UidRecord{6a4a9c6 u0a143 TPSL bg:+3m25s199ms idle change:cached procs:1 seq(1283,1283,1283)}
       at android.app.ContextImpl.startServiceCommon(ContextImpl.java:1577)
       at android.app.ContextImpl.startService(ContextImpl.java:1532)
       at android.content.ContextWrapper.startService(ContextWrapper.java:664)
       at android.content.ContextWrapper.startService(ContextWrapper.java:664)
       at com.simplecity.amp_library.utils.MusicServiceConnectionUtils.bindToService(SourceFile:36)
       at com.simplecity.amp_library.ui.activities.BaseActivity.bindService(SourceFile:129)
       at com.simplecity.amp_library.ui.activities.BaseActivity.onResume(SourceFile:96)

onResume() এবং super.onResume() ) বলা হওয়ার সাথে সাথেই কীভাবে আমার অ্যাপটি পটভূমিতে রয়েছে?

এটি আমার কোনও অর্থবোধ করে না। এটি কি প্ল্যাটফর্ম বাগ হতে পারে? এই ক্র্যাশ দ্বারা আক্রান্ত সমস্ত 3500+ ব্যবহারকারী অ্যান্ড্রয়েড পিতে আছেন।


আপডেট: এটি প্রোডে আমাদের জন্য কাজ করছে, তবে এটি 100% নয়। আমি গত দেড় মাস ধরে একটি ক্র্যাশ প্রতিবেদন পেয়েছি যখন অন্যথায় যদি একশটিরও বেশি ভাল হত। এটি যথাযথভাবে স্থির না হওয়া পর্যন্ত এটি আপাতত আমাদের সেরা বিকল্প বলে মনে হচ্ছে। আমি যদি 300 এর বেশি সময় বাড়াতে পারি যে একটি ক্রাশ কখনও ঘটেনি?

আমরা এখনই এটি পরীক্ষা করছি যা এখন পর্যন্ত কাজ করছে বলে মনে হচ্ছে। আমরা আরও ফলাফল দেখতে হিসাবে আপডেট হবে

class ResumingServiceManager(val lifecycle: Lifecycle) : LifecycleObserver {

    init {
        lifecycle.addObserver(this)
    }

    val disposable: CompositeDisposable = CompositeDisposable()

    fun startService(context: Context, intent: Intent) {
        if (Build.VERSION.SDK_INT < Build.VERSION_CODES.O) {
            context.startService(intent)
        } else {
            Single.just(true)
                    .delaySubscription(300, TimeUnit.MILLISECONDS)
                    .subscribeOn(AndroidSchedulers.mainThread())
                    .observeOn(AndroidSchedulers.mainThread())
                    .subscribeBy(
                            onSuccess = {
                                context.startService(intent)
                            }

                    ).addTo(disposable)
        }
    }

    @OnLifecycleEvent(Lifecycle.Event.ON_STOP)
    fun stopped() {
        disposable.clear()
    }

    @OnLifecycleEvent(Lifecycle.Event.ON_DESTROY)
    fun destroy() {
        lifecycle.removeObserver(this)
    }
}

onCreate() এটিকে আরম্ভ করুন এবং তারপরে আপনি যে কোনও সময় অনআরএসুমে কোনও পরিষেবা শুরু করতে চান কেবল resumingServiceManager.startService(this, intent) শুরু করুন সার্ভিস ম্যানেজআর্টসার্ট সার্ভিস resumingServiceManager.startService(this, intent)

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


আমাদের দলও একই সমস্যার মুখোমুখি হয়েছিল। আমার ক্যালেন্ডারটি এপ্রিল, 2019 এর 5 দেখায়, তবে সমস্যাটি এখনও আমার স্যামসাং গ্যালাক্সি এস 9 +, অ্যান্ড্রয়েড 9.0 (এক ইউআই) -এ পুনরুত্পাদন করে

আমরা অনারুমে পরিষেবাটি শুরু করি এবং অন পজিসহ বন্ধ করুন ause

কিভাবে পুনরুত্পাদন

যখন এই যুক্তির সাথে ক্রিয়াকলাপটি স্ক্রিনে থাকে তখন কেবল আপনার ডিভাইসটিকে লক করুন এবং 10-15 মিনিট স্পর্শ করবেন না। আনলক স্ক্রিনের পরে, অ্যাপ্লিকেশন ক্রাশ হবে।

কিভাবে ঠিক করবো

আমরা সমাধান পেয়েছি যা আসলে কাজ করে। অ্যান্ড্রয়েড 8+ থেকে, android.os.Handler.post (...) এ আপনার পরিষেবা শুরু করুন

উদাহরণ (কোটলিন):

override fun onResume() {
    super.onResume()
    Handler().post {
        val serviceIntent = Intent(activity, SomeService::class.java)
        activity?.startService(serviceIntent)
        activity?.bindService(serviceIntent, serviceConnection, Context.BIND_AUTO_CREATE)
    }
}

শুভকামনা!


গুগল থেকে একটি কার্যনির্বাহী আছে:

ভবিষ্যতে অ্যান্ড্রয়েড রিলিজে বিষয়টি বিবেচনা করা হয়েছে।

অ্যাপ্লিকেশন ক্রাশ এড়ানোর জন্য একটি কর্মপরিকল্পনা রয়েছে। অ্যাপ্লিকেশনগুলি ActivityManager.getRunningAppProcesses () এ কল করে Activity.onResume () এ প্রক্রিয়া অবস্থা পেতে পারে এবং যদি গুরুত্বের স্তরটি ActivityManager.RunningAppProcessInfo.IMPORTANCE_FOREGROUND এর চেয়ে কম হয় তবে পরিষেবা শুরু করা এড়ানো যায়। যদি ডিভাইসটি পুরোপুরি জাগ্রত না হয়, তত্ক্ষণাত্ ক্রিয়াকলাপগুলি বিরতি দেওয়া হবে এবং অবশেষে সম্পূর্ণরূপে জাগ্রত হওয়ার পরে এটি আবার শুরু করা হবে।

সুতরাং আমি মনে করি এটি পছন্দ করা উচিত:

// hack for https://issuetracker.google.com/issues/113122354
    List<ActivityManager.RunningAppProcessInfo> runningAppProcesses = activityManager.getRunningAppProcesses();
    if (runningAppProcesses != null) {
        int importance = runningAppProcesses.get(0).importance;
        // higher importance has lower number (?)
        if (importance <= ActivityManager.RunningAppProcessInfo.IMPORTANCE_FOREGROUND)
            URLPlayerService.startActionBroadcastServiceData(PlayerActivity.this);
    }

আমি হ্যান্ডলারটি একটি কার্যক্ষম হিসাবে ব্যবহার করেছি এবং এটি বেশ ভাল কাজ করে তবে 100% নয়:

// hack for https://issuetracker.google.com/issues/113122354
   handler.postDelayed(() -> URLPlayerService.startService(PlayerActivity.this),200);

তারা ক্র্যাশটি স্থির করে (ভবিষ্যতের কিছু রিলিজে, ঠিক কোনটি নিশ্চিত নয়) এবং আপাতত একটি কার্যপ্রণালী সরবরাহ করেছে: https://issuetracker.google.com/issues/110237673#comment9





android-9.0-pie