Cómo mantener el servicio funcionando en segundo plano

Estoy creando una aplicación que inicia una actividad tan pronto como el usuario pulsa el botón de encendido 3 veces. Después de algunas investigaciones descubrí que para hacer esto, primero debes crear un servicio que lance un receptor de transmisión para comprobar el estado de encendido / apagado de la pantalla.

Básicamente, quiero que se ejecute incluso cuando la aplicación está cerrada. Debe comenzar otra actividad tan pronto como se presione el botón de encendido 3 o más veces.

Si conoces la solución, por favor, dame el código completo o un enlace a la respuesta.

De alguna manera logré escribir este código, pero no funciona:

UpdateService.java

Esta es la clase de servicio que usé:

import android.app.Service; import android.content.BroadcastReceiver; import android.content.Intent; import android.content.IntentFilter; import android.os.IBinder; import android.util.Log; import android.widget.Toast; public class UpdateService extends Service { BroadcastReceiver mReceiver; @Override public void onCreate() { super.onCreate(); // register receiver that handles screen on and screen off logic IntentFilter filter = new IntentFilter(Intent.ACTION_SCREEN_ON); filter.addAction(Intent.ACTION_SCREEN_OFF); mReceiver = new MyReceiver(); registerReceiver(mReceiver, filter); } @Override public void onDestroy() { unregisterReceiver(mReceiver); Log.i("onDestroy Reciever", "Called"); super.onDestroy(); } @Override public void onStart(Intent intent, int startId) { boolean screenOn = intent.getBooleanExtra("screen_state", false); if (!screenOn) { Log.i("screenON", "Called"); Toast.makeText(getApplicationContext(), "Awake", Toast.LENGTH_LONG) .show(); } else { Log.i("screenOFF", "Called"); Toast.makeText(getApplicationContext(), "Sleep", Toast.LENGTH_LONG) .show(); } } @Override public IBinder onBind(Intent intent) { // TODO Auto-generated method stub return null; } } 

MyReceiver.java

 import android.content.BroadcastReceiver; import android.content.Context; import android.content.Intent; public class MyReceiver extends BroadcastReceiver { private boolean screenOff; @Override public void onReceive(Context context, Intent intent) { if (intent.getAction().equals(Intent.ACTION_SCREEN_OFF)) { screenOff = true; } else if (intent.getAction().equals(Intent.ACTION_SCREEN_ON)) { screenOff = false; } Intent i = new Intent(context, UpdateService.class); i.putExtra("screen_state", screenOff); context.startService(i); } } 

Mainfest.xml

 <receiver android:name=".MyReceiver"> <intent-filter> <action android:name="android.intent.action.SCREEN_OFF"/> <action android:name="android.intent.action.SCREEN_ON"/> </intent-filter> </receiver> <service android:name=".UpdateService" /> 

También mencione si debo incluir algo en mi archivo mainactivity.java o la actividad a la que redirigir.

He utilizado estos permisos:

 <uses-permission android:name="com.android.alarm.permission.SET_ALARM" /> <uses-permission android:name="android.permission.VIBRATE" /> <uses-permission android:name="android.permission.READ_CONTACTS" /> <uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" /> <uses-permission android:name="android.permission.WAKE_LOCK" /> <uses-permission android:name="android.permission.INTERNET" /> <uses-permission android:name="android.permission.SEND_SMS" /> <uses-permission android:name="android.permission.RECEIVE_SMS" /> <uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" /> <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" /> <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" /> <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" /> <uses-permission android:name="android.permission.ACCESS_WIFI_STATE" /> 

No tienes código completo para saber con seguridad, pero déjame hacer una conjetura educada:

No implementaste una Aplicación o Actividad sí?

Creo que necesita al menos uno de ellos para registrar el receptor en onCreate () onResume () callbacks, simplemente indicando un receptor en el manifiesto NO PUEDE funcionar.

Y la depuración en eclipse o cualquier otro IDE con la integración de Android puede ser realmente útil, ya que muestra los procesos de su aplicación, y usted puede saber con certeza si han surgido o no. Un poco de depuración le dirá si su receptor está funcionando correctamente.

Si te interesa compartir más código, podemos por supuesto discutir más.

¿Prueba esto?

 MyService public class MyService extends Service { @Override public void onCreate() { super.onCreate(); ... if (!registered) { MyReceiver mybroadcast = new MyReceiver() { registerReceiver(mybroadcast, new IntentFilter(Intent.ACTION_SCREEN_ON)); registerReceiver(mybroadcast, new IntentFilter(Intent.ACTION_SCREEN_OFF)); } } } MyReceiver public class MyReceiver extends BroadcastReceiver { @Override public void onReceive(Context context, Intent intent) { ... } } BootStartUpReciever public class BootStartUpReciever extends BroadcastReceiver { @Override public void onReceive(Context context, Intent intent) { // Start Service On Boot Start Up Intent service = new Intent(context, MyService.class); context.startService(service); } } Manifest <service android:name="my.package.MyService" /> <receiver android:name="my.package.BootStartUpReciever" android:enabled="true" android:exported="true" > <intent-filter> <action android:name="android.intent.action.BOOT_COMPLETED" /> <category android:name="android.intent.category.LAUNCHER" /> </intent-filter> </receiver> 

Creo que no hay necesidad de la clase de servicio para su requisito. Porque va a iniciar una actividad cuando se llama a la pantalla de acción. Por favor, remítase a mi siguiente implementación y comparta sus pensamientos.

 //Application class. public class MyApplication extends Application { static String TAG = "MyApplication"; @Override public void onCreate() { super.onCreate(); IntentFilter intentFilter = new IntentFilter(Intent.ACTION_SCREEN_ON); intentFilter.addAction(Intent.ACTION_SCREEN_OFF); registerReceiver(new BroadcastReceiver() { @Override public void onReceive(Context context, Intent intent) { // screen off if (intent.getAction().equals(Intent.ACTION_SCREEN_OFF)) { Log.d(TAG, Intent.ACTION_SCREEN_OFF); //screen on } else if (intent.getAction().equals(Intent.ACTION_SCREEN_ON)) { Log.d(TAG, Intent.ACTION_SCREEN_ON); // To open your main activity. Intent i = new Intent(); i.setClass(context, MainActivity.class); i.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP); i.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); context.startActivity(i); } } }, intentFilter); } } // Manifest.xml <?xml version="1.0" encoding="utf-8"?> <manifest xmlns:android="http://schemas.android.com/apk/res/android" package="com.hopabit.wakeup" android:versionCode="1" android:versionName="1.0" > <uses-sdk android:minSdkVersion="8" android:targetSdkVersion="19" /> <application android:name=".MyApplication" android:allowBackup="true" android:icon="@drawable/ic_launcher" android:label="@string/app_name" android:theme="@style/AppTheme" > <activity android:name="com.hopabit.wakeup.MainActivity" android:label="@string/app_name" > <intent-filter> <action android:name="android.intent.action.MAIN" /> <category android:name="android.intent.category.LAUNCHER" /> </intent-filter> </activity> </application> </manifest> 

Con el fin de mantener su servicio en funcionamiento es necesario poner en un hilo. Asegúrese de que el servicio está en un hilo extra, ya que un servicio por sí mismo no es un proceso o hilo adicional. Esto podría hacerse, por ejemplo, con un Handler .

 HandlerThread thread = new HandlerThread(SERVICE_THREAD_NAME); thread.start(); handlerThreadId = thread.getId(); serviceLooper = thread.getLooper(); serviceHandler = new ServiceHandler(serviceLooper); 

Vi tu código. Estás muy cerca de la solución.

Regístrese su receptor de ancho de banda tanto para la pantalla de eventos como para la pantalla dentro de la onCreate () de su actividad

 if (!registered) { MyReceiver mybroadcast = new MyReceiver() { registerReceiver(mybroadcast, new IntentFilter(Intent.ACTION_SCREEN_ON)); registerReceiver(mybroadcast, new IntentFilter(Intent.ACTION_SCREEN_OFF)); } 

Mantener un contador int en preferencia compartida o en cualquier otro lugar, inicializado con 0 al principio e incrementar ese contador en onReceive ():

 public class MyReceiver extends BroadcastReceiver { private boolean screenOff; @Override public void onReceive(Context context, Intent intent) { int counter = get counter value from shared preference. if (intent.getAction().equals(Intent.ACTION_SCREEN_OFF)) { screenOff = true; //increment the counter++ } else if (intent.getAction().equals(Intent.ACTION_SCREEN_ON)) { screenOff = false; //increment the counter++ } if(counter>3){ Intent i = new Intent(context, UpdateService.class); i.putExtra("screen_state", screenOff); context.startService(i); } } } 

Puede iniciar el servicio y repetirlo con frecuencia y también escuchar el evento en el arranque. Puede utilizar este enlace que tiene un servicio funcionando todo el tiempo. https://github.com/commonsguy/cwac-wakeful Podría ayudar en su problema.

Creo que lo que necesitas es usar un IntentService.

Te diré por qué:

El servicio se está ejecutando en el subproceso de interfaz de usuario (incluso cuando están en segundo plano), por lo que es mejor para la interacción con la interfaz de usuario, pero por otro lado, no deben estar en ejecución durante un período largo de tiempo como desee. Aparte, el IntentService se está ejecutando en otro hilo, por lo que es mejor utilizarlos para las tareas de fondo que son más largos.

Lo que debe hacer es guardar en la memoria (utilizando el objeto Aplicación) u otro Singleton las veces que el estado de encendido / apagado de la pantalla.

Si necesita más ayuda, avíseme

FlipAndroid es un fan de Google para Android, Todo sobre Android Phones, Android Wear, Android Dev y Aplicaciones para Android Aplicaciones.