在引导完成时启动 Android 应用程序:我的解决方案是否过于复杂?
Starting Android application at boot completion: is my solution overly complicated?
我有一个应用程序,我希望它在引导完成后自动启动。下面的代码似乎过于复杂,当我滑动到相邻的工作区时,应用程序启动不稳定。
我在这里错过了什么?我有一个 activity class、一个服务 class,以及一个广播接收器。下面是我的代码(按顺序),然后是清单。
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
}
}
广播接收器
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>
更新解决方案,2015 年 10 月 22 日:
将服务更改为:
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);
}
}
接收方:
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);
}
}
导致使用服务 w/no 行为不当的工作配置。 但是 一起删除服务并修改接收器:
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);
}
}
还产生了在启动完成后启动应用程序的功能和更简洁的配置。
您的 BroadcastReceiver 调用
context.startService(serviceIntent)
因此,如果服务尚不存在(启动后不久就会出现这种情况),则会创建该服务,从而从其 onCreate()
方法启动 activity。所以该应用程序在一定程度上可以正常工作。
但是当您调用 startService()
时,系统总是调用服务的 onStartCommand()
方法。您没有覆盖该方法,因此系统使用 class android.app.Service
中的标准实现。
正如您在 grepcode.com 上看到的那样,该方法将 return 默认情况下类似于 START_STICKY
的值。这告诉系统保持服务活动,直到它被明确停止。
在你的情况下,我想系统通过暂时终止然后重新激活(=创建)服务来响应滑动,这反过来又启动了你的activity。
可以找到有关服务生命周期的一些信息here。
你能做什么:
覆盖 onStartCommand()
以从那里而不是从 onCreate()
开始 activity。然后像 here
中描述的那样使用 stopSelf(int)
最后一件事:当退出 activity 时,不要使用 System.exit(0)
而是调用 finish()
,请参阅 "why" 的 SO 答案。
我有一个应用程序,我希望它在引导完成后自动启动。下面的代码似乎过于复杂,当我滑动到相邻的工作区时,应用程序启动不稳定。
我在这里错过了什么?我有一个 activity class、一个服务 class,以及一个广播接收器。下面是我的代码(按顺序),然后是清单。
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
}
}
广播接收器
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>
更新解决方案,2015 年 10 月 22 日:
将服务更改为:
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);
}
}
接收方:
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);
}
}
导致使用服务 w/no 行为不当的工作配置。 但是 一起删除服务并修改接收器:
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);
}
}
还产生了在启动完成后启动应用程序的功能和更简洁的配置。
您的 BroadcastReceiver 调用
context.startService(serviceIntent)
因此,如果服务尚不存在(启动后不久就会出现这种情况),则会创建该服务,从而从其 onCreate()
方法启动 activity。所以该应用程序在一定程度上可以正常工作。
但是当您调用 startService()
时,系统总是调用服务的 onStartCommand()
方法。您没有覆盖该方法,因此系统使用 class android.app.Service
中的标准实现。
正如您在 grepcode.com 上看到的那样,该方法将 return 默认情况下类似于 START_STICKY
的值。这告诉系统保持服务活动,直到它被明确停止。
在你的情况下,我想系统通过暂时终止然后重新激活(=创建)服务来响应滑动,这反过来又启动了你的activity。
可以找到有关服务生命周期的一些信息here。
你能做什么:
覆盖 onStartCommand()
以从那里而不是从 onCreate()
开始 activity。然后像 here
stopSelf(int)
最后一件事:当退出 activity 时,不要使用 System.exit(0)
而是调用 finish()
,请参阅 "why" 的 SO 答案。