0

I have an application that I would like to have automatically start following boot completion. The following code seems overly complicated and I get erratic application starts when swiping to a neighbouring workspace.

What am I missing here? I have an activity class, a service class, as well as a broadcast receiver. Below is my code (in that order) followed by the manifest.

public class BlueDoor extends Activity implements OnClickListener{  
Button btnExit;

@Override
public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);     

    requestWindowFeature(Window.FEATURE_NO_TITLE);
    getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN,
            WindowManager.LayoutParams.FLAG_FULLSCREEN);
    setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);
    setContentView(R.layout.main);

    btnExit = (Button) this.findViewById(R.id.ExitButton);  
    btnExit.setOnClickListener(this);
}   

@Override
public void onClick(View v) {
    switch (v.getId()) {
    case R.id.ExitButton:
        System.exit(0);
        break;
    }
 }
}

service.class

 public class BlueDoorStartService extends Service {
 @Override
 public IBinder onBind(Intent intent) {
  return null;
 }

 @Override
 public void onCreate() {
  super.onCreate();
  Toast.makeText(this, "Service Started", Toast.LENGTH_LONG).show();

  Intent callIntent = new Intent(Intent.ACTION_CALL); 
  callIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK); 
  callIntent.setClass(this, BlueDoor.class);
  startActivity(callIntent); 
  // do something when the service is created
 }
}

broadcast receiver

public class StartBlueDoorAtBootReceiver extends BroadcastReceiver {
@Override
public void onReceive(Context context, Intent intent) {

    if (Intent.ACTION_BOOT_COMPLETED.equals(intent.getAction())) {
        Intent serviceIntent = new Intent(context, BlueDoorStartService.class);
        context.startService(serviceIntent);
    }
 }
}

Manifest.xml

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.bluedoor"
android:versionCode="1"
android:versionName="1.0" >
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />
<uses-sdk
    android:minSdkVersion="8"
    android:targetSdkVersion="21" />
<application
    android:allowBackup="true"
    android:icon="@drawable/ic_launcher"
    android:label="@string/app_name"
    android:theme="@style/AppTheme" >

    <receiver 
    android:name=".StartBlueDoorAtBootReceiver"
    android:enabled="true"
    android:exported="false" >
    <intent-filter>
     <action android:name="android.intent.action.BOOT_COMPLETED" />
</intent-filter>
</receiver>

    <service android:name=".BlueDoorStartService" >
    </service>

    <activity
        android:name=".BlueDoor"
        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>

UPDATE Solution(s), 10/22/2015:

Changing the service to:

public class BlueDoorStartService extends Service {
@Override
public IBinder onBind(Intent intent) {
    throw new UnsupportedOperationException("Not yet implemented");   
}
@Override
public void onCreate() {
    super.onCreate();
}
@Override
    public void onDestroy() {
       super.onDestroy();
    }
    @Override
    public int onStartCommand(Intent intent, int flags, int startId) {      
    return super.onStartCommand(intent, flags, startId);
    }
}

and the receiver to:

public class StartBlueDoorAtBootReceiver extends BroadcastReceiver {
@Override
public void onReceive(Context context, Intent intent) {
        // Start Service On Boot Start Up
        Intent serviceIntent = new Intent(context, BlueDoorStartService.class);
        context.startService(serviceIntent);
        //Start App On Boot Start Up
        Intent App = new Intent(context, BlueDoor.class);
        App.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
        context.startActivity(App);
   }
}

resulted in a working configuration using a service w/no misbehaving. However deleting the service all together and modifying the receiver thus:

public class StartBlueDoorAtBootReceiver extends BroadcastReceiver {
@Override
public void onReceive(Context context, Intent intent) {
        Intent App = new Intent(context, BlueDoor.class);
        App.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
        context.startActivity(App);
}
}

also resulted in a functional as well as a more concise configuration that starts the application following boot completion.

portsample
  • 1,986
  • 4
  • 19
  • 35

1 Answers1

0

Your BroadcastReceiver calls

context.startService(serviceIntent)

so the service will be created if it doesn't exist yet (which will be the case shortly after booting) and thus start the activity from its onCreate() method. So the app works, to a certain extent.

BUT when you call startService(), the system always calls the service's onStartCommand() method. You did not override that method, so the system uses the standard implementation from class android.app.Service.

As you can read on grepcode.com, the method will return a value like START_STICKY by default. This tells the system to keep the service alive until it is explicitly stopped.

In your case, I suppose the system reacted to the swiping by temporarily killing and then reanimating (= creating) the service, which in turn started your activity.

Some information on the service lifecycle can be found here.

What you can do: Override onStartCommand() to start the activity from there instead of from onCreate(). Then use stopSelf(int) like described here

One last thing: when exiting from the activity, don't use System.exit(0) but call finish() instead, see this SO answer for "why".

Community
  • 1
  • 1
Bö macht Blau
  • 12,820
  • 5
  • 40
  • 61