今天要讨论的是:在Android手机上如何根据用户的设置来决定是否在开机时启动应用程序。这句话不知道怎么说才能通顺,就先详细说一下要解决的问题吧。

我们都知道要让应用程序在开机时启动,首先是在manifest中添加权限,注册receiver,给receiver添加action,然后在receiver的onReceive方法中启动一个service或者activity。

如果某个应用程序想让用户决定是不是在开机时启动,用户选择是,这个应用程序就接收boot completed 广播,用户选择否,这个程序就不接收boot completed广播。可是由于receiver是注册在manifest文件中,怎样让它在手机启动时不响应boot completed广播了。

有人说在onReceive方法中检查SharedPreferences,这是不对的,即使它执行完onReceive后就结束了,但它毕竟是启动了。

解决的方法是使用PackageManager,然后调用它的setComponentEnabledSetting方法,这个方法可以让一个组件失效或者生效,如果让这个receiver失效了,他就接收不到广播了,当然让它生效了,就能接收到广播了。

 

 

先贴代码片段

首先是权限

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

接着注册receiver

<receiver android:name=".MyReceiver">
             <intent-filter>
                 <action android:name="android.intent.action.BOOT_COMPLETED"></action>
             </intent-filter>
         </receiver>

然后是onReceiver方法,我选择启动一个Activity测试

public class MyReceiver extends BroadcastReceiver {
     
     @Override
     public void onReceive(Context context, Intent intent) {
         if (intent.getAction().equals(Intent.ACTION_BOOT_COMPLETED)) {
             Toast.makeText(context, "receive boot completed", Toast.LENGTH_LONG).show();
             Intent start = new Intent(context, DisableReceiverInCodeActivity.class);
             start.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
             context.startActivity(start);
         }
     }

主界面是DisableReceiverInCodeActivity,布局文件中有个checkbox,当checkbox选中,就在开机时启动这个程序,否则不启动。

<?xml version="1.0" encoding="utf-8"?>
 <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
     android:layout_width="fill_parent"
     android:layout_height="fill_parent"
     android:orientation="vertical" >    <LinearLayout
         android:layout_width="fill_parent"
         android:layout_height="wrap_content"
         android:orientation="horizontal" >
         <TextView
             android:layout_width="wrap_content"
             android:layout_height="wrap_content" 
             android:text="start on boot complete">
         </TextView>
         <CheckBox android:layout_width="wrap_content"
             android:layout_height="wrap_content"
             android:id="@+id/boot_complete_checkbox"/>
     </LinearLayout>
     
 </LinearLayout>

然后是checkbox的事件和处理

public class DisableReceiverInCodeActivity extends Activity {
     /** Called when the activity is first created. */
     @Override
     public void onCreate(Bundle savedInstanceState) {
         super.onCreate(savedInstanceState);
         setContentView(R.layout.main);        final CheckBox bootCheck = (CheckBox) findViewById(R.id.boot_complete_checkbox);
         final ComponentName cm = new ComponentName("com.rsft.test.demo1", "com.rsft.test.demo1.MyReceiver");
         final PackageManager pm = getPackageManager();
         int state = pm.getComponentEnabledSetting(cm);
         if (state != PackageManager.COMPONENT_ENABLED_STATE_DISABLED
                 && state != PackageManager.COMPONENT_ENABLED_STATE_DISABLED_USER) {
             bootCheck.setChecked(true);
         }
         bootCheck
                 .setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {                    @Override
                     public void onCheckedChanged(CompoundButton buttonView,
                             boolean isChecked) {
                         int newState = bootCheck.isChecked() ? PackageManager.COMPONENT_ENABLED_STATE_ENABLED
                                 : PackageManager.COMPONENT_ENABLED_STATE_DISABLED;
                         pm.setComponentEnabledSetting(cm, newState,
                                 PackageManager.DONT_KILL_APP);
                     }
                 });
     }
 }

然后就结束了,简单说一下ComponentName cm = new ComponentName("com.rsft.test.demo1", "com.rsft.test.demo1.MyReceiver") 这个东西前面是程序的包名,后面是组件的类名,我的是一个receiver,注意类名一定得是全名,就是包名+类名的方式。

再说一下pm.setComponentEnabledSetting(cm, newState,
                                PackageManager.DONT_KILL_APP); 这个就是让一个组件失效或者生效的方法,第一个参数是组件,第二个是你要设置的状态,查查文档就知道有哪些状态,第三个参数可设置的值只有两个,具体看看文档。


谢谢阅读

若水飞天