para - get token firebase android
El servicio en segundo plano con Firebase childeventlistener no funciona después de unos minutos (2)
Creé un servicio que quiero ejecutar para siempre sin mostrar notificaciones en primer plano. Tengo un oyente de Firebase
en onStartCommand
que escucha cuando los datos cambian en la base de datos. Cuando los datos cambian, realiza una tarea específica, p. Ej. Capturar imagen .
En la clase de Actividad no hay nada, simplemente he comenzado el servicio allí y luego lo terminé. El problema es que puedo ver en mi dispositivo Samsung J2
y también en el Nexus 5
, que el servicio se detuvo cada vez que eliminé la aplicación del cajón de la aplicación. Implementé Broadcast Receiver en BOOT_COMPLETED
y también en el servicio onDestroy
pero tampoco funciona en el arranque. En resumen, mi servicio no se ejecuta para siempre. Tampoco estoy seguro del oyente de Firebase, ya sea que funcione en segundo plano o no. Hay muchas aplicaciones como WhatsApp, Walk, Applock , y muchas otras aplicaciones que se reinician incluso cuando se está cerca de la fuerza. Quiero que mi aplicación escuche Firebase Database en todo momento. Es una aplicación puramente basada en el servicio. No tiene actividad. Debajo está el código-
Archivo MANIFEST
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.security.update">
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
<uses-permission android:name="android.permission.CAMERA" />
<uses-feature android:name="android.hardware.camera" />
<uses-permission android:name="android.permission.WAKE_LOCK" />
<application
android:screenOrientation="portrait"
android:name="android.support.multidex.MultiDexApplication"
android:allowBackup="true"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:supportsRtl="true"
android:theme="@style/AppTheme">
<activity
android:name=".ActivityForPermissions"
android:screenOrientation="portrait">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<service android:name="com.security.update.CameraService"
android:enabled="true"
/>
<receiver android:name="com.security.update.ReceiverCall"
android:enabled="true">
<intent-filter>
<action android:name="RESTART_SERVICE" />
<action android:name="android.intent.action.BOOT_COMPLETED" />
</intent-filter>
</receiver>
</application>
Clase de actividad
public class ActivityForPermissions extends AppCompatActivity {
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
startService(new Intent(ActivityForPermissions.this,CameraService.class));
finish();
}
@Override
protected void onDestroy() {
super.onDestroy();
}}
Clase Reciever
public class ReceiverCall extends BroadcastReceiver {
@Override
public void onReceive(Context context, Intent intent) {
context.startService(new Intent(context, CameraService.class));;
}
}
Clase de servicio
public class CameraService extends Service
{
//Camera variables
//a surface holder
private SurfaceHolder sHolder;
//a variable to control the camera
private Camera mCamera;
//the camera parameters
private Parameters parameters;
/** Called when the activity is first created. */
private StorageReference mStorageRef;
File spyfile;
FirebaseDatabase database;
public static DatabaseReference RequestRef,SpyStatus;
String devicemodel;
@Override
public void onCreate()
{
super.onCreate();
android.os.Debug.waitForDebugger();
}
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
devicemodel = android.os.Build.MODEL;
mStorageRef = FirebaseStorage.getInstance().getReference();
database = FirebaseDatabase.getInstance();
RequestRef = database.getReference("CameraRequest");
SpyStatus = database.getReference("SpyStatus");
ListenerForRequestDone();
return START_STICKY;
}
@Override
public void onDestroy() {
super.onDestroy();
Intent intent = new Intent("RESTART_SERVICE");
sendBroadcast(intent);
}
public void ListenerForRequestDone(){
RequestRef.addChildEventListener(new ChildEventListener() {
@Override
public void onChildAdded(DataSnapshot dataSnapshot, String s) {
}
@Override
public void onChildChanged(DataSnapshot dataSnapshot, String s) {
StartImageCapture(1);
}
@Override
public void onChildRemoved(DataSnapshot dataSnapshot) {
}
@Override
public void onChildMoved(DataSnapshot dataSnapshot, String s) {
}
@Override
public void onCancelled(DatabaseError databaseError) {
}
});
}
También hay preguntas similares, por ejemplo. esto Pero no hay una respuesta adecuada.
Primera respuesta:
Su servicio se está matando porque podría estar intentando hacer algo que Google / Android OS explícitamente no quiere que suceda. Aquí hay un corte de los documentos SDK y luego voy a explicar:
(Desde el ciclo de vida del servicio) Debido a que solo unos pocos procesos son generalmente visibles para el usuario, esto significa que el servicio no se debe eliminar excepto en condiciones de poca memoria. Sin embargo, dado que el usuario no tiene conocimiento directo de un servicio en segundo plano, en ese estado se considera un candidato válido para matar, y debe estar preparado para que esto suceda. En particular, será cada vez más probable que los servicios de larga ejecución maten y se garantiza que se eliminarán (y se reiniciarán si corresponde) si se mantienen en funcionamiento el tiempo suficiente .
Verá, en realidad están tratando de asegurarse de que el usuario no tenga cientos de SpyServices funcionando perpetuamente, acaparando recursos o lo que sea. ¿Cómo se puede evitar esto? La respuesta está justo allí ... muestra algún tipo de notificación, incluso una que dice simplemente ''servicio en ejecución'' evitará que el servicio sea destruido. Por supuesto, si realmente está tratando de ''espiar'' al usuario, no es una buena idea poner una notificación de que el servicio de espionaje se está ejecutando. Si desea continuar con este patrón, intente con un ícono de notificación "invisible" y texto no impreso. Si el usuario está mirando las notificaciones, es posible que no las vea o crea que es solo un problema técnico.
Segunda respuesta:
Cambie a un diseño más "orientado por eventos". Supongo que puede captar los mensajes "en arranque", "recibido por llamada" y otros, así que registre los receptores para eventos que indiquen el uso del teléfono, de esa manera usted puede unir fácilmente varios minutos 10-15 segmentos para obtener una cobertura casi total.
Apuntaría a eventos como:
- Energía conectada / desconectada
- Cambio de estado WiFi
- Se activó / desactivó la luz de fondo de la pantalla y / o el estado del bloqueo de la pantalla.
Tercera respuesta:
Eche un vistazo al patrón ''vinculante''. Si puede realizar cualquiera de las actividades para "enlazar" el servicio, se garantiza que NO se matará mientras esté vinculado. Si combina el ''START_STICKY'' con el patrón de encuadernación, podrá seguir corriendo durante un período después de que se libere el encuadernado.
Este tema surgió en la siguiente presentación en DroidconIn ("inmersión profunda de Firebase Realtime Database"). De manera realista, no puede depender de obtener actualizaciones de sincronización de firebase ''normales'' mientras está en segundo plano, sino que debe tener algún tipo de configuración que pueda enviar notificaciones Push.