Android - Mulai layanan saat boot

107

Dari semua yang saya lihat di Stack Exchange dan di tempat lain, saya sudah menyiapkan semuanya dengan benar untuk memulai IntentService saat booting OS Android. Sayangnya itu tidak dimulai saat boot, dan saya tidak mendapatkan kesalahan apa pun. Mungkin para ahli bisa membantu ...

Nyata:

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
  package="com.phx.batterylogger"
  android:versionCode="1"
  android:versionName="1.0"
  android:installLocation="internalOnly">

<uses-sdk android:minSdkVersion="8" />
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.BATTERY_STATS" />

<application android:icon="@drawable/icon" android:label="@string/app_name">
    <service android:name=".BatteryLogger"/>
    <receiver android:name=".StartupIntentReceiver">  
        <intent-filter>  
            <action android:name="android.intent.action.BOOT_COMPLETED" />  
        </intent-filter>  
    </receiver>
</application>

</manifest>

BroadcastReceiver untuk Startup:

package com.phx.batterylogger;

import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;

public class StartupIntentReceiver extends BroadcastReceiver {
    @Override
    public void onReceive(Context context, Intent intent) {
        Intent serviceIntent = new Intent(context, BatteryLogger.class);
        context.startService(serviceIntent);
    }
}

UPDATE : Saya mencoba hampir semua saran di bawah ini, dan saya menambahkan logging seperti Log.v("BatteryLogger", "Got to onReceive, about to start service");onReceive handler dari StartupIntentReceiver, dan tidak ada yang dicatat. Jadi itu bahkan tidak sampai ke BroadcastReceiver.

Saya pikir saya menerapkan APK dan menguji dengan benar, hanya menjalankan Debug di Eclipse dan konsol mengatakan itu berhasil menginstalnya ke tablet Xoom saya di \ BatteryLogger \ bin \ BatteryLogger.apk. Kemudian untuk mengujinya, saya mem-boot ulang tablet dan kemudian melihat log di DDMS dan memeriksa Layanan yang Berjalan di pengaturan OS. Apakah ini semua terdengar benar, atau saya melewatkan sesuatu? Sekali lagi, bantuan apa pun sangat dihargai.

Gady
sumber
1
masalah apa yang Anda dapatkan, apakah Anda tidak mendapatkan UI ..?
Lalit Poptani
1
Layanan tidak pernah dimulai, itulah masalahnya.
Gady
bagaimana Anda mengetahui bahwa layanan Anda belum dimulai, apakah Anda sudah mencetak Log atau semacamnya ..?
Lalit Poptani
1
Anda tidak perlu log untuk melihatnya tidak berjalan. OS Android memperlihatkan layanan yang sedang berjalan. Namun, akan lebih bijaksana untuk menggunakan logging untuk melihat apakah terjadi kesalahan. Saya berani menebak bahwa itu terjadi sebelum context.startService () jika terjadi kesalahan.
Tony
1
Saya menambahkan Log.v("BatteryLogger", "Got to onReceive, about to start service");ke penangan onReceive, dan itu tidak pernah muncul di log. Jadi pendengar gagal (?)
Gady

Jawaban:

302

Nah berikut adalah contoh lengkap dari Aplikasi AutoStart

File AndroidManifest

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="pack.saltriver" android:versionCode="1" android:versionName="1.0">

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

    <application android:icon="@drawable/icon" android:label="@string/app_name">

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

        <activity android:name=".hello"></activity>
        <service android:enabled="true" android:name=".service" />
    </application>
</manifest>

autostart.java

public class autostart extends BroadcastReceiver 
{
    public void onReceive(Context context, Intent arg1) 
    {
        Intent intent = new Intent(context,service.class);
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
            context.startForegroundService(intent);
        } else {
            context.startService(intent);
        }
        Log.i("Autostart", "started");
    }
}

service.java

public class service extends Service
{
    private static final String TAG = "MyService";
    @Override
    public IBinder onBind(Intent intent) {
        return null;
    }
    public void onDestroy() {
        Toast.makeText(this, "My Service Stopped", Toast.LENGTH_LONG).show();
        Log.d(TAG, "onDestroy");
    }

    @Override
    public void onStart(Intent intent, int startid)
    {
        Intent intents = new Intent(getBaseContext(),hello.class);
        intents.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
        startActivity(intents);
        Toast.makeText(this, "My Service Started", Toast.LENGTH_LONG).show();
        Log.d(TAG, "onStart");
    }
}

hello.java - Ini akan muncul setiap kali Anda memulai perangkat setelah menjalankan Aplikasi satu kali.

public class hello extends Activity 
{   
    public void onCreate(Bundle savedInstanceState) 
    {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);
        Toast.makeText(getBaseContext(), "Hello........", Toast.LENGTH_LONG).show();
    }
}
Lalit Poptani
sumber
10
+1 untuk contoh lengkap. Mungkin saya harus mengubah IntentService saya dengan onHandleIntent ke Layanan lama biasa
Gady
6
Ini akhirnya menyelesaikannya. Masalahnya adalah kombinasi layanan saya menjadi IntentService, bukan Layanan lama biasa dan kesalahan dalam kode layanan. Ketelitian jawaban ini dan masuk ke Android membantu saya menyelesaikan masalah saya.
Gady
3
1 untuk contoh detailnya. Apakah ini juga akan berfungsi tanpa aktivitas?
balas
1
Callback onStart () tidak digunakan lagi. Anda harus menggunakan onStartCommand () sebagai gantinya.
mmBs
1
@mmBs jawaban ini hampir berusia 5 tahun, jadi sudah jelas
Lalit Poptani
3

Layanan Anda mungkin dimatikan sebelum selesai karena perangkat akan tidur setelah booting. Anda perlu mendapatkan penguncian layar saat aktif terlebih dahulu. Untungnya, pustaka Dukungan memberi kita kelas untuk melakukan ini:

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);
    }
}

kemudian, di Layanan Anda, pastikan untuk melepaskan kunci layar aktif:

    @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);
    }

Jangan lupa untuk menambahkan izin WAKE_LOCK:

<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />
<uses-permission android:name="android.permission.WAKE_LOCK" />
phreakhead
sumber
1
Saya mengalami masalah yang sama. Apakah Anda keberatan membantu saya? Terima kasih! stackoverflow.com/questions/35373525/starting-my-service
Ruchir Baronia
2

Mengikuti harus bekerja. Saya telah memverifikasi. Mungkin masalah Anda ada di tempat lain.

public class MyReceiver extends BroadcastReceiver{

    @Override
    public void onReceive(Context context, Intent intent) {
        Log.d("TAG", "MyReceiver");
        Intent serviceIntent = new Intent(context, Test1Service.class);
        context.startService(serviceIntent);
    }
}




public class Test1Service extends Service {
    /** Called when the activity is first created. */
    @Override
    public void onCreate() {
        super.onCreate();
        Log.d("TAG", "Service created.");
    }

    @Override
    public int onStartCommand(Intent intent, int flags, int startId) {
        Log.d("TAG", "Service started.");
        return super.onStartCommand(intent, flags, startId);
    }

    @Override
    public void onStart(Intent intent, int startId) {
        super.onStart(intent, startId);
        Log.d("TAG", "Service started.");
    }
    @Override
    public IBinder onBind(Intent arg0) {
        return null;
    }
}




<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
      package="com.test"
      android:versionCode="1"
      android:versionName="1.0"
      android:installLocation="internalOnly">
    <uses-sdk android:minSdkVersion="8" />

    <application android:icon="@drawable/icon" android:label="@string/app_name">

    <uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />
    <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
    <uses-permission android:name="android.permission.BATTERY_STATS" 
    />
<!--        <activity android:name=".MyActivity">
            <intent-filter>  
                <action android:name="android.intent.action.MAIN" /> 
                <category android:name="android.intent.category.LAUNCHER"></category> 
            </intent-filter>
       </activity> -->
        <service android:name=".Test1Service" 
                  android:label="@string/app_name"
                  >
        </service>
        <receiver android:name=".MyReceiver">  
            <intent-filter>  
                <action android:name="android.intent.action.BOOT_COMPLETED" /> 
            </intent-filter>  
        </receiver> 
    </application>
</manifest>
Vivek
sumber
Terima kasih untuk ini, tetapi tetap tidak berhasil. Log bahkan tidak menunjukkan bahwa itu membuatnya ke StartupIntentReceiver. Ada ide lain?
Gady
1
Apakah kode Anda berfungsi di emulator? Bisakah Anda menerima maksud di emulator?
Vivek
Saya mengujinya di emulator dan mendapatkan error di DDMS, tetapi sepertinya setidaknya layanan mencoba untuk memulai, meskipun tidak ada Log()pernyataan saya di sana dan perangkat emulator tidak menunjukkan layanan saya berjalan di setelan OS. Berikut adalah kesalahan di DDMS: System.err - at com.phx.batterylogger$1.onReceive(BatteryLogger.java:43)Apakah itu berarti masalahnya ada di baris 43 layanan BatteryLogger saya?
Gady
2

Saya telah menemukan cara untuk membuat aplikasi Anda berjalan dengan baik saat perangkat di-boot ulang, ikuti langkah-langkah di bawah ini agar berhasil.

File AndroidManifest

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="pack.saltriver" android:versionCode="1" android:versionName="1.0">
<uses-permission 
android:name="android.permission.REQUEST_IGNORE_BATTERY_OPTIMIZATIONS"/>
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />

<application android:icon="@drawable/icon" android:label="@string/app_name">

<activity android:name=".MainActivity">
        <intent-filter>
            <action android:name="android.intent.action.MAIN" />

            <category android:name="android.intent.category.LAUNCHER" />
        </intent-filter>
    </activity>
    <receiver android:name=".UIBootReceiver" android:enabled="true" 
    android:exported="true">
        <intent-filter>
            <action android:name="android.intent.action.BOOT_COMPLETED" />
            <category android:name="android.intent.category.DEFAULT" />
        </intent-filter>
    </receiver>
     <service android:name=".class_Service" />
</application>

UIBootReceiver

public class UIBootReceiver extends BroadcastReceiver {

private static final String TAG = "UIBootReceiver";
@Override

    public void onReceive(Context context, Intent arg1)
    {
        Toast.makeText(context, "started", Toast.LENGTH_SHORT).show();
        Intent intent = new Intent(context,class_Service.class);
        context.startService(intent);
    }
  }

Ini meminta izin untuk tidak perlu mengelola penghematan baterai untuk aplikasi ini sehingga Anda dapat berjalan di latar belakang dengan stabil.

Deklarasikan kode ini di onCreate () dari kelas MainActivity:

   Intent myIntent = new Intent();
    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
        myIntent.setAction(Settings.ACTION_REQUEST_IGNORE_BATTERY_OPTIMIZATIONS);
        myIntent.setData(Uri.parse("package:" + 
   DeviceMovingSpeed.this.getPackageName()));
    }
    startActivity(myIntent);
Huy TRAN
sumber
1

Terlihat sangat mirip dengan milik saya tetapi saya menggunakan nama paket lengkap untuk penerima:

<receiver android:name=".StartupIntentReceiver">

Saya sudah:

<receiver android:name="com.your.package.AutoStart"> 
ciscogambo.dll
sumber
Yup, itu agak sedikit memikirkan masalah Anda, jadi lebih baik posting contoh hello world.
Lalit Poptani
1

Saya sudah sukses tanpa paket lengkap, apakah Anda tahu di mana rantai panggilan terputus? Jika Anda men-debug dengan Log()'s, pada titik mana ia tidak lagi berfungsi?

Saya pikir itu mungkin ada di IntentService Anda, ini semua terlihat baik-baik saja.

Phix
sumber
Saya menambahkan Log.v("BatteryLogger", "Got to onReceive, about to start service");ke penangan onReceive, dan itu tidak pernah muncul di log. Jadi pendengar gagal (?)
Gady
Apa yang membuat penerima siaran mulai saat telepon di-boot? Terima kasih!
Ruchir Baronia
Nak. Saya belum pernah menyentuh android dalam beberapa tahun. Maaf @Ruchir
Phix
0

Hanya untuk mempermudah pencarian, seperti yang disebutkan dalam komentar, ini tidak dimungkinkan sejak 3.1 https://stackoverflow.com/a/19856367/6505257

MrKew
sumber
Itu tidak benar, seperti yang dinyatakan oleh Think Twice Code Once di bagian komentar dari jawaban yang sama.
Ricardo A.
Penjelasan yang lebih rinci untuk mendukung argumen saya: stackoverflow.com/questions/20441308/…
Ricardo
Sudah sangat lama sejak saya melakukan apa pun dengan android, tetapi Anda benar, itu mungkin. Tidak perlu argumen lain. (Saya akan mengedit jawabannya)
MrKew