Starting a background service when the OS boots - java

I'm trying to start my background service when the device boots, but nothing is happening. This is my code:
AndroidManifest.xml
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="it.test"
android:permission="android.permission.RECEIVE_BOOT_COMPLETED">
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />
<application
android:allowBackup="true"
android:icon="#mipmap/ic_launcher"
android:label="#string/app_name"
android:supportsRtl="true"
android:theme="#style/AppTheme">
<activity android:name=".MainActivity">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
</application>
</manifest>
Autostart.java
package it.test;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.util.Log;
public class Autostart extends BroadcastReceiver {
#Override
public void onReceive(Context arg0, Intent arg1) {
Intent intent = new Intent(arg0, AppService.class);
arg0.startService(intent);
Log.e("it.Test", "***** SERVER STARTING CALLED *****");
}
}
AppService.java
package it.test;
import android.app.Service;
import android.content.Intent;
import android.os.IBinder;
import android.util.Log;
import android.widget.Toast;
public class AppService extends Service {
#Override
public IBinder onBind(Intent intent) {
return null;
}
#Override
public void onDestroy() {
Toast.makeText(this, "My AppService Stopped", Toast.LENGTH_LONG).show();
Log.e("it.Test", "***** SERVICE STOPPED *****");
}
#Override
public void onStart(Intent intent, int startid) {
Toast.makeText(this, "My AppService Started", Toast.LENGTH_LONG).show();
Log.e("it.Test", "***** SERVICE STARTED *****");
/*
MainActivity.calc();
MainActivity.save();
*/
}
}
When my phone boots I don't see any toast (I don't see either the "My AppService Started" nor the "My AppService Stopped" toast) and nothing gets logged by the application...
Anyone knows what I am doing wrong??
Thanks!
EDIT: Solution to the problem
After seeing the post Trying to start a service on boot on Android linked in an answer and after many debugging I found the solution to my problem :) Thank to everyone!
Modification to AndroidManifest.xml
Added inside <application>:
<receiver android:name="it.test.Autostart">
<intent-filter>
<action android:name="android.intent.action.BOOT_COMPLETED" />
</intent-filter>
</receiver>
<service
android:name="it.test.AppService"
android:enabled="true" />
Added also:
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
[...]
android:installLocation="internalOnly">
Modifications to AppService.java
To make the service work, I had to override in the AppService class onStartCommand instead of onStart, so I completely removed the method onStart from my class.
New onStartCommand:
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
Toast.makeText(this, "My AppService Started", Toast.LENGTH_LONG).show();
Log.e("it.Test", "***** SERVICE STARTED ***** from onStartCommand");
MainActivity.calc(this);
MainActivity.save();
return Service.START_REDELIVER_INTENT;//todo I'm not sure about what I have to return
}

Your broadcast receiver is not registered at AndroidManifest.xml
You need to register the broadcast receiver:
<receiver android:name=".<RECEIVER_NAME>">
<intent-filter>
<action android:name="android.intent.action.BOOT_COMPLETED" />
</intent-filter>
</receiver>
If your app is installed to external storage it won't receive BOOT_COMPLETE broadcast message. To prevent this you can install your application in internal storage. you can do this just adding this line in AndroidManifest.xml
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
android:installLocation="internalOnly"
... >
Source: https://stackoverflow.com/a/32938071/1549700

You have you register your broadcast receiver and service under the <application> tag
<!-- [START service_listener] -->
<service
android:name=".it.test.AppService"
android:enabled="true" />
<!-- [END service_listener] -->
<!-- [START broadcast_receiver] -->
<receiver android:name=".it.test.Autostart">
<intent-filter>
<action android:name="android.intent.action.BOOT_COMPLETED" />
</intent-filter>
</receiver>
<!-- [END broadcast_receiver] -->

You need to register the broadcast receiver:
<receiver android:name=".Autostart">
<intent-filter>
<action android:name="android.intent.action.BOOT_COMPLETED" />
</intent-filter>
</receiver>

You need this in your manifest file:
<receiver android:name=".it.test.Autostart">
<intent-filter>
<action android:name="android.intent.action.BOOT_COMPLETED"/>
</intent-filter>
</receiver>

Have you register broadcast receiver in manifest file and also also give boot completed permission in your broadcast receiver, if any problem then ask in comment, your code is perfect.

Related

How to dispatch intent to MainActivity from another activity? (react native)

I've created a custom deep link dispatcher in Java within a react native project.
The issue I'm having is that I can't get MainActivity to start from my dispatcher, and I can't quite figure out why.
I have AndroidManifest set up so that the deep link is captured in LinkDispatcherActivity effectively, but the startActivity(dispatchedIntent) never reaches MainActivity, which is where I assume it needs to go. Ordinarily in AndroidManifest.xml, deep links would be sent to MainActivity).
It does open the app, but I assume it's because LinkDispatcherActivity is part of the app? Not sure, if I say something dumb it's because this is only my 3rd day in a row writing Java 😰
Below is my code.
package com.example.app;
//Inspired by https://github.com/justeat/Android.Samples.Deeplinks, Licensed under Apache 2.0
import android.app.Activity;
import android.content.Intent;
import android.net.Uri;
import android.os.Bundle;
import android.util.Log;
import net.openid.appauth.RedirectUriReceiverActivity;
public class LinkDispatcherActivity extends Activity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
try {
dispatchIntent(getIntent());
} catch (IllegalArgumentException iae) {
// Malformed URL
if (BuildConfig.DEBUG) {
Log.e("Deep links", "Invalid URI", iae);
}
} finally {
// Always finish the activity so that it doesn't stay in our history
finish();
}
}
public void dispatchIntent(Intent intent) {
final Uri uri = intent.getData();
final String host = uri.getHost().toLowerCase();
if (uri == null) throw new IllegalArgumentException("Uri cannot be null");
// Default intent
Intent dispatchedIntent = new Intent(LinkDispatcherActivity.this, MainActivity.class);
dispatchedIntent.setData(uri);
intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP | Intent.FLAG_ACTIVITY_SINGLE_TOP);
Log.d(dispatchedIntent.getDataString(), "dispatchIntent: intent string");
// Auth intent only, this is why I need the dispatcher
if ("login".equals(host)) {
dispatchedIntent = new Intent(this, RedirectUriReceiverActivity.class);
dispatchedIntent.putExtra("requestCode", 0);
Log.d("Login", "mapAppLink: ");
startActivityForResult(dispatchedIntent, 0);
return;
}
Log.d("Default", "mapAppLink: ");
startActivity(dispatchedIntent);
}
}
This is what my AndroidManifest.xml looks like:
<manifest xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools"
package="com.example.app">
<!-- < Only if you're using GCM or localNotificationSchedule() > -->
<uses-permission android:name="android.permission.WAKE_LOCK" />
<permission
android:name="${applicationId}.permission.C2D_MESSAGE"
android:protectionLevel="signature" />
<uses-permission android:name="${applicationId}.permission.C2D_MESSAGE" />
<!-- < Only if you're using GCM or localNotificationSchedule() > -->
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.CAMERA" />
<uses-permission android:name="android.permission.VIBRATE" />
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />
<application
android:name=".MainApplication"
android:allowBackup="false"
android:icon="#mipmap/ic_launcher"
android:label="#string/app_name"
android:roundIcon="#mipmap/ic_launcher_round"
android:theme="#style/AppTheme"
android:requestLegacyExternalStorage="true">
<meta-data
android:name="com.google.android.geo.API_KEY"
android:value="<redacted>" />
<!-- < Notification Services > -->
<meta-data
android:name="com.google.firebase.messaging.default_notification_icon"
android:resource="#mipmap/ic_notification" />
<meta-data
android:name="com.google.firebase.messaging.default_notification_color"
tools:replace="android:resource"
android:resource="#color/colorAccent" />
<!-- Change the value to true to enable pop-up for in foreground on receiving remote notifications (for prevent duplicating while showing local notifications set this to false) -->
<meta-data android:name="com.dieam.reactnativepushnotification.notification_foreground"
android:value="true"/>
<meta-data
android:name="com.google.firebase.messaging.default_notification_channel_id"
tools:replace="android:value"
android:value="rn-push-notification-channel-id" />
<meta-data android:name="com.dieam.reactnativepushnotification.notification_channel_name" android:value="Default Channel"/>
<meta-data android:name="com.dieam.reactnativepushnotification.notification_channel_description" android:value="Default channel for push notifications"/>
<meta-data
android:name="com.dieam.reactnativepushnotification.notification_color"
android:resource="#color/colorAccent" />
<receiver android:name="com.dieam.reactnativepushnotification.modules.RNPushNotificationActions" />
<receiver android:name="com.dieam.reactnativepushnotification.modules.RNPushNotificationPublisher" />
<receiver android:name="com.dieam.reactnativepushnotification.modules.RNPushNotificationBootEventReceiver">
<intent-filter>
<action android:name="android.intent.action.BOOT_COMPLETED" />
<action android:name="android.intent.action.QUICKBOOT_POWERON" />
<action android:name="com.htc.intent.action.QUICKBOOT_POWERON"/>
</intent-filter>
</receiver>
<!-- START: Add this-->
<service
android:name=".MainNotificationService">
<intent-filter>
<action android:name="com.google.firebase.MESSAGING_EVENT"/>
</intent-filter>
</service>
<receiver
android:name="com.intercom.reactnative.RNIntercomPushBroadcastReceiver"
tools:replace="android:exported"
android:exported="true"/>
<activity
android:name=".MainActivity"
android:configChanges="keyboard|keyboardHidden|screenSize|uiMode"
android:launchMode="singleTask"
android:label="#string/app_name"
android:screenOrientation="portrait"
android:windowSoftInputMode="adjustResize">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
<action android:name="android.intent.action.DOWNLOAD_COMPLETE" />
</intent-filter>
</activity>
<activity android:name=".LinkDispatcherActivity"
tools:node="replace">
<intent-filter>
<action android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.DEFAULT" />
<category android:name="android.intent.category.BROWSABLE" />
<data
android:scheme="example"
android:host="login" />
</intent-filter>
</activity>
<activity android:name="com.facebook.react.devsupport.DevSettingsActivity" />
</application>
</manifest>
Edit: for the intent, I've tried:
new Intent(getApplicationContext(), MainActivity.class)
new Intent(reactContext, MainActivity.class) (extending ReactActivity instead of Activity)
new Intent(this, MainActivity.class)
new Intent("MainActivity")
Try adding RedirectUriReceiverActivity to the manifest - I couldn't see it in there.
<activity android:name="com.facebook.react.devsupport.RedirectUriReceiverActivity" />
This is what I ended up with for the LinkDispatcherActivity. To summarize, what I did was dispatch the intents that the deep activities were eventually supposed to invoke directly, instead of trying to forward the intent. In other words, if you're trying to pass an intent from one activity to another, maybe don't and consider dispatching the activity/function/intent that you want to run afterwards. I still think forwarding the intent should have worked, but this is what ended up working.
In order to accomplish the above, I:
Called a function within the AppAuth package that generates an intent, and dispatch it
Used ReactContext to emit the url listener event that React Native uses to respond to deep links.
Below is the code:
//Inspired by https://github.com/justeat/Android.Samples.Deeplinks, Licensed under Apache 2.0
package com.example.app;
import android.content.Intent;
import android.net.Uri;
import android.util.Log;
import net.openid.appauth.AuthorizationManagementActivity;
import com.facebook.react.ReactActivity;
import com.facebook.react.ReactInstanceManager;
import com.facebook.react.bridge.Arguments;
import com.facebook.react.bridge.ReactContext;
import com.facebook.react.bridge.WritableMap;
import com.facebook.react.modules.core.DeviceEventManagerModule;
public class LinkDispatcherActivity extends ReactActivity {
#Override
protected void onResume() {
super.onResume();
try {
dispatchIntent(getIntent());
} catch (IllegalArgumentException iae) {
// Malformed URL
if (BuildConfig.DEBUG) {
Log.e("Deep links", "Invalid URI", iae);
}
} finally {
// Always finish the activity so that it doesn't stay in our history
finish();
}
}
public void dispatchIntent(Intent intent) {
final Uri uri = intent.getData();
final String host = uri.getHost().toLowerCase();
if (uri == null) throw new IllegalArgumentException("Uri cannot be null");
// Default intent, e.g. settings, fitbit
// wait for react context
ReactInstanceManager reactInstanceManager = getReactInstanceManager();
ReactContext reactContext = reactInstanceManager.getCurrentReactContext();
Intent dispatchedIntent = new Intent(getApplicationContext(), MainActivity.class);
dispatchedIntent.setData(uri);
dispatchedIntent.putExtra("url", uri.toString());
dispatchedIntent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP | Intent.FLAG_ACTIVITY_SINGLE_TOP);
// Auth intent only
if ("login".equals(host)) {
Intent authIntent = AuthorizationManagementActivity.createResponseHandlingIntent(getApplicationContext(), uri);
startActivity(authIntent);
return;
}
// Below from https://stackoverflow.com/questions/48445010/send-data-from-android-activity-to-react-native?rq=1
WritableMap uriMap = Arguments.createMap();
uriMap.putString("url", uri.toString());
if(reactContext != null) {
reactContext.getJSModule(DeviceEventManagerModule.RCTDeviceEventEmitter.class)
.emit("url", uriMap);
// If there's no context, create a listener to wait for it
} else {
reactInstanceManager.addReactInstanceEventListener(new ReactInstanceManager.ReactInstanceEventListener() {
#Override
public void onReactContextInitialized(ReactContext context) {
context.getJSModule(DeviceEventManagerModule.RCTDeviceEventEmitter.class)
.emit("url", uriMap);
reactInstanceManager.removeReactInstanceEventListener(this);
}
});
}
}
}

Start an application after Android boot

I need to know how to make an application that I created in Android and made in Android Studio runs automatically when the device boots.
The only thing I have found is this guide https://codigofacilito.com/articulos/auto-ejecucion-de-una-aplicacion-al-inicio-de-un-depositivo-con-android but it does not run when the device starts.
ANDROID MANIFEST
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.resolucion.pruebaauto">
<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>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<receiver android:enabled="true"
android:name=".Auto"
android:permission="android.permission.RECEIVE_BOOT_COMPLETED">
<intent-filter>
<action android:name="android.intent.action.BOOT_COMPLETED"/>
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
</receiver>
</application>
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED"/>
</manifest>
BROADCAST RECEIVER
package com.resolucion.pruebaauto;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
public class Auto extends BroadcastReceiver{
public void onReceive(Context context,Intent intent) {
if (Intent.ACTION_BOOT_COMPLETED.equals(intent.getAction())) {
Intent i = new Intent(context, MainActivity.class);
i.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
context.startActivity(i);
}
}
}
MAINACTIVITY
package com.resolucion.pruebaauto;
import androidx.appcompat.app.AppCompatActivity;
import android.os.Bundle;
public class MainActivity extends AppCompatActivity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
}
}

BroadcastReceiver for Incoming calls in android doesn't work

I'm trying to develop android app for that can record phone calls. So, in the initial step, I've to see if BroadcastReceiver is getting fired or not.
I've added permissions, receiver tag in AndroidManifest file. I'm testing on OnePlus X. Activity is gets started but BroadcastReceiver doesn't get fired when I get call. What's going wrong here?
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.myapp">
<uses-permission android:name="android.permission.READ_PHONE_STATE" />
<application
android:allowBackup="true"
android:icon="#mipmap/ic_launcher"
android:label="#string/app_name"
android:supportsRtl="true"
android:theme="#style/AppTheme">
<activity
android:name="com.example.myapp.MainActivity"
android:label="#string/app_name"
android:screenOrientation="portrait">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<receiver android:name=".PhoneStateReceiver">
<intent-filter>
<action android:name="android.intent.action.PHONE_STATE" />
</intent-filter>
</receiver>
</application>
</manifest>
PhoneStateReceiver.Java
package com.example.myapp;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.telephony.TelephonyManager;
import android.widget.Toast;
public class PhoneStateReceiver extends BroadcastReceiver {
#Override
public void onReceive(Context context, Intent intent) {
try {
System.out.println("Receiver start");
String state = intent.getStringExtra(TelephonyManager.EXTRA_STATE);
String incomingNumber = intent.getStringExtra(TelephonyManager.EXTRA_INCOMING_NUMBER);
if(state.equals(TelephonyManager.EXTRA_STATE_RINGING)){
Toast.makeText(context,"Incoming Call State",Toast.LENGTH_SHORT).show();
Toast.makeText(context,"Ringing State Number is -"+incomingNumber,Toast.LENGTH_SHORT).show();
}
if ((state.equals(TelephonyManager.EXTRA_STATE_OFFHOOK))){
Toast.makeText(context,"Call Received State",Toast.LENGTH_SHORT).show();
}
if (state.equals(TelephonyManager.EXTRA_STATE_IDLE)){
Toast.makeText(context,"Call Idle State",Toast.LENGTH_SHORT).show();
}
}
catch (Exception e){
e.printStackTrace();
}
}
}
The permission READ_PHONE_STATE is a dangerous permission, if you are on a marshmallow device you must request runtime permission else your broadcast receiver will not work neither it will throw an error.
That is the most likely the cause of issue from your code because you have correctly registered in the Intent filter other than that there is nothing wrong as it is just a broadcast receiver and should work, i.e get called by the Android system.

Launching an application at start-up

I want my application to be automatically launched when the system is started. Can anyone tell me how to do that?
Thanks in advance for the time you will spend trying to help me.
First, you need the permission in your manifest:
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />
Also, in your manifest, define your service and listen for the boot-completed action:
<service android:name=".MyService" android:label="My Service">
<intent-filter>
<action android:name="com.myapp.MyService" />
</intent-filter>
</service>
<receiver
android:name=".receiver.StartMyServiceAtBootReceiver"
android:enabled="true"
android:exported="true"
android:label="StartMyServiceAtBootReceiver">
<intent-filter>
<action android:name="android.intent.action.BOOT_COMPLETED" />
</intent-filter>
</receiver>
Then you need to define the receiver that will get the BOOT_COMPLETED action and start your service.
public class StartMyServiceAtBootReceiver extends BroadcastReceiver {
#Override
public void onReceive(Context context, Intent intent) {
if ("android.intent.action.BOOT_COMPLETED".equals(intent.getAction())) {
Intent serviceIntent = new Intent("com.myapp.MySystemService");
context.startService(serviceIntent);
}
}
}
And now your service should be running when the phone starts up.
Here is Complete working Example Code,
AndroidManifest.xml
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.practice" android:versionCode="1" android:versionName="1.0">
<uses-sdk android:minSdkVersion="4" />
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED"></uses-permission>
<application android:icon="#drawable/icon" android:label="#string/app_name">
<activity android:name=".AutoStartExampleActivity"
android:label="#string/app_name">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<receiver android:name="AutoStart"></receiver>
<receiver android:name=".AutoStart">
<intent-filter>
<action android:name="android.intent.action.BOOT_COMPLETED" />
</intent-filter>
</receiver>
</application>
</manifest>
AutoStartExampleActivity File
package com.practice;
import android.app.Activity;
import android.os.Bundle;
public class AutoStartExampleActivity extends Activity {
/** Called when the activity is first created. */
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
}
}
BroadcastReceiver Code,
package com.practice;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
public class AutoStart extends BroadcastReceiver
{
public void onReceive(Context context, Intent intent)
{
System.out.println ( "Application Started" );
// put your TimerTask calling class here
try
{
Intent myIntent = new Intent ( context, AutoStartExampleActivity.class );
myIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
context.startActivity(myIntent);
}
catch ( Exception e )
{
System.out.println ( " Error while Starting Activity " + e.toString() );
}
}
}

Android - Start service on boot

From everything I've seen on Stack Exchange and elsewhere, I have everything set up correctly to start an IntentService when Android OS boots. Unfortunately it is not starting on boot, and I'm not getting any errors. Maybe the experts can help...
Manifest:
<?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 for Startup:
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);
}
}
UPDATE: I tried just about all of the suggestions below, and I added logging such as Log.v("BatteryLogger", "Got to onReceive, about to start service"); to the onReceive handler of the StartupIntentReceiver, and nothing is ever logged. So it isn't even making it to the BroadcastReceiver.
I think I'm deploying the APK and testing correctly, just running Debug in Eclipse and the console says it successfully installs it to my Xoom tablet at \BatteryLogger\bin\BatteryLogger.apk. Then to test, I reboot the tablet and then look at the logs in DDMS and check the Running Services in the OS settings. Does this all sound correct, or am I missing something? Again, any help is much appreciated.
Well here is a complete example of an AutoStart Application
AndroidManifest file
<?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 - This will pop-up everytime you start the device after executing the Applicaton once.
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();
}
}
Following should work. I have verified. May be your problem is somewhere else.
Receiver:
public class MyReceiver extends BroadcastReceiver{
#Override
public void onReceive(Context context, Intent intent) {
if (Intent.ACTION_BOOT_COMPLETED.equals(arg1.getAction())) {
Log.d("TAG", "MyReceiver");
Intent serviceIntent = new Intent(context, Test1Service.class);
context.startService(serviceIntent);
}
}
}
Service:
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;
}
}
Manifest:
<?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>
Your Service may be getting shut down before it completes due to the device going to sleep after booting. You need to obtain a wake lock first. Luckily, the Support library gives us a class to do this:
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);
}
}
then, in your Service, make sure to release the 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);
}
Don't forget to add the WAKE_LOCK permission:
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />
<uses-permission android:name="android.permission.WAKE_LOCK" />
I have found a way to make your application run well when the device reboots, please follow the steps below to be successful.
AndroidManifest file
<?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>
</manifest>
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);
}
}
This is asking permission to not need to manage battery saving for this app so you can run in the background stably.
Declare this code in onCreate () of MainActivity class:
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);
Looks very similar to mine but I use the full package name for the receiver:
<receiver android:name=".StartupIntentReceiver">
I have:
<receiver android:name="com.your.package.AutoStart">
I've had success without the full package, do you know where the call chain is getting interrupted? If you debug with Log()'s, at what point does it no longer work?
I think it may be in your IntentService, this all looks fine.
Just to make searching easier, as mentioned in comments, this is not possible since 3.1
https://stackoverflow.com/a/19856367/6505257

Categories

Resources