Android'de önyükleme sırasında bir hizmet başlatmaya çalışıyor


332

Bir cihaz android'de açıldığında bir hizmet başlatmaya çalışıyordum, ancak çalışamıyorum. Çevrimiçi bağlantıların bir dizi baktım ama kod hiçbiri çalışmıyor. Bir şey mi unuttum?

AndroidManifest.xml

<receiver
    android:name=".StartServiceAtBootReceiver"
    android:enabled="true"
    android:exported="false"
    android:label="StartServiceAtBootReceiver" >
    <intent-filter>
        <action android:name="android.intent.action._BOOT_COMPLETED" />
    </intent-filter>
</receiver>

<service
    android:name="com.test.RunService"
    android:enabled="true" />

Yayın alıcı

public void onReceive(Context context, Intent intent) {
    if ("android.intent.action.BOOT_COMPLETED".equals(intent.getAction())) {
        Intent serviceLauncher = new Intent(context, RunService.class);
        context.startService(serviceLauncher);
        Log.v("TEST", "Service loaded at start");
    }
}

2
ne yaptığımı bilmiyorum ama şimdi çalışıyor sanırım android olabilir: alıcı için izin = "android.permission.RECEIVE_BOOT_COMPLETED"
Alex

<action android: name = "android.intent.action._BOOT_COMPLETED" /> içindeki fazladan "_" i kontrol ettiniz mi?
OneWorld

Sistemin alıcıyı çağırabilmesi için dışa aktarılan doğru olmalıdır, değil mi? Yoksa varsayılan olarak doğru mu?
Eugen Pechanec

Yanıtlar:


601

Diğer cevaplar iyi gözüküyor, ama her şeyi tek bir cevaba yazacağımı sanıyordum.

AndroidManifest.xmlDosyanızda aşağıdakilere ihtiyacınız var :

  1. Senin içinde <manifest>eleman:

    <uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />
  2. <application>Öğenizde ( ürününüz için tam nitelikli [veya göreli] bir sınıf adı kullandığınızdan emin olun BroadcastReceiver):

    <receiver android:name="com.example.MyBroadcastReceiver">  
        <intent-filter>  
            <action android:name="android.intent.action.BOOT_COMPLETED" />  
        </intent-filter>  
    </receiver>
    

    (İhtiyacınız olmayan android:enabled, exportednitelikleri, vb: Android varsayılan doğru)

    İçinde MyBroadcastReceiver.java:

    package com.example;
    
    public class MyBroadcastReceiver extends BroadcastReceiver {
        @Override
        public void onReceive(Context context, Intent intent) {
            Intent startServiceIntent = new Intent(context, MyService.class);
            context.startService(startServiceIntent);
        }
    }
    

Orijinal sorudan:

  • eğer açık değil <receiver>unsur oldu <application>elemanı
  • için doğru tam nitelikli (veya göreli) sınıf adının BroadcastReceiverbelirtilip belirtilmediği açık değil
  • içinde bir yazım hatası vardı <intent-filter>

2
Bu iyi görünüyor. Bunu temel olarak kullanacağım, teşekkürler :). Hiçbir onay işareti veya upvotes veya cevap ne yazık ki :(. Herkes bunu doğrulamak?
Nanne

51
Yalnızca bir tamamlayıcı: uygulamanızın dahili belleğe yüklendiğinden emin olun <manifest xmlns: android = "..." package = "..." android: installLocation = "internalOnly">
Bao Le

2
Android Jellybean 4.2.2'de <receiver> etiketinde, stackoverflow.com/questions/16671619/… '
Piovezan

6
Alıcı farklı şeyler için kullanılıyorsa: <br> if ("android.intent.action.BOOT_COMPLETED" .equals (intent.getAction ())) {Intent serviceIntent = new Intent (context, Service_Location.class); // i.putExtra ("KEY1", "Hizmet tarafından kullanılacak değer"); context.startService (serviceIntent); }
Gunnar Bernstein

2
Bunun yerine developer.android.com/reference/android/support/v4/content/… 'ı genişletmelisiniz . Aygıtın uyandırma olayını alan ve daha sonra işi bir Hizmete geçiren ve aynı zamanda cihazın geçiş sırasında tekrar uyku moduna geçmemesini sağlayan bir BroadcastReceiver uygulaması için bir Yardımcıdır. Bu sınıf sizin için kısmi bir uyandırma kilidi oluşturmaya ve yönetmeye özen gösterir; kullanmak için WAKE_LOCK iznini istemelisiniz.
Damian

84

Ek bilgi olarak: Harici depolama birimi takılmadan önce BOOT_COMPLETE uygulamalara gönderilir . Dolayısıyla, uygulama harici bir depolama birimine kurulursa BOOT_COMPLETE yayın mesajı almaz.

Daha fazla detay burada bölümünde için Yayın Alıcıları dinleme "çizme tamamlandı"


Yukarıdaki sorunu önlemek için, geliştirici bir uygulama için bildirimde "android: installLocation =" internalOnly "ayarlayabilir. Bu kötü bir fikir mi? Bir akıllı telefon uygulaması için, tüm kullanıcıların% 99,9'u (tahminim) uygulamayı normal olarak yüklüyorsa , harici depolama yerine dahili depolama kullanarak, manifest için "internalOnly" eklenmesi iyi olur gibi görünüyor. Bu konuda herhangi bir düşünce veya fikir için minnettar olurum.
AJW

69

Aygıt önyüklemesinde hizmet nasıl başlatılır (otomatik çalıştırma uygulaması vb.)

İlk olarak: Android 3.1+ sürümünden beri, kullanıcı uygulamanızı en az bir kez hiç başlatmamışsa veya kullanıcı "zorla kapalı" uygulamasını BOOT_COMPLETE almazsınız. Bu, kötü amaçlı yazılımların otomatik olarak kayıt hizmetini önlemek için yapıldı. Bu güvenlik açığı Android'in yeni sürümlerinde kapatıldı.

Çözüm:

Etkinlikle uygulama oluşturun. Kullanıcı bir kez çalıştırdığında uygulama BOOT_COMPLETE yayın mesajı alabilir.

İkinci olarak: Harici depolama birimi takılmadan önce BOOT_COMPLETE gönderilir. Uygulama harici depolama birimine kurulursa BOOT_COMPLETE yayın mesajı almaz.

Bu durumda iki çözüm vardır:

  1. Uygulamanızı dahili depolamaya yükleyin
  2. Dahili depolama alanına başka bir küçük uygulama yükleyin. Bu uygulama BOOT_COMPLETE alır ve harici depolama alanında ikinci uygulamayı çalıştırır.

Uygulamanız dahili depolama birimine zaten yüklenmişse, aşağıdaki kod cihaz önyüklemesinde hizmetin nasıl başlatılacağını anlamanıza yardımcı olabilir.


Manifest.xml içinde

İzin:

<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />

BOOT_COMPLETED alıcınızı kaydedin:

<receiver android:name="org.yourapp.OnBoot">
    <intent-filter>
        <action android:name="android.intent.action.BOOT_COMPLETED"/>
    </intent-filter>
</receiver>

Hizmetinizi kaydedin:

<service android:name="org.yourapp.YourCoolService" />

Alıcı OnBoot.java'da:

public class OnBoot extends BroadcastReceiver
{

    @Override
    public void onReceive(Context context, Intent intent) 
    {
        // Create Intent
        Intent serviceIntent = new Intent(context, YourCoolService.class);
        // Start service
        context.startService(serviceIntent);

    }

 }

HTC için, cihaz RECEIVE_BOOT_COMPLETED yakalamıyorsa bu kodu Manifest'e de eklemeniz gerekebilir:

<action android:name="android.intent.action.QUICKBOOT_POWERON" />

Alıcı şimdi şöyle görünür:

<receiver android:name="org.yourapp.OnBoot">
    <intent-filter>
        <action android:name="android.intent.action.BOOT_COMPLETED"/>
        <action android:name="android.intent.action.QUICKBOOT_POWERON" />
    </intent-filter>
</receiver>

Yeniden başlatma emülatörü veya gerçek cihaz olmadan BOOT_COMPLETED nasıl test edilir? Bu kolay. Bunu dene:

adb -s device-or-emulator-id shell am broadcast -a android.intent.action.BOOT_COMPLETED

Cihaz kimliği nasıl alınır? Kimliğine sahip bağlı cihazların listesini alın:

adb devices

ADB'de adb varsayılan olarak şunları bulabilirsiniz:

adt-installation-dir/sdk/platform-tools

Zevk almak! )


İlk paragrafınız sermayeydi. Hata ayıklayıcıda çalıştıramadım.
estornes

34

İle birlikte

<action android:name="android.intent.action.BOOT_COMPLETED" />  

Ayrıca kullan,

<action android:name="android.intent.action.QUICKBOOT_POWERON" />

HTC cihazları BOOT_COMPLETED ürününü yakalamıyor gibi görünüyor


HTC cihazları için izinlerde benzer bir şey eklemeniz mi gerekiyor?
Nanda

2
Bu bazı durumlarda yararlı olabilir, ancak HTC Hızlı Önyükleme'nin sistem durumunun dosya sistemine kaydedildiği ve android.intent.action.QUICKBOOT_POWERONyalnızca hızlı önyüklemeden geri yükleme sırasında gönderildiği bir hazırda bekletme modu olduğunu anlıyorum . Bu, Hızlı Önyükleme'den kurtarılırken korunurken alarmları sıfırlama gibi şeylerin yapılması gerekmediği anlamına gelir. Bu nedenle, yalnızca <action android:name="android.intent.action.QUICKBOOT_POWERON" />kullanıcı aygıtın önyüklendiğini düşündüğünde bir şeyler yapmak istiyorsanız kullanmak gerekir .
HexAndBugs

2
Uygulama geliştiricinin bakış açısından, davranış yalnızca HTC cihazlarında mevcutsa, bunu asla kullanmamalıyız. Çünkü, BOOT_COMPLETED, belgelere göre cihaz AÇIK olduğunda her zaman gönderilecektir. Başka bir üretici başka bir hızlı önyükleme yöntemi ile gelebilir ve kodumuzu her birinin özellikleriyle karıştırırız.
Subin Sebastian

@HexAndBugs Hızlı Önyüklemenin, sistem durumunun dosya sistemine kaydedildiği bir hazırda bekletme modu olduğunu onaylayabildiniz mi? Sistem durumu kaydedilmezse Hızlı Önyüklemeden sonra gelecekteki Bildirimler için kullanılacak alarmları sıfırlamak istiyorum ... lütfen önerin.
AJW

20

sorunun başında yazım hatası var:

<action android:name="android.intent.action._BOOT_COMPLETED"/>

onun yerine :

<action android:name="android.intent.action.BOOT_COMPLETED"/>

bir küçük "_" ve tüm bu sorun :)


13

Ben sadece şimdi Fast Bootseçeneği nedeniyle olabilir öğrendim Settings>Power

Bu seçeneği kapattığımda, uygulamam bu yayını alır ancak başka şekilde almaz.

Bu arada, var Android 2.3.3üzerinde HTC Incredible S.

Umarım yardımcı olur.


Sorunun kesinlikle olası nedeni. Android 4.0.3 çalıştıran HTC Desire C üzerinde de gözlemlendi.
Zelimir


7

Bahsedilen tüm cevapları ve püf noktaları denedikten sonra, sonunda kodun neden telefonumda çalışmadığını anladım. "Huawei Honor 3C Android 4.2.2 " gibi bazı Android telefonların ayarlarında bir Statup Manager menüsü vardır ve uygulamanızın listede kontrol edilmesi gerekir. :)


5

Ek bir <category>etiketim var, bunun herhangi bir fark yaratıp yaratmadığını bilmiyorum.

<receiver android:name="BootIntentReceiver">  
        <intent-filter>  
            <action android:name="android.intent.action.BOOT_COMPLETED" />  
            <category android:name="android.intent.category.HOME" />  
        </intent-filter>  
</receiver>

"android.intent.action.BOOT_COMPLETED".equals(intent.getAction()Alıcı muhtemelen yine de bu niyeti aldığından if-yantümcesini atlatmayı denediniz mi?


bunu denedim ve ben de işe yaramadı btw işe yaramadı ben de <kullanımları izin android var: adı = "android.permission.RECEIVE_BOOT_COMPLETED" />
Alex

2
Her ihtimale karşı: AndroidManifest'teki herhangi bir etikete android.intent.category.HOME eklenmesi, Samsung Galaxy Tab uygulamasının, uyumluluk modunu kapatmak için kesmek kullandıktan sonra bile uygulamayı uyumluluk modunda çalıştırmasına neden olur. bunun diğer sekmeler için aynı olup olmadığından emin değilim. HOME kategorisini hiç ayarlamamanızı öneririm. gereksiz.
moonlightcheese


3

Harici depolama birimini takmadan önce BOOT_COMPLETE yürütme gönderilir. Uygulamanız harici bir depolama birimine kurulursa BOOT_COMPLETE yayın mesajı almaz. Bunu önlemek için uygulamanızı dahili depoya yükleyebilirsiniz. bunu menifest.xml dosyasına bu satırı ekleyerek yapabilirsiniz

<manifest xmlns:android="http://schemas.android.com/apk/res/android"
android:installLocation="internalOnly"
... >

Bazı HTC cihazları, gerçek bir yeniden başlatma değil, derin bir hazırda bekletme moduna benzeyen ve bu nedenle BOOT_COMPLETE amacını vermemesi gereken "hızlı önyükleme" özelliğini etkinleştirebilir. Bunu kurtarmak için bu niyet filtresini alıcınızın içine ekleyebilirsiniz:

            <intent-filter>
                <action android:name="android.intent.action.BOOT_COMPLETED" />
                <action android:name="android.intent.action.QUICKBOOT_POWERON" />
            </intent-filter>

Önerdiğiniz gibi, yukarıdaki sorunu önlemek için, geliştirici bir uygulama için bildirimde "android: installLocation =" internalOnly "ayarlayabilir. Bu kötü bir fikir mi? Bir akıllı telefon uygulaması için, eğer tüm kullanıcıların% 99.9'u (benim tahminim) dahili depolama birimi yerine harici depolama kullanarak, normalde uygulamayı yüklemek, o zaman beyannamesine "internalOnly" ilavesi iyi olurdu görünüyor ben bu konuda düşüncelerinizi veya fikirleri takdir ediyorum -.. AJW
AJW

3

Ben de öyle yaptım

1. Alıcı sınıfını yaptım

public class BootReceiver extends BroadcastReceiver {
    @Override
    public void onReceive(Context context, Intent intent) {
        //whatever you want to do on boot
       Intent serviceIntent = new Intent(context, YourService.class);
       context.startService(serviceIntent);
    }
}

2. manifest'te

<manifest...>
    <uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED"/>
    <application...>
        <receiver android:name=".BootReceiver" android:enabled="true" android:exported="false">
            <intent-filter>
                <action android:name="android.intent.action.BOOT_COMPLETED" />
            </intent-filter>
        </receiver>
    ...

3. ve TÜM sonra alıcıyı MainActivity'de "ayarlamanız" GEREKİR, onCreate içinde olabilir

...
 final ComponentName onBootReceiver = new ComponentName(getApplication().getPackageName(), BootReceiver.class.getName());
        if(getPackageManager().getComponentEnabledSetting(onBootReceiver) != PackageManager.COMPONENT_ENABLED_STATE_ENABLED)
        getPackageManager().setComponentEnabledSetting(onBootReceiver,PackageManager.COMPONENT_ENABLED_STATE_ENABLED,PackageManager.DONT_KILL_APP);
...

ApiDemos'tan öğrendiğim son yığın


2

Android Studio kullanıyorsanız ve otomatik tamamlamaya çok düşkünseniz, sizi bilgilendirmeliyim, Android Studio v 1.1.0 kullanıyorum ve aşağıdaki izin için otomatik tamamlama kullandım

<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />

Ve Android Studio Otomatik olarak RECEIVE_BOOT_COMPLETEDtüm küçük harflerle tamamlandı receive_boot_completedve saçlarımı çekmeye devam ettim çünkü önyüklemede hizmete başlamak için yapılacaklar için kontrol listemi zaten işaretledim. Tekrar onayladım

Android Studio, bu izni küçük harflerle otomatik olarak tamamlar.


2

@Damian'ın yorumladığı gibi, bu konudaki tüm cevaplar yanlış yapıyor. Bu şekilde manuel olarak yapılması, Servisinizin cihazdan uyku moduna geçmesinin durdurulması riskini taşır. Önce bir uyandırma kilidi almanız gerekir. Neyse ki, Destek kütüphanesi bize bunu yapmak için bir sınıf verir :

public class SimpleWakefulReceiver extends WakefulBroadcastReceiver {
    @Override
    public void onReceive(Context context, Intent intent) {
        // This is the Intent to deliver to our service.
        Intent service = new Intent(context, SimpleWakefulService.class);

        // Start the service, keeping the device awake while it is launching.
        Log.i("SimpleWakefulReceiver", "Starting service @ " + SystemClock.elapsedRealtime());
        startWakefulService(context, service);
    }
}

ardından Hizmetinizde, uyandırma kilidini açtığınızdan emin olun:

    @Override
    protected void onHandleIntent(Intent intent) {
        // At this point SimpleWakefulReceiver is still holding a wake lock
        // for us.  We can do whatever we need to here and then tell it that
        // it can release the wakelock.

...
        Log.i("SimpleWakefulReceiver", "Completed service @ " + SystemClock.elapsedRealtime());
        SimpleWakefulReceiver.completeWakefulIntent(intent);
    }

WAKE_LOCK izin belgesini ana etkinliğinize eklemeyi unutmayın:

<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />
<uses-permission android:name="android.permission.WAKE_LOCK" />

Küçük bir soru şüphe var. Benim hizmet bir hizmet ve IntentService değil, çünkü onHandleIntend yöntemi basit hizmet geçersiz kılınamaz çünkü bu şekilde kullanamazsınız ?
paolo2988

Aynı sorunu yaşıyorum. Bana yardım eder misin? Teşekkürler! stackoverflow.com/questions/35373525/starting-my-service
Ruchir Baronia

Belki kullanabilir onNewIntent()misin? Veya IntentService kaynağına bakabilir ve Hizmetinizin eşleşmesi için ne yapmanız gerektiğini görebilirsiniz ...
phreakhead

1

Aslında, çok uzun zaman önce bu sorunla karşılaşıyorum ve düzeltilmesi gerçekten çok kolay, "android.intent.action.BOOT_COMPLETED"izin ve niyet filtresini ayarlarsanız aslında yanlış bir şey yapmazsınız.

Android 4.X'te, önyüklemede hizmete başlamadan önce yayın dinleyicisini çalıştırmanız gerektiğine dikkat edin, yani, yayın alıcınız çalıştıktan sonra uygulamanızın beklediğiniz gibi çalışması gerekir, Ancak, Android 4.X'te, herhangi bir etkinlik olmadan önyüklemede hizmeti başlatmanın bir yolunu bulamadım, sanırım google güvenlik nedeniyle bunu yaptı.


0

Alıcı sınıfında boş yapıcıyı bırakırsam bu sorunla karşılaştım. Boş kondansatör çıkarıldıktan sonraAlıma yöntemleri iyi çalışmaya başladı.

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.