how to start a service when starting the device?

2

I need to start a service when the device starts up. I have searched the Internet and I have implemented what is necessary, but I get an error and I can not solve it, try not to start a service but an activity and it works then I do not know what may be happening.

Monitor Class

    public class Monitor extends BroadcastReceiver {
    @Override
    public void onReceive(Context context, Intent intent) {
        /*Intent i = new Intent(context, MainEventos.class);
        i.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
        context.startActivity(i);*/
        Intent service = new Intent(context.getApplicationContext(),  ServicioNotificaciones.class);
        context.startService(service);
    }
}

Android Manifest

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

<application
    android:allowBackup="true"
    android:icon="@mipmap/ic_launcher"
    android:label="@string/app_name"
    android:roundIcon="@mipmap/ic_launcher_round"
    android:supportsRtl="true"
    android:theme="@style/AppTheme">
    <activity android:name=".MainActivity">
        <intent-filter>
            <category android:name="android.intent.category.DEFAULT" />
        </intent-filter>
    </activity>
    <receiver android:name=".Monitor" >
        <intent-filter>
            <action android:name="android.intent.action.BOOT_COMPLETED" />
        </intent-filter>
    </receiver>
    <service android:name="com.example.alex_.girardotaeventos.ServicioNotificaciones"
        android:exported="true">
        <intent-filter>
            <action android:name="com.example.alex_.girardotaeventos.ServicioNotificaciones"></action>
        </intent-filter>
    </service>

    <activity android:name=".activity_splash_screen" android:theme="@style/AppTheme.NoActionBar" android:configChanges="screenSize|orientation">
        <intent-filter>
            <action android:name="android.intent.action.MAIN" />
            <category android:name="android.intent.category.LAUNCHER" />
        </intent-filter>
    </activity>
    <activity android:name=".MainEventos" android:configChanges="screenSize|orientation">
        <intent-filter>
            <category android:name="android.intent.category.DEFAULT" />
        </intent-filter>
    </activity>
    <activity android:name=".MainItem" android:label="Evento" android:parentActivityName=".MainEventos">
        <meta-data android:name="android.support.PARENT_ACTIVITY" android:value=".MainEventos">
        </meta-data>
        <intent-filter>
            <category android:name="android.intent.category.DEFAULT" />
        </intent-filter>
    </activity>
</application>

Service

public class ServicioNotificaciones extends Service {
int numFilas=0;
private NotificationManager notification;
@Override
public void onCreate(){

}

@Override
public int onStartCommand(Intent intent, int flag, int proccess){

    notification = (NotificationManager) getSystemService(NOTIFICATION_SERVICE);

    final Handler handler = new Handler();
    Timer timer = new Timer();

    TimerTask task = new TimerTask() {
        @Override
        public void run() {
            handler.post(new Runnable() {
                @RequiresApi(api = Build.VERSION_CODES.O)
                public void run() {
                    final String[] descripcion = new String[1];
                    try {
                        final AsyncHttpClient client = new AsyncHttpClient();
                        client.get("http://192.168.1.101/androidimg/UltimaImagen.php", new AsyncHttpResponseHandler() {
                            @Override
                            public void onSuccess(int statusCode, Header[] headers, byte[] responseBody) {
                                if (statusCode == 200){
                                    try {
                                        JSONArray jsonArray = new JSONArray(new String(responseBody));
                                        descripcion[0] = jsonArray.getJSONObject(0).getString("descripcion");
                                        Log.d("DESCR",descripcion[0].toString());
                                    }catch (JSONException e){
                                        e.printStackTrace();
                                    }
                                }
                            }
                            @Override
                            public void onFailure(int statusCode, Header[] headers, byte[] responseBody, Throwable error) {

                            }
                        });

                        final int edad = getEdad("edad",getApplicationContext());
                        final String genero = getGenero("genero",getApplicationContext());

                        final int[] fila = new int[1];
                        final AsyncHttpClient clientt = new AsyncHttpClient();
                        clientt.get("http://192.168.1.101/androidimg/numFilas.php", new AsyncHttpResponseHandler() {
                            @Override
                            public void onSuccess(int statusCode, Header[] headers, byte[] responseBody) {
                                if (statusCode == 200){
                                    try {
                                        JSONArray jsonArray = new JSONArray(new String(responseBody));
                                        fila[0] = jsonArray.getJSONObject(0).getInt("filas");
                                        if (fila[0]>numFilas && numFilas!=0 && edad>=Integer.valueOf(descripcion[0].toString().substring(0,2)) &&
                                                edad<=Integer.valueOf(descripcion[0].toString().substring(3,5)) &&
                                                descripcion[0].indexOf(genero)!=-1){
                                            NotificationUtils notUtils = new NotificationUtils(getApplicationContext());
                                            Notification.Builder nb = notUtils.
                                                    getAndroidChannelNotification("Nuevo Evento","Se ha agregado un nuevo evento");
                                            notUtils.getManager().notify(101, nb.build());
                                        }
                                        numFilas = fila[0];
                                    }catch (JSONException e){
                                        e.printStackTrace();
                                    }
                                }
                            }

                            @Override
                            public void onFailure(int statusCode, Header[] headers, byte[] responseBody, Throwable error) {

                            }
                        });

                    } catch (Exception e) {
                        Log.e("error", e.getMessage());
                    }
                }
            });
        }
    };
    timer.schedule(task, 0, 6000);
    return START_STICKY;
}

@TargetApi(Build.VERSION_CODES.M)
private void notification1(int id, int iconId, String titulo, String contenido){

    NotificationCompat.Builder builder =
            (NotificationCompat.Builder) new NotificationCompat.Builder(this)
                    .setSmallIcon(iconId)
                    .setLargeIcon(BitmapFactory.decodeResource(getResources(),R.mipmap.ic_launcher))
                    .setContentTitle(titulo)
                    .setContentText(contenido)
                    .setColor(getResources().getColor(R.color.colorAccent,null));
    notification.notify(id,builder.build());
}

public void onDestroy(){
}

@Nullable
@Override
public IBinder onBind(Intent intent) {
    return null;
}

public class NotificationUtils extends ContextWrapper {

    private NotificationManager mManager;
    public static final String ANDROID_CHANNEL_ID = "com.chikeandroid.tutsplustalerts.ANDROID";
    public static final String IOS_CHANNEL_ID = "com.chikeandroid.tutsplustalerts.IOS";
    public static final String ANDROID_CHANNEL_NAME = "ANDROID CHANNEL";
    public static final String IOS_CHANNEL_NAME = "IOS CHANNEL";

    @RequiresApi(api = Build.VERSION_CODES.O)
    public NotificationUtils(Context base) {
        super(base);
        createChannels();
    }

    @RequiresApi(api = Build.VERSION_CODES.O)
    private void createChannels() {

        // create android channel
        NotificationChannel androidChannel = new NotificationChannel(ANDROID_CHANNEL_ID,
                ANDROID_CHANNEL_NAME, NotificationManager.IMPORTANCE_DEFAULT);
        // Sets whether notifications posted to this channel should display notification lights
        androidChannel.enableLights(true);
        // Sets whether notification posted to this channel should vibrate.
        androidChannel.enableVibration(true);
        // Sets the notification light color for notifications posted to this channel
        androidChannel.setLightColor(Color.GREEN);
        // Sets whether notifications posted to this channel appear on the lockscreen or not
        androidChannel.setLockscreenVisibility(Notification.VISIBILITY_PRIVATE);

        getManager().createNotificationChannel(androidChannel);


        // create ios channel
        NotificationChannel iosChannel = new NotificationChannel(IOS_CHANNEL_ID,
                IOS_CHANNEL_NAME, NotificationManager.IMPORTANCE_HIGH);
        iosChannel.enableLights(true);
        iosChannel.enableVibration(true);
        iosChannel.setLightColor(Color.GRAY);
        iosChannel.setLockscreenVisibility(Notification.VISIBILITY_PUBLIC);
        getManager().createNotificationChannel(iosChannel);
    }

    private NotificationManager getManager() {
        if (mManager == null) {
            mManager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
        }
        return mManager;
    }

    @RequiresApi(api = Build.VERSION_CODES.O)
    public Notification.Builder getAndroidChannelNotification(String title, String body) {
        Intent intent = new Intent(getApplicationContext(), MainEventos.class);
        PendingIntent pendingIntent = PendingIntent.getActivity(getApplicationContext(),0,intent,0);
        return new Notification.Builder(getApplicationContext(), ANDROID_CHANNEL_ID)
                .setContentTitle(title)
                .setContentText(body)
                .setContentIntent(pendingIntent)
                .setSmallIcon(android.R.drawable.stat_notify_more)
                .setAutoCancel(true);
    }
}
public static int getEdad(String key, Context context) {
    SharedPreferences preferences = PreferenceManager.getDefaultSharedPreferences(context);
    return preferences.getInt(key, 0);
}
public static String getGenero(String key, Context context) {
    SharedPreferences preferences = PreferenceManager.getDefaultSharedPreferences(context);
    return preferences.getString(key, null);
}

}

Errors

09-26 15:02:48.231 2989-2989/com.example.alex_.girardotaeventos E/AndroidRuntime: FATAL EXCEPTION: main
                                                                              Process: com.example.alex_.girardotaeventos, PID: 2989
                                                                              java.lang.RuntimeException: Unable to start receiver com.example.alex_.girardotaeventos.Monitor: java.lang.IllegalStateException: Not allowed to start service Intent { cmp=com.example.alex_.girardotaeventos/.ServicioNotificaciones }: app is in background uid UidRecord{5dec8da u0a103 RCVR idle procs:1 seq(0,0,0)}
                                                                                  at android.app.ActivityThread.handleReceiver(ActivityThread.java:3259)
                                                                                  at android.app.ActivityThread.-wrap17(Unknown Source:0)
                                                                                  at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1677)
                                                                                  at android.os.Handler.dispatchMessage(Handler.java:105)
                                                                                  at android.os.Looper.loop(Looper.java:164)
                                                                                  at android.app.ActivityThread.main(ActivityThread.java:6541)
                                                                                  at java.lang.reflect.Method.invoke(Native Method)
                                                                                  at com.android.internal.os.Zygote$MethodAndArgsCaller.run(Zygote.java:240)
                                                                                  at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:767)
                                                                               Caused by: java.lang.IllegalStateException: Not allowed to start service Intent { cmp=com.example.alex_.girardotaeventos/.ServicioNotificaciones }: app is in background uid UidRecord{5dec8da u0a103 RCVR idle procs:1 seq(0,0,0)}
                                                                                  at android.app.ContextImpl.startServiceCommon(ContextImpl.java:1505)
                                                                                  at android.app.ContextImpl.startService(ContextImpl.java:1461)
                                                                                  at android.content.ContextWrapper.startService(ContextWrapper.java:644)
                                                                                  at android.content.ContextWrapper.startService(ContextWrapper.java:644)
                                                                                  at com.example.alex_.girardotaeventos.Monitor.onReceive(Monitor.java:18)
                                                                                  at android.app.ActivityThread.handleReceiver(ActivityThread.java:3252)
                                                                                  at android.app.ActivityThread.-wrap17(Unknown Source:0) 
                                                                                  at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1677) 
                                                                                  at android.os.Handler.dispatchMessage(Handler.java:105) 
                                                                                  at android.os.Looper.loop(Looper.java:164) 
                                                                                  at android.app.ActivityThread.main(ActivityThread.java:6541) 
                                                                                  at java.lang.reflect.Method.invoke(Native Method) 
                                                                                  at com.android.internal.os.Zygote$MethodAndArgsCaller.run(Zygote.java:240) 
                                                                                  at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:767) 
    
asked by ALEX MAURICIO CADAVID QUICENO 26.09.2017 в 17:00
source

1 answer

0

To start a service when you turn on your device:

You are already doing this when defining the action to your BroadcastReceiver that is the one that starts the service, only add android:enabled="true" and permission android:permission="android.permission.RECEIVE_BOOT_COMPLETED" :

<receiver android:enabled="true" android:name=".Monitor" android:permission="android.permission.RECEIVE_BOOT_COMPLETED">
        <intent-filter>
            <action android:name="android.intent.action.BOOT_COMPLETED" />
        </intent-filter>
    </receiver>

Remember that the full initialization ( BOOT_COMPLETED ), is done a few seconds after you see the device turned on.

I add a example of a service that starts on power up the device.

Regarding the error:

  

java.lang.RuntimeException: Unable to start receiver   com.example.alex_.girardotaeventos.Monitor:   java.lang.IllegalStateException: Not allowed to start service Intent {   cmp = com.example.alex_.girardotaeventos / .ServicioNotificaciones}: app   is in background uid UidRecord {5dec8da u0a103 RCVR idle procs: 1   seq (0,0,0)}

The Monitor class is the BroadcastReceiver that starts the service,

public class Monitor extends BroadcastReceiver {

and the service is class ServicioNotificaciones :

public class ServicioNotificaciones extends Service {

The problem is that the intent-filter BOOT_COMPLETED must be defined for the BroadcastReceiver but for the service you should not have it defined, delete that part :

<receiver android:enabled="true" android:name=".Monitor" android:permission="android.permission.RECEIVE_BOOT_COMPLETED">
        <intent-filter>
            <action android:name="android.intent.action.BOOT_COMPLETED" />
        </intent-filter>
    </receiver>
   <service android:enabled="true" android:name="com.example.alex_.girardotaeventos.ServicioNotificaciones"
    android:exported="true">
   </service>

The BroadcastReceiver (class Monitor ) must be the one that starts the service , which is correct.

  @Override
    public void onReceive(Context context, Intent intent) {
        Intent service = new Intent(context.getApplicationContext(),  ServicioNotificaciones.class);
        service.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
        context.startService(service);
    }
    
answered by 26.09.2017 в 17:04