在Android源码中,提供的快捷开关相对是比较少的,Android4.0系统默认提供的桌面快捷开关AppWidget上只有5种开关(分别是Wifi开关、蓝牙开关、GPS开关、同步开关、亮度设置开关)如下图所示:
当然,有时候就需要开发实现承载更多的快捷开关的AppWidget来实现用户体验,所以,本文主要针对这些开关的主要代码实现来重点解决开发这些快捷开关。
本文涉及到的快捷开关代码实现有Wifi、蓝牙、GPS、同步、亮度设置、飞行模式、移动数据流量(实现开启和关闭移动网络)、静音模式、重启、关机、锁屏、屏幕旋转等。需要注意的是:实现这些开关控制时都需要在AndroidManifest.xml文件中添加相应的权限。
一般这些开关在被设置改变时,系统会向外界发送相应的广播。所以,当用代码实现操作这些开关时,我们可以通过动态注册广播接收器,来接收这些系统发送的状态改变广播,以此来验证我们是否正常设置改变了这些开关。
当然,在本文以下的一些实例代码中,开关按钮也随着状态的改变而显示不同的文字,动态注册广播接收会显得有点多余,不过这只是证明系统会发送相应的广播,还应用开发还是有用处的,至少我们可以在不同的进程中监听接收这些广播。
1. Wifi开关:
1). Wifi开关由WifiManager这个类控制实现。
2). 当Wifi开关改变时,系统会向外界发送广播.wifi.WIFI_STATE_CHANGED;
示列代码如下:
[java]view plaincopypackagecom.example.wst; importandroid.app.Activity; importandroid.content.BroadcastReceiver; importandroid.content.Context; importandroid.content.Intent; importandroid.content.IntentFilter; .wifi.WifiManager; importandroid.os.Bundle; importandroid.view.View; importandroid.view.View.OnClickListener; importandroid.widget.Button; importandroid.widget.Toast; publicclassWifiSwitchTestextendsActivityimplementsOnClickListener { privateWifiManagermWifiManager; privateButtonmWifiButton; //Wifi设置改变系统发送的广播 publicstaticfinalStringWIFI_STATE_CHANGED=".wifi.WIFI_STATE_CHANGED"; privateTestChangemTestChange; privateIntentFiltermIntentFilter; /**Calledwhentheactivityisfirstcreated.*/ @Override publicvoidonCreate(BundlesavedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.main); mWifiManager=(WifiManager)getSystemService(Context.WIFI_SERVICE); mTestChange=newTestChange(); mIntentFilter=newIntentFilter(); //添加广播接收器过滤的广播 mIntentFilter.addAction(".wifi.WIFI_STATE_CHANGED"); mWifiButton=(Button)findViewById(R.id.wifi); refreshButton(); mWifiButton.setOnClickListener(this); } @Override protectedvoidonDestroy() { //TODOAuto-generatedmethodstub super.onDestroy(); //解除广播接收器 unregisterReceiver(mTestChange); } @Override protectedvoidonResume() { //TODOAuto-generatedmethodstub super.onResume(); //注册广播接收器 registerReceiver(mTestChange,mIntentFilter); } //更新按钮 privatevoidrefreshButton() { mWifiButton.setText(mWifiManager.isWifiEnabled()?R.string.wifi_off:R.string.wifi_on); } @Override publicvoidonClick(Viewv) { //TODOAuto-generatedmethodstub if(mWifiManager.isWifiEnabled()) { //关闭Wifi,按钮显示开启 mWifiManager.setWifiEnabled(false); } else { //开启Wifi,按钮显示关闭 mWifiManager.setWifiEnabled(true); } } privateclassTestChangeextendsBroadcastReceiver { @Override publicvoidonReceive(Contextcontext,Intentintent) { //TODOAuto-generatedmethodstub Stringaction=intent.getAction(); if(WIFI_STATE_CHANGED.equals(action)) { refreshButton(); Toast.makeText(WifiSwitchTest.this,"Wifi设置有改变", Toast.LENGTH_SHORT).show(); } } } }
权限添加:
[html]view plaincopy<uses-permissionandroid:name="android.permission.ACCESS_WIFI_STATE"/> <uses-permissionandroid:name="android.permission.CHANGE_WIFI_STATE"/>
2. 蓝牙开关:
1). 蓝牙开关主要调用BluetoothAdapter相关方法实现
2). 蓝牙有四种状态:正在打开、打开、正在关闭、关闭
3). 蓝牙状态改变,系统向外界发送广播android.bluetooth.adapter.action.STATE_CHANGED或android.bluetooth.a2dp.profile.action.CONNECTION_STATE_CHANGED;
示例代码如下:
[java]view plaincopypackagecom.example.bts; importandroid.app.Activity; importandroid.bluetooth.BluetoothAdapter; importandroid.content.BroadcastReceiver; importandroid.content.Context; importandroid.content.Intent; importandroid.content.IntentFilter; importandroid.os.Bundle; importandroid.view.View; importandroid.view.View.OnClickListener; importandroid.widget.Button; importandroid.widget.Toast; publicclassBluetoothSwitchextendsActivityimplementsOnClickListener { privateButtonmBluetooth; privateBluetoothAdaptermBluetoothAdapter; privateTestChangemTestChange; privateIntentFiltermIntentFilter; publicstaticfinalStringBLUETOOTH_STATE_CHANGED="android.bluetooth.adapter.action.STATE_CHANGED"; privatestaticfinalStringBLUETOOTH_ACTION="android.bluetooth.a2dp.profile.action.CONNECTION_STATE_CHANGED"; /**Calledwhentheactivityisfirstcreated.*/ @Override publicvoidonCreate(BundlesavedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.main); mBluetoothAdapter=BluetoothAdapter.getDefaultAdapter(); mTestChange=newTestChange(); mIntentFilter=newIntentFilter(); //添加广播接收器过滤的广播 mIntentFilter.addAction("android.bluetooth.adapter.action.STATE_CHANGED"); mIntentFilter.addAction("android.bluetooth.a2dp.profile.action.CONNECTION_STATE_CHANGED"); mBluetooth=(Button)findViewById(R.id.blue); refreshButton(); mBluetooth.setOnClickListener(this); } @Override protectedvoidonDestroy() { //TODOAuto-generatedmethodstub super.onDestroy(); //解除广播接收器 unregisterReceiver(mTestChange); } @Override protectedvoidonResume() { //TODOAuto-generatedmethodstub super.onResume(); //注册广播接收器 registerReceiver(mTestChange,mIntentFilter); } //更新按钮状态 privatevoidrefreshButton() { switch(getBluetoothStatus()) { caseBluetoothAdapter.STATE_ON: mBluetooth.setText(R.string.off); break; caseBluetoothAdapter.STATE_TURNING_ON: mBluetooth.setText(R.string.oning); break; caseBluetoothAdapter.STATE_OFF: mBluetooth.setText(R.string.on); break; caseBluetoothAdapter.STATE_TURNING_OFF: mBluetooth.setText(R.string.offing); break; } } //获取蓝牙当前状态 privateintgetBluetoothStatus() { returnmBluetoothAdapter.getState(); } //设置蓝牙开关 privatevoidsetBluetoothStatus() { switch(getBluetoothStatus()) { caseBluetoothAdapter.STATE_ON: mBluetoothAdapter.disable(); break; caseBluetoothAdapter.STATE_TURNING_ON: mBluetoothAdapter.disable(); break; caseBluetoothAdapter.STATE_OFF: mBluetoothAdapter.enable(); break; caseBluetoothAdapter.STATE_TURNING_OFF: mBluetoothAdapter.enable(); break; } } @Override publicvoidonClick(Viewv) { //TODOAuto-generatedmethodstub setBluetoothStatus(); } privateclassTestChangeextendsBroadcastReceiver { @Override publicvoidonReceive(Contextcontext,Intentintent) { //TODOAuto-generatedmethodstub Stringaction=intent.getAction(); if(BLUETOOTH_STATE_CHANGED.equals(action)||BLUETOOTH_ACTION.equals(action)) { Toast.makeText(BluetoothSwitch.this,"蓝牙模式设置有改变", Toast.LENGTH_SHORT).show(); //动态刷新按钮 refreshButton(); } } } }
权限添加:
[html]view plaincopy<uses-permissionandroid:name="android.permission.BLUETOOTH"/> <uses-permissionandroid:name="android.permission.BLUETOOTH_ADMIN"/>
3. 屏幕旋转开关:
1). 屏幕旋转开关设置主要调用android.provider.Settings.System的putInt和getInt方法实现。
2). 通过ContentObserver来动态观察屏幕旋转设置的改变。
示例代码如下:
[java]view plaincopypackagecom.example.srs; importandroid.app.Activity; importandroid.content.ContentResolver; importandroid.content.Context; importandroid.database.ContentObserver; .Uri; importandroid.os.Bundle; importandroid.os.Handler; importandroid.provider.Settings; importandroid.provider.Settings.SettingNotFoundException; importandroid.util.Log; importandroid.view.View; importandroid.view.View.OnClickListener; importandroid.widget.Button; importandroid.widget.Toast; publicclassScreenRotationSwitchextendsActivityimplementsOnClickListener { privateButtonmRotationButton; privateRotationObservermRotationObserver; /**Calledwhentheactivityisfirstcreated.*/ @Override publicvoidonCreate(BundlesavedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.main); //创建观察类对象 mRotationObserver=newRotationObserver(newHandler()); mRotationButton=(Button)findViewById(R.id.rotation); refreshButton(); mRotationButton.setOnClickListener(this); } @Override protectedvoidonDestroy(){ //TODOAuto-generatedmethodstub super.onDestroy(); //解除观察变化 mRotationObserver.stopObserver(); } @Override protectedvoidonResume(){ //TODOAuto-generatedmethodstub super.onResume(); //注册观察变化 mRotationObserver.startObserver(); } //更新按钮状态 privatevoidrefreshButton() { if(getRotationStatus(this)==1) { mRotationButton.setText(R.string.rotation_off); } else { mRotationButton.setText(R.string.rotation_on); } } //得到屏幕旋转的状态 privateintgetRotationStatus(Contextcontext) { intstatus=0; try { status=android.provider.Settings.System.getInt(context.getContentResolver(), android.provider.Settings.System.ACCELEROMETER_ROTATION); } catch(SettingNotFoundExceptione) { //TODOAuto-generatedcatchblock e.printStackTrace(); } returnstatus; } privatevoidsetRotationStatus(ContentResolverresolver,intstatus) { //得到uri Uriuri=android.provider.Settings.System.getUriFor("accelerometer_rotation"); //沟通设置status的值改变屏幕旋转设置 android.provider.Settings.System.putInt(resolver,"accelerometer_rotation",status); //通知改变 resolver.notifyChange(uri,null); } @Override publicvoidonClick(Viewv) { //TODOAuto-generatedmethodstub if(getRotationStatus(this)==1) { setRotationStatus(getContentResolver(),0); } else { setRotationStatus(getContentResolver(),1); } } //观察屏幕旋转设置变化,类似于注册动态广播监听变化机制 privateclassRotationObserverextendsContentObserver { ContentResolvermResolver; publicRotationObserver(Handlerhandler) { super(handler); mResolver=getContentResolver(); //TODOAuto-generatedconstructorstub } //屏幕旋转设置改变时调用 @Override publicvoidonChange(booleanselfChange) { //TODOAuto-generatedmethodstub super.onChange(selfChange); //更新按钮状态 refreshButton(); Toast.makeText(ScreenRotationSwitch.this,"旋转屏幕设置有变化", Toast.LENGTH_SHORT).show(); } publicvoidstartObserver() { mResolver.registerContentObserver(Settings.System .getUriFor(Settings.System.ACCELEROMETER_ROTATION),false, this); } publicvoidstopObserver() { mResolver.unregisterContentObserver(this); } } }
权限添加:
[html]view plaincopy<uses-permissionandroid:name="android.permission.WRITE_SETTINGS"/>
4. 同步开关:
1). 同步开关设置主要由ContentResolver类(抽象类)的静态函数来实现;
2). 当同步模式改变时,系统会向外界发送广播com.android.sync.SYNC_CONN_STATUS_CHANGED;
示例代码如下:
[java]view plaincopypackagecom.example.sst; importandroid.app.Activity; importandroid.content.BroadcastReceiver; importandroid.content.ContentResolver; importandroid.content.Context; importandroid.content.Intent; importandroid.content.IntentFilter; .ConnectivityManager; importandroid.os.Bundle; importandroid.view.View; importandroid.view.View.OnClickListener; importandroid.widget.Button; importandroid.widget.Toast; publicclassSyncSwitchTestextendsActivityimplementsOnClickListener { privateButtonmSyncButton; privateTestChangemTestChange; privateIntentFiltermIntentFilter; //同步模式改变系统发送的广播 privatestaticfinalStringSYNC_CONN_STATUS_CHANGED="com.android.sync.SYNC_CONN_STATUS_CHANGED"; /**Calledwhentheactivityisfirstcreated.*/ @Override publicvoidonCreate(BundlesavedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.main); mTestChange=newTestChange(); mIntentFilter=newIntentFilter(); //添加广播接收器过滤的广播 mIntentFilter.addAction("com.android.sync.SYNC_CONN_STATUS_CHANGED"); mSyncButton=(Button)findViewById(R.id.sync); refreshButton(); mSyncButton.setOnClickListener(this); } @Override protectedvoidonDestroy() { //TODOAuto-generatedmethodstub super.onDestroy(); //解除广播接收器 unregisterReceiver(mTestChange); } @Override protectedvoidonResume(){ //TODOAuto-generatedmethodstub super.onResume(); //注册广播接收器 registerReceiver(mTestChange,mIntentFilter); } //更新按钮状态 privatevoidrefreshButton() { mSyncButton.setText(getSyncStatus(this)?R.string.sync_off:R.string.sync_on); } privatebooleangetSyncStatus(Contextcontext) { ConnectivityManagerconnManager=(ConnectivityManager)context.getSystemService(Context.CONNECTIVITY_SERVICE); returnconnManager.getBackgroundDataSetting()&&ContentResolver.getMasterSyncAutomatically(); } privatevoidsetSyncStatus(booleanenbled) { /*getMasterSyncAutomatically和setMasterSyncAutomatically为抽象类ContentResolver的静态函数, *所以可以直接通过类来调用 */ ContentResolver.setMasterSyncAutomatically(enbled); } @Override publicvoidonClick(Viewv) { //TODOAuto-generatedmethodstub if(getSyncStatus(this)) { setSyncStatus(false); } else { setSyncStatus(true); } } privateclassTestChangeextendsBroadcastReceiver { @Override publicvoidonReceive(Contextcontext,Intentintent) { //TODOAuto-generatedmethodstub Stringaction=intent.getAction(); if(SYNC_CONN_STATUS_CHANGED.equals(action)) { refreshButton(); Toast.makeText(SyncSwitchTest.this,"同步模式设置有改变",Toast.LENGTH_SHORT).show(); } } } }
权限添加:
[html]view plaincopy<uses-permissionandroid:name="android.permission.READ_SYNC_STATS"/> <uses-permissionandroid:name="android.permission.READ_SYNC_SETTINGS"/> <uses-permissionandroid:name="android.permission.WRITE_SYNC_SETTINGS"/>
5. 亮度设置开关:
1). 亮度设置的主要调用Settings.System的putInt和getInt方法来处理,已经调用PowerManager的setBacklightBrightness方法来实现调节手机亮度。
2).PowerManager的setBacklightBrightness的方法是隐藏的,通过反射来调用实现。
3).通过ContentObserver来动态观察亮度设置的改变。
示例代码如下:
[java]view plaincopypackagecom.example.bs; importjava.lang.reflect.Field; importjava.lang.reflect.InvocationTargetException; importjava.lang.reflect.Method; importandroid.app.Activity; importandroid.content.ContentResolver; importandroid.content.Context; importandroid.database.ContentObserver; importandroid.os.Bundle; importandroid.os.Handler; importandroid.os.PowerManager; importandroid.provider.Settings; importandroid.provider.Settings.SettingNotFoundException; importandroid.view.View; importandroid.view.View.OnClickListener; importandroid.widget.Button; importandroid.widget.Toast; publicclassBrightnessSwitchextendsActivityimplementsOnClickListener { privateButtonmBrightness; privatestaticfinalintLIGHT_NORMAL=64; privatestaticfinalintLIGHT_50_PERCENT=127; privatestaticfinalintLIGHT_75_PERCENT=191; privatestaticfinalintLIGHT_100_PERCENT=255; privatestaticfinalintLIGHT_AUTO=0; privatestaticfinalintLIGHT_ERR=-1; privateBrightObservermBrightObserver; privatePowerManagermPowerManager; /**Calledwhentheactivityisfirstcreated.*/ @Override publicvoidonCreate(BundlesavedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.main); mPowerManager=(PowerManager)getSystemService(Context.POWER_SERVICE); mBrightObserver=newBrightObserver(newHandler()); mBrightness=(Button)findViewById(R.id.bright); refreshButton(); mBrightness.setOnClickListener(this); } @Override protectedvoidonDestroy() { //TODOAuto-generatedmethodstub super.onDestroy(); mBrightObserver.stopObserver(); } @Override protectedvoidonResume() { //TODOAuto-generatedmethodstub super.onResume(); mBrightObserver.startObserver(); } //更新按钮 privatevoidrefreshButton() { switch(getBrightStatus()) { caseLIGHT_NORMAL: mBrightness.setText(R.string.light_50percent); break; caseLIGHT_50_PERCENT: mBrightness.setText(R.string.light_75percent); break; caseLIGHT_75_PERCENT: mBrightness.setText(R.string.light_100percent); break; caseLIGHT_100_PERCENT: mBrightness.setText(R.string.light_auto); break; caseLIGHT_AUTO: mBrightness.setText(R.string.light_normal); break; caseLIGHT_ERR: mBrightness.setText(R.string.light_err); break; } } //得到当前亮度值状态 privateintgetBrightStatus() { //TODOAuto-generatedmethodstub intlight=0; booleanauto=false; ContentResolvercr=getContentResolver(); try { auto=Settings.System.getInt(cr, Settings.System.SCREEN_BRIGHTNESS_MODE)==Settings.System.SCREEN_BRIGHTNESS_MODE_AUTOMATIC; if(!auto) { light=android.provider.Settings.System.getInt(cr, Settings.System.SCREEN_BRIGHTNESS,-1); if(light>0&&light<=LIGHT_NORMAL) { returnLIGHT_NORMAL; } elseif(light>LIGHT_NORMAL&&light<=LIGHT_50_PERCENT) { returnLIGHT_50_PERCENT; } elseif(light>LIGHT_50_PERCENT&&light<=LIGHT_75_PERCENT) { returnLIGHT_75_PERCENT; } elseif(light>LIGHT_75_PERCENT&&light<=LIGHT_100_PERCENT) { returnLIGHT_100_PERCENT; } } else { returnLIGHT_AUTO; } } catch(SettingNotFoundExceptione1) { //TODOAuto-generatedcatchblock e1.printStackTrace(); } returnLIGHT_ERR; } privatevoidsetBrightStatus() { intlight=0; switch(getBrightStatus()) { caseLIGHT_NORMAL: light=LIGHT_50_PERCENT-1; break; caseLIGHT_50_PERCENT: light=LIGHT_75_PERCENT-1; break; caseLIGHT_75_PERCENT: light=LIGHT_100_PERCENT-1; break; caseLIGHT_100_PERCENT: startAutoBrightness(getContentResolver()); break; caseLIGHT_AUTO: light=LIGHT_NORMAL-1; stopAutoBrightness(getContentResolver()); break; caseLIGHT_ERR: light=LIGHT_NORMAL-1; break; } setLight(light); setScreenLightValue(getContentResolver(),light); } /*因为PowerManager提供的函数setBacklightBrightness接口是隐藏的, *所以在基于第三方开发调用该函数时,只能通过反射实现在运行时调用 */ privatevoidsetLight(intlight) { try { //得到PowerManager类对应的Class对象 Class<?>pmClass=Class.forName(mPowerManager.getClass().getName()); //得到PowerManager类中的成员mService(mService为PowerManagerService类型) Fieldfield=pmClass.getDeclaredField("mService"); field.setAccessible(true); //实例化mService ObjectiPM=field.get(mPowerManager); //得到PowerManagerService对应的Class对象 Class<?>iPMClass=Class.forName(iPM.getClass().getName()); /*得到PowerManagerService的函数setBacklightBrightness对应的Method对象, *PowerManager的函数setBacklightBrightness实现在PowerManagerService中 */ Methodmethod=iPMClass.getDeclaredMethod("setBacklightBrightness",int.class); method.setAccessible(true); //调用实现PowerManagerService的setBacklightBrightness method.invoke(iPM,light); } catch(ClassNotFoundExceptione) { //TODOAuto-generatedcatchblock e.printStackTrace(); } catch(NoSuchFieldExceptione) { //TODOAuto-generatedcatchblock e.printStackTrace(); } catch(IllegalArgumentExceptione) { //TODOAuto-generatedcatchblock e.printStackTrace(); } catch(IllegalAccessExceptione) { //TODOAuto-generatedcatchblock e.printStackTrace(); } catch(NoSuchMethodExceptione) { //TODOAuto-generatedcatchblock e.printStackTrace(); } catch(InvocationTargetExceptione) { //TODOAuto-generatedcatchblock e.printStackTrace(); } } @Override publicvoidonClick(Viewv) { //TODOAuto-generatedmethodstub setBrightStatus(); } //启动自动调节亮度 publicvoidstartAutoBrightness(ContentResolvercr) { Settings.System.putInt(cr,Settings.System.SCREEN_BRIGHTNESS_MODE, Settings.System.SCREEN_BRIGHTNESS_MODE_AUTOMATIC); } //关闭自动调节亮度 publicvoidstopAutoBrightness(ContentResolvercr) { Settings.System.putInt(cr,Settings.System.SCREEN_BRIGHTNESS_MODE, Settings.System.SCREEN_BRIGHTNESS_MODE_MANUAL); } //设置改变亮度值 publicvoidsetScreenLightValue(ContentResolverresolver,intvalue) { android.provider.Settings.System.putInt(resolver,Settings.System.SCREEN_BRIGHTNESS, value); } privateclassBrightObserverextendsContentObserver { ContentResolvermResolver; publicBrightObserver(Handlerhandler) { super(handler); mResolver=getContentResolver(); } @Override publicvoidonChange(booleanselfChange) { //TODOAuto-generatedmethodstub super.onChange(selfChange); refreshButton(); Toast.makeText(BrightnessSwitch.this,"亮度设置有改变",Toast.LENGTH_SHORT).show(); } //注册观察 publicvoidstartObserver() { mResolver.registerContentObserver(Settings.System .getUriFor(Settings.System.SCREEN_BRIGHTNESS),false, this); mResolver.registerContentObserver(Settings.System .getUriFor(Settings.System.SCREEN_BRIGHTNESS_MODE),false, this); } //解除观察 publicvoidstopObserver() { mResolver.unregisterContentObserver(this); } } }
权限添加:
[html]view plaincopy<uses-permissionandroid:name="android.permission.WRITE_SETTINGS"/> <uses-permissionandroid:name="android.permission.DEVICE_POWER"/>
6. 飞行模式开关:
1). 飞行模式主要是调用Settings.System的getInt和setInt方法来处理。
2). 当飞行模式改变时,系统会向外界发送广播android.intent.action.AIRPLANE_MODE;
示例代码如下:
[java]view plaincopypackagecom.example.apmst; importandroid.app.Activity; importandroid.content.BroadcastReceiver; importandroid.content.Context; importandroid.content.Intent; importandroid.content.IntentFilter; importandroid.os.Bundle; importandroid.provider.Settings; importandroid.view.View; importandroid.view.View.OnClickListener; importandroid.widget.Button; importandroid.widget.Toast; publicclassAirplaneModeSwitchTestextendsActivityimplementsOnClickListener { privateButtonmAirplane; //飞行模式设置改变系统发送的广播 privatestaticfinalStringAIRPLANE_MODE="android.intent.action.AIRPLANE_MODE"; privateTestChangemTestChange; privateIntentFiltermIntentFilter; /**Calledwhentheactivityisfirstcreated.*/ @Override publicvoidonCreate(BundlesavedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.main); mTestChange=newTestChange(); mIntentFilter=newIntentFilter(); //添加广播接收器过滤的广播 mIntentFilter.addAction("android.intent.action.AIRPLANE_MODE"); mAirplane=(Button)findViewById(R.id.airplane); refreshButton(); mAirplane.setOnClickListener(this); } @Override protectedvoidonDestroy() { //TODOAuto-generatedmethodstub super.onDestroy(); //解除广播接收器 unregisterReceiver(mTestChange); } @Override protectedvoidonResume() { //TODOAuto-generatedmethodstub super.onResume(); //注册广播接收器 registerReceiver(mTestChange,mIntentFilter); } //更新按钮状态 privatevoidrefreshButton() { mAirplane.setText(getAirplaneModeStatus()?R.string.airplane_off:R.string.airplane_on); } //获取飞行模式关闭或开启状态 privatebooleangetAirplaneModeStatus() { booleanstatus=Settings.System.getInt(this.getContentResolver(), Settings.System.AIRPLANE_MODE_ON,0)==1?true:false; returnstatus; } //开启或关闭飞行模式 privatevoidsetAirplaneMode(Contextcontext,booleanenable) { Settings.System.putInt(context.getContentResolver(), Settings.System.AIRPLANE_MODE_ON,enable?1:0); Intentintent=newIntent(Intent.ACTION_AIRPLANE_MODE_CHANGED); intent.putExtra("state",enable); context.sendBroadcast(intent); } @Override publicvoidonClick(Viewv) { //TODOAuto-generatedmethodstub if(getAirplaneModeStatus()) { setAirplaneMode(this,false); } else { setAirplaneMode(this,true); } } privateclassTestChangeextendsBroadcastReceiver { @Override publicvoidonReceive(Contextcontext,Intentintent) { //TODOAuto-generatedmethodstub Stringaction=intent.getAction(); if(AIRPLANE_MODE.equals(action)) { refreshButton(); Toast.makeText(AirplaneModeSwitchTest.this,"飞行模式设置有改变", Toast.LENGTH_SHORT).show(); } } } }
权限添加:
[html]view plaincopy<uses-permissionandroid:name="android.permission.WRITE_SETTINGS"/>
7. 移动数据流量开关:
1). 移动数据流量由ConnectivityManager类控制实现,这个类实现设置和获取移动流量状态的方法是隐藏的,所以我们只能通过反射来实现(或者在源码下编译APK)。
2). 相关广播为android.intent.action.ANY_DATA_STATE;
示例代码如下:
[java]view plaincopypackagecom.example.mdst; importjava.lang.reflect.Field; importjava.lang.reflect.InvocationTargetException; importjava.lang.reflect.Method; importandroid.app.Activity; importandroid.content.BroadcastReceiver; importandroid.content.Context; importandroid.content.Intent; importandroid.content.IntentFilter; .ConnectivityManager; importandroid.os.Bundle; importandroid.view.View; importandroid.view.View.OnClickListener; importandroid.widget.Button; importandroid.widget.Toast; publicclassMobileDataSwitchTestextendsActivityimplementsOnClickListener { privateConnectivityManagermConnectivityManager; privateButtonmMobileDataButton; //移动数据设置改变系统发送的广播 privatestaticfinalStringNETWORK_CHANGE="android.intent.action.ANY_DATA_STATE"; privateTestChangemTestChange; privateIntentFiltermIntentFilter; /**Calledwhentheactivityisfirstcreated.*/ @Override publicvoidonCreate(BundlesavedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.main); mConnectivityManager=(ConnectivityManager)getSystemService(Context.CONNECTIVITY_SERVICE); mTestChange=newTestChange(); mIntentFilter=newIntentFilter(); //添加广播接收器过滤的广播 mIntentFilter.addAction("android.intent.action.ANY_DATA_STATE"); mMobileDataButton=(Button)findViewById(R.id.mobile_data); refreshButton(); mMobileDataButton.setOnClickListener(this); } @Override protectedvoidonDestroy() { //TODOAuto-generatedmethodstub super.onDestroy(); //解除广播接收器 unregisterReceiver(mTestChange); } @Override protectedvoidonResume() { //TODOAuto-generatedmethodstub super.onResume(); //注册广播接收器 registerReceiver(mTestChange,mIntentFilter); } privatevoidrefreshButton() { mMobileDataButton.setText(getMobileDataStatus()?R.string.mobile_data_off:R.string.mobile_data_on); } //获取移动数据开关状态 privatebooleangetMobileDataStatus() { StringmethodName="getMobileDataEnabled"; ClasscmClass=mConnectivityManager.getClass(); BooleanisOpen=null; try { Methodmethod=cmClass.getMethod(methodName,null); isOpen=(Boolean)method.invoke(mConnectivityManager,null); } catch(Exceptione) { e.printStackTrace(); } returnisOpen; } //通过反射实现开启或关闭移动数据 privatevoidsetMobileDataStatus(booleanenabled) { try { Class<?>conMgrClass=Class.forName(mConnectivityManager.getClass().getName()); //得到ConnectivityManager类的成员变量mService(ConnectivityService类型) FieldiConMgrField=conMgrClass.getDeclaredField("mService"); iConMgrField.setAccessible(true); //mService成员初始化 ObjectiConMgr=iConMgrField.get(mConnectivityManager); //得到mService对应的Class对象 Class<?>iConMgrClass=Class.forName(iConMgr.getClass().getName()); /*得到mService的setMobileDataEnabled(该方法在android源码的ConnectivityService类中实现), *该方法的参数为布尔型,所以第二个参数为Boolean.TYPE */ MethodsetMobileDataEnabledMethod=iConMgrClass.getDeclaredMethod( "setMobileDataEnabled",Boolean.TYPE); setMobileDataEnabledMethod.setAccessible(true); /*调用ConnectivityManager的setMobileDataEnabled方法(方法是隐藏的), *实际上该方法的实现是在ConnectivityService(系统服务实现类)中的 */ setMobileDataEnabledMethod.invoke(iConMgr,enabled); }catch(ClassNotFoundExceptione) { e.printStackTrace(); }catch(NoSuchFieldExceptione) { e.printStackTrace(); }catch(SecurityExceptione) { e.printStackTrace(); }catch(NoSuchMethodExceptione) { e.printStackTrace(); }catch(IllegalArgumentExceptione) { e.printStackTrace(); }catch(IllegalAccessExceptione) { e.printStackTrace(); }catch(InvocationTargetExceptione) { e.printStackTrace(); } } @Override publicvoidonClick(Viewv) { //TODOAuto-generatedmethodstub if(getMobileDataStatus()) { setMobileDataStatus(false); mMobileDataButton.setText(R.string.mobile_data_on); } else { setMobileDataStatus(true); mMobileDataButton.setText(R.string.mobile_data_off); } } privateclassTestChangeextendsBroadcastReceiver { @Override publicvoidonReceive(Contextcontext,Intentintent) { //TODOAuto-generatedmethodstub Stringaction=intent.getAction(); if(NETWORK_CHANGE.equals(action)) { Toast.makeText(MobileDataSwitchTest.this,"移动数据设置有改变", Toast.LENGTH_SHORT).show(); } } } } 权限添加:[html]view plaincopy<uses-permissionandroid:name="android.permission.ACCESS_NETWORK_STATE"/> <uses-permissionandroid:name="android.permission.CHANGE_NETWORK_STATE"/> <uses-permissionandroid:name="android.permission.WRITE_APN_SETTINGS"/>
8. 静音模式开关:
1). 静音模式由AudioManager控制实现,有三种状态:正常(有声音)、震动、静音
2).当模式改变时,系统会向外界发送广播android.media.RINGER_MODE_CHANGED;
示例代码如下:
[java]view plaincopypackagecom.example.sst; importandroid.app.Activity; importandroid.content.BroadcastReceiver; importandroid.content.Context; importandroid.content.Intent; importandroid.content.IntentFilter; importandroid.media.AudioManager; importandroid.os.Bundle; importandroid.view.View; importandroid.view.View.OnClickListener; importandroid.widget.Button; importandroid.widget.Toast; publicclassSilentSwitchTesextendsActivityimplementsOnClickListener { privateAudioManagermAudioManager; privateButtonmSilentButton; privateTestChangemTestChange; privateIntentFiltermIntentFilter; //静音模式改变系统发送的广播 publicstaticfinalStringRINGER_MODE_CHANGED="android.media.RINGER_MODE_CHANGED"; /**Calledwhentheactivityisfirstcreated.*/ @Override publicvoidonCreate(BundlesavedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.main); mAudioManager=(AudioManager)getSystemService(Context.AUDIO_SERVICE); mTestChange=newTestChange(); mIntentFilter=newIntentFilter(); //添加广播接收器过滤的广播 mIntentFilter.addAction("android.media.RINGER_MODE_CHANGED"); mSilentButton=(Button)findViewById(R.id.silent); refreshButton(); mSilentButton.setOnClickListener(this); } @Override protectedvoidonDestroy() { //TODOAuto-generatedmethodstub super.onDestroy(); //解除广播接收器 unregisterReceiver(mTestChange); } @Override protectedvoidonResume(){ //TODOAuto-generatedmethodstub super.onResume(); //注册广播接收器 registerReceiver(mTestChange,mIntentFilter); } //更新按钮 privatevoidrefreshButton() { switch(getSilentStatus()) { caseAudioManager.RINGER_MODE_SILENT: mSilentButton.setText(R.string.mode_vibrate); break; caseAudioManager.RINGER_MODE_NORMAL: mSilentButton.setText(R.string.mode_silent); break; caseAudioManager.RINGER_MODE_VIBRATE: mSilentButton.setText(R.string.mode_normal); break; } } //获取手机当前的静音模式状态 privateintgetSilentStatus() { returnmAudioManager.getRingerMode(); } //设置手机的静音、正常、震动模式 privatevoidsetSilentMode() { switch(getSilentStatus()) { caseAudioManager.RINGER_MODE_SILENT: mAudioManager.setRingerMode(AudioManager.RINGER_MODE_VIBRATE); break; caseAudioManager.RINGER_MODE_NORMAL: mAudioManager.setRingerMode(AudioManager.RINGER_MODE_SILENT); break; caseAudioManager.RINGER_MODE_VIBRATE: mAudioManager.setRingerMode(AudioManager.RINGER_MODE_NORMAL); break; } } @Override publicvoidonClick(Viewv) { //TODOAuto-generatedmethodstub setSilentMode(); } privateclassTestChangeextendsBroadcastReceiver { @Override publicvoidonReceive(Contextcontext,Intentintent) { //TODOAuto-generatedmethodstub Stringaction=intent.getAction(); if(RINGER_MODE_CHANGED.equals(action)) { refreshButton(); Toast.makeText(SilentSwitchTes.this,"静音模式设置有改变",Toast.LENGTH_SHORT).show(); } } } }
静音模式开关设置不需要添加权限。
<-----以下的开关设置实现需要有系统的UID使用Platform的apk签名,否则是没有权限调用的,会报SecurityException异常----->
注:1). 可以不通过apk签名,直接在android源码下编译生成apk,再将apk安装到手机;
2). 如果手机有root权限,那么也不需要apk签名,直接通过adb工具将apk推到system/app目录下:操作指令为adb remount---->adb push xxx.apk system/app (注:该apk将做为系统应用)
9. GPS开关:
1). GPS开关设置的实现由Secure类的相关静态方法实现。
2).Secure的isLocationProviderEnabled和setLocationProviderEnabled调用需要APK签名;
示例代码如下:
[java]view plaincopypackagecom.example.gst; importandroid.app.Activity; importandroid.content.Context; importandroid.location.LocationManager; importandroid.os.Bundle; importandroid.provider.Settings.Secure; importandroid.view.View; importandroid.view.View.OnClickListener; importandroid.widget.Button; publicclassGpsSwitchTestextendsActivityimplementsOnClickListener { privateButtonmGpsButton; /**Calledwhentheactivityisfirstcreated.*/ @Override publicvoidonCreate(BundlesavedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.main); mGpsButton=(Button)findViewById(R.id.gps); refreshButton(); mGpsButton.setOnClickListener(this); } //根据当前的Gps状态,初始化按钮的显示 privatevoidrefreshButton() { mGpsButton.setText(getGpsStatus(this)?R.string.gps_off:R.string.gps_on); } //获取Gps开启或关闭状态 privatebooleangetGpsStatus(Contextcontext) { booleanstatus=Secure.isLocationProviderEnabled(context.getContentResolver(), LocationManager.GPS_PROVIDER); returnstatus; } //打开或关闭Gps privatevoidsetGpsStatus(Contextcontext,booleanenabled) { Secure.setLocationProviderEnabled(context.getContentResolver(), LocationManager.GPS_PROVIDER,enabled); } @Override publicvoidonClick(Viewv) { //TODOAuto-generatedmethodstub if(getGpsStatus(this)) { setGpsStatus(this,false); mGpsButton.setText(R.string.gps_on); } else { setGpsStatus(this,true); mGpsButton.setText(R.string.gps_off); } } }
权限添加:
[html]view plaincopy<uses-permissionandroid:name="android.permission.ACCESS_FINE_LOCATION"/> <uses-permissionandroid:name="android.permission.WRITE_SETTINGS"/> <uses-permissionandroid:name="android.permission.WRITE_SECURE_SETTINGS"/>
10. 锁屏:
1). 手机进入锁屏主要由PowerManager的goToSleep函数实现。
2). PowerManager的goToSleep调用需要apk签名。
示例代码:
[java]view plaincopypackagecom.example.lsst; importandroid.app.Activity; importandroid.content.Context; importandroid.os.Bundle; importandroid.os.PowerManager; importandroid.os.SystemClock; importandroid.view.View; importandroid.view.View.OnClickListener; importandroid.widget.Button; publicclassLockScreenSwitchTestextendsActivityimplementsOnClickListener { privatePowerManagermPowerManager; privateButtonmLockButton; /**Calledwhentheactivityisfirstcreated.*/ @Override publicvoidonCreate(BundlesavedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.main); mPowerManager=(PowerManager)getSystemService(Context.POWER_SERVICE); mLockButton=(Button)findViewById(R.id.lock); mLockButton.setOnClickListener(this); } privatevoidlockScreen() { //强制手机进入锁屏,这时候手机会灭屏,点亮后是处于锁屏状态 mPowerManager.goToSleep(SystemClock.uptimeMillis()); } @Override publicvoidonClick(Viewv) { //TODOAuto-generatedmethodstub lockScreen(); } }
权限添加:
[html]view plaincopy<uses-permissionandroid:name="android.permission.USES_POLICY_FORCE_LOCK"/> <uses-permissionandroid:name="android.permission.DEVICE_POWER"/>
11. 重启:
1). 手机重启需要调用PowerManager的reboot方法实现,参数为null;
2). 该方法的调用,需要有系统的UID使用Platform的APK签名,否则是没有权限调用的,会报SecurityException异常。
示例代码如下:
[java]view plaincopypackagecom.example.rs; importandroid.app.Activity; importandroid.content.Context; importandroid.os.Bundle; importandroid.os.PowerManager; importandroid.view.View; importandroid.view.View.OnClickListener; importandroid.widget.Button; publicclassRebootSwitchextendsActivityimplementsOnClickListener { privateButtonmRebootButton; privatePowerManagermPowerManager; /**Calledwhentheactivityisfirstcreated.*/ @Override publicvoidonCreate(BundlesavedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.main); mPowerManager=(PowerManager)getSystemService(Context.POWER_SERVICE); mRebootButton=(Button)findViewById(R.id.reboot); mRebootButton.setOnClickListener(this); } privatevoidreboot(Stringreason) { mPowerManager.reboot(null); } @Override publicvoidonClick(Viewv) { //TODOAuto-generatedmethodstub reboot(null); } }
权限添加:
[html]view plaincopy<uses-permissionandroid:name="android.permission.REBOOT"/>
12. 关机:
1). 手机关机直接通过创建相关的Intent来启动一个对话框,根据对话框的确认或取消键来选择是否关机
2). 关机实现需要apk签名。
示例代码如下:
[java]view plaincopypackagecom.example.sds; importandroid.app.Activity; importandroid.content.Intent; importandroid.os.Bundle; importandroid.view.View; importandroid.view.View.OnClickListener; importandroid.widget.Button; publicclassShutDownSwitchextendsActivityimplementsOnClickListener { privateButtonmShutDown; /**Calledwhentheactivityisfirstcreated.*/ @Override publicvoidonCreate(BundlesavedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.main); mShutDown=(Button)findViewById(R.id.shutdown); mShutDown.setOnClickListener(this); } @Override publicvoidonClick(Viewv) { //TODOAuto-generatedmethodstub Intentintent=newIntent("android.intent.action.ACTION_REQUEST_SHUTDOWN"); intent.putExtra("android.intent.extra.KEY_CONFIRM",true); intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK); //弹出系统内置的对话框,选择确定关机或取消关机 startActivity(intent); } }
权限添加:
[html]view plaincopy<uses-permissionandroid:name="android.permission.SHUTDOWN"/>
ok,本文的快捷开关代码实现介绍就到此结束,有了上面这些快捷开关的实现代码,那么当你想要开发一个AppWidget来承载和实现这些开关时就容易多了,至于如何去开发一个AppWidget,有兴趣的读者可以去找找相关这些方面的资料。
相关代码下载链接:/detail/stevenhu_223/5572751
如果觉得《Android快捷开关实现 Wifi开关 蓝牙开关 GPS开关 同步开关 亮度设置开关》对你有帮助,请点赞、收藏,并留下你的观点哦!