Android - iniciar serviço na inicialização

107

De tudo o que vi no Stack Exchange e em outros lugares, tenho tudo configurado corretamente para iniciar um IntentService quando o sistema operacional Android é inicializado. Infelizmente, ele não está iniciando na inicialização e não estou recebendo nenhum erro. Talvez os especialistas possam ajudar ...

Manifesto:

<?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 para inicialização:

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

ATUALIZAÇÃO : tentei quase todas as sugestões abaixo e adicionei o registro, como Log.v("BatteryLogger", "Got to onReceive, about to start service");ao manipulador onReceive do StartupIntentReceiver, e nada é registrado. Portanto, não está nem chegando ao BroadcastReceiver.

Acho que estou implantando o APK e testando corretamente, apenas executando Debug no Eclipse e o console diz que o instalou com sucesso no meu tablet Xoom em \ BatteryLogger \ bin \ BatteryLogger.apk. Em seguida, para testar, eu reinicializo o tablet e, em seguida, vejo os logs no DDMS e verifico os Serviços em execução nas configurações do SO. Isso tudo parece correto ou estou perdendo alguma coisa? Novamente, qualquer ajuda é muito apreciada.

Gady
fonte
1
que problema você está tendo, você não está recebendo nenhuma IU ..?
Lalit Poptani,
1
O serviço nunca começa, esse é o problema.
Gady,
como você ficou sabendo que seu serviço não está começando, você imprimiu os Logs ou algo parecido ..?
Lalit Poptani
1
Você não precisa de registros para ver que não está funcionando. O sistema operacional Android expõe serviços em execução. No entanto, seria aconselhável usar o registro para ver se um erro está ocorrendo. Eu arriscaria supor que isso acontece antes de context.startService () se um erro estiver ocorrendo.
Tony,
1
Eu adicionei Log.v("BatteryLogger", "Got to onReceive, about to start service");ao manipulador onReceive e ele nunca aparece nos logs. Então, o ouvinte está falhando (?)
Gady,

Respostas:

302

Bem, aqui está um exemplo completo de um aplicativo AutoStart

Arquivo 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 - aparecerá toda vez que você iniciar o dispositivo após executar a aplicação uma vez.

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
fonte
10
1 para um exemplo completo. Talvez eu deva mudar meu IntentService com onHandleIntent para um simples serviço antigo
Gady,
6
Isso acabou resolvendo tudo. O problema era uma combinação do meu serviço sendo um IntentService em vez do antigo serviço e erros no código do serviço. A eficácia dessa resposta e o login no Android me ajudaram a resolver meus problemas.
Gady,
3
1 para o exemplo detalhado. Isso também funcionaria sem uma atividade?
balas
1
O retorno de chamada onStart () está obsoleto. Você deve usar onStartCommand () em vez disso.
MMBs de
1
@mmBs esta resposta tem quase 5 anos, então é óbvio
Lalit Poptani
3

Seu serviço pode estar sendo encerrado antes de ser concluído devido ao dispositivo entrar em suspensão após a inicialização. Você precisa obter um wake lock primeiro. Felizmente, a biblioteca de suporte nos oferece uma classe para fazer isso:

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

em seguida, em seu serviço, certifique-se de liberar o wake lock:

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

Não se esqueça de adicionar a permissão WAKE_LOCK:

<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />
<uses-permission android:name="android.permission.WAKE_LOCK" />
phreakhead
fonte
1
Eu estou tendo o mesmo problema. Você se importa em me ajudar? Obrigado! stackoverflow.com/questions/35373525/starting-my-service
Ruchir Baronia
2

Seguir deve funcionar. Eu verifiquei. Pode ser que o seu problema esteja em outro lugar.

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
fonte
Obrigado por isso, mas ainda não funcionou. Os logs nem mesmo mostram que ele chega ao StartupIntentReceiver. Alguma outra ideia?
Gady,
1
Seu código está funcionando no emulador? Você consegue receber a intenção no emulador?
Vivek,
Testei no emulador e recebo um erro no DDMS, mas parece que pelo menos o serviço está tentando iniciar, embora nenhuma das minhas Log()instruções esteja lá e o dispositivo do emulador não mostre meu serviço como sendo executado nas configurações do sistema operacional. Aqui está o erro no DDMS: System.err - at com.phx.batterylogger$1.onReceive(BatteryLogger.java:43)Isso significa que o problema está na linha 43 do meu serviço BatteryLogger?
Gady,
2

Eu encontrei uma maneira de fazer seu aplicativo funcionar bem quando o dispositivo for reinicializado, siga as etapas abaixo para ter sucesso.

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

Isso é pedir permissão para não precisar gerenciar a economia de bateria para este aplicativo para que você possa executar em segundo plano de forma estável.

Declare este código em onCreate () da classe 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
fonte
1

É muito parecido com o meu, mas uso o nome completo do pacote para o receptor:

<receiver android:name=".StartupIntentReceiver">

Eu tenho:

<receiver android:name="com.your.package.AutoStart"> 
ciscogambo
fonte
Sim, foi um pouco difícil resolver o seu problema, então é melhor postar um exemplo de hello world.
Lalit Poptani,
1

Tive sucesso sem o pacote completo, você sabe onde a cadeia de chamadas está sendo interrompida? Se você depurar com Log()o, em que ponto ele não funcionará mais?

Acho que pode estar no seu IntentService, tudo parece bem.

Phix
fonte
Eu adicionei Log.v("BatteryLogger", "Got to onReceive, about to start service");ao manipulador onReceive e ele nunca aparece nos logs. Então, o ouvinte está falhando (?)
Gady,
O que faz o broadcast receiver iniciar quando o telefone é inicializado? Obrigado!
Ruchir Baronia
Garoto. Não toquei no Android há alguns anos. Desculpe @Ruchir
Phix
0

Apenas para facilitar a pesquisa, conforme mencionado nos comentários, isso não é possível desde 3.1 https://stackoverflow.com/a/19856367/6505257

MrKew
fonte
Isso não é verdade, conforme afirmado por Think Twice Code Once na seção de comentários da mesma resposta.
Ricardo A.
Uma explicação mais detalhada para apoiar meu argumento: stackoverflow.com/questions/20441308/…
Ricardo A.
Faz muito tempo que não faço nada com o Android, mas você está certo, é possível. Nenhum outro argumento necessário. (Vou editar a resposta)
MrKew