Android - запуск службы при загрузке

107

Из всего, что я видел на Stack Exchange и в других местах, у меня все настроено правильно, чтобы запускать IntentService при загрузке ОС Android. К сожалению, он не запускается при загрузке, и я не получаю никаких ошибок. Может, специалисты помогут ...

Манифест:

<?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 для запуска:

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

ОБНОВЛЕНИЕ : я попробовал почти все предложения, приведенные ниже, и добавил ведение журнала, например, Log.v("BatteryLogger", "Got to onReceive, about to start service");в обработчик onReceive StartupIntentReceiver, и ничего не регистрируется. Так что он даже не попадает в BroadcastReceiver.

Я думаю, что развертываю APK и тестирую правильно, просто запускаю Debug в Eclipse, и консоль сообщает, что успешно устанавливает его на мой планшет Xoom в \ BatteryLogger \ bin \ BatteryLogger.apk. Затем для проверки перезагружаю планшет, затем просматриваю логи в DDMS и проверяю «Работающие службы» в настройках ОС. Все это звучит правильно, или я что-то упускаю? Опять же, любая помощь приветствуется.

Гади
источник
1
какая у вас проблема, разве у вас нет интерфейса ..?
Лалит Поптани
1
Сервис просто не запускается, вот в чем проблема.
Gady
как вы узнали, что ваша служба не запускается, распечатали ли вы журналы или что-то в этом роде?
Лалит Поптани
1
Вам не нужны журналы, чтобы увидеть, что он не работает. ОС Android предоставляет работающие службы. Однако было бы разумно использовать ведение журнала, чтобы увидеть, возникает ли ошибка. Рискну предположить, что это происходит до context.startService (), если возникает ошибка.
Тони
1
Я добавил Log.v("BatteryLogger", "Got to onReceive, about to start service");в обработчик onReceive, и он никогда не отображается в журналах. Значит, слушатель терпит неудачу (?)
Гэди

Ответы:

302

Вот полный пример приложения AutoStart.

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 - это будет всплывать каждый раз при запуске устройства после выполнения приложения Applicaton один раз.

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();
    }
}
Лалит Поптани
источник
10
+1 для полного примера. Может, мне стоит изменить свой IntentService с onHandleIntent на простой старый сервис
Gady
6
Это в конечном итоге решило ее. Проблема заключалась в комбинации того, что моя служба была IntentService вместо простой старой службы, и ошибок в коде службы. Тщательный ответ и вход в Android помогли мне решить мои проблемы.
Gady
3
+1 за подробный пример. Будет ли это работать без активности?
balas
1
Обратный вызов onStart () устарел. Вместо этого вы должны использовать onStartCommand ().
mmBs
1
@mmBs этому ответу почти 5 лет, так что это очевидно
Лалит Поптани
3

Ваша Служба может быть отключена до завершения из-за того, что устройство переходит в спящий режим после загрузки. Сначала вам нужно получить блокировку слежения. К счастью, библиотека поддержки дает нам класс для этого:

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

затем в вашем Сервисе не забудьте снять блокировку пробуждения:

    @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:

<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />
<uses-permission android:name="android.permission.WAKE_LOCK" />
мошенник
источник
1
У меня та же проблема. Не могли бы вы мне помочь? Спасибо! stackoverflow.com/questions/35373525/starting-my-service
Ruchir Baronia
2

Следующее должно работать. Я проверил. Может быть ваша проблема в другом.

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>
Вивек
источник
Спасибо за это, но все равно не сработало. Журналы даже не показывают, что он попадает в StartupIntentReceiver. Есть другие идеи?
Gady
1
Ваш код работает в эмуляторе? Можете ли вы получить намерение в эмуляторе?
Вивек
Я тестировал в эмуляторе и получаю сообщение об ошибке в DDMS, но похоже, что, по крайней мере, служба пытается запуститься, хотя ни одного из моих Log()утверждений там нет, и устройство эмулятора не показывает, что моя служба работает в настройках ОС. Вот ошибка в DDMS: System.err - at com.phx.batterylogger$1.onReceive(BatteryLogger.java:43)Означает ли это, что проблема находится в строке 43 моей службы BatteryLogger?
Gady
2

Я нашел способ заставить ваше приложение работать нормально при перезагрузке устройства, пожалуйста, выполните следующие действия, чтобы добиться успеха.

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

Это запрашивает разрешение не управлять экономией заряда батареи для этого приложения, чтобы вы могли стабильно работать в фоновом режиме.

Объявите этот код в onCreate () класса 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);
Хай ТРАН
источник
1

Очень похоже на мой но я использую полное имя пакета для приемника:

<receiver android:name=".StartupIntentReceiver">

У меня есть:

<receiver android:name="com.your.package.AutoStart"> 
цискогамбо
источник
Да, это было немного, чтобы разобраться с вашей проблемой, поэтому лучше опубликовать пример hello world.
Лалит Поптани
1

Я добился успеха без полного пакета, вы знаете, где прерывается цепочка вызовов? Если вы отлаживаетеLog() , в какой момент он больше не работает?

Я думаю, что это может быть в вашем IntentService, все выглядит нормально.

Фикс
источник
Я добавил Log.v("BatteryLogger", "Got to onReceive, about to start service");в обработчик onReceive, и он никогда не отображается в журналах. Значит, слушатель терпит неудачу (?)
Гэди
Что заставляет широковещательный приемник запускаться при загрузке телефона? Спасибо!
Ruchir Baronia
Мальчик. Я не трогал андроид несколько лет. Извините @Ruchir
Phix
0

Чтобы упростить поиск, как упоминалось в комментариях, это невозможно с версии 3.1 https://stackoverflow.com/a/19856367/6505257

MrKew
источник
Это неправда, как утверждает Think Twice Code Once. в разделе комментариев того же ответа.
Ricardo A.
Более подробное объяснение в поддержку моего аргумента: stackoverflow.com/questions/20441308/…
Рикардо А.
Я действительно давно ничего не делал с андроидом, но вы правы, это возможно. Никаких других аргументов не требуется. (
Отредактирую