SettingsAppWidgetProvider.java revision 03a6110b4f62e72592b451c05848cfaad8c65324
1/* 2 * Copyright (C) 2009 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17package com.android.settings.widget; 18 19import android.app.PendingIntent; 20import android.appwidget.AppWidgetManager; 21import android.appwidget.AppWidgetProvider; 22import android.bluetooth.BluetoothDevice; 23import android.content.ComponentName; 24import android.content.ContentResolver; 25import android.content.Context; 26import android.content.IContentService; 27import android.content.Intent; 28import android.content.pm.PackageManager; 29import android.location.LocationManager; 30import android.net.ConnectivityManager; 31import android.net.Uri; 32import android.net.wifi.WifiManager; 33import android.os.IHardwareService; 34import android.os.RemoteException; 35import android.os.ServiceManager; 36import android.provider.Settings; 37import android.util.Log; 38import android.widget.RemoteViews; 39import com.android.settings.R; 40import com.android.settings.bluetooth.LocalBluetoothManager; 41 42/** 43 * Provides control of power-related settings from a widget. 44 */ 45public class SettingsAppWidgetProvider extends AppWidgetProvider { 46 static final String TAG = "SettingsAppWidgetProvider"; 47 48 static final ComponentName THIS_APPWIDGET = 49 new ComponentName("com.android.settings", 50 "com.android.settings.widget.SettingsAppWidgetProvider"); 51 52 private static LocalBluetoothManager mLocalBluetoothManager = null; 53 54 private static final int BUTTON_WIFI = 0; 55 private static final int BUTTON_BRIGHTNESS = 1; 56 private static final int BUTTON_SYNC = 2; 57 private static final int BUTTON_GPS = 3; 58 private static final int BUTTON_BLUETOOTH = 4; 59 60 private static final int STATE_DISABLED = 0; 61 private static final int STATE_ENABLED = 1; 62 private static final int STATE_INTERMEDIATE = 2; 63 64 /** 65 * Minimum and maximum brightnesses. Don't go to 0 since that makes the display unusable 66 */ 67 private static final int MINIMUM_BACKLIGHT = android.os.Power.BRIGHTNESS_DIM + 10; 68 private static final int MAXIMUM_BACKLIGHT = android.os.Power.BRIGHTNESS_ON; 69 private static final int DEFAULT_BACKLIGHT = (int) (android.os.Power.BRIGHTNESS_ON * 0.4f); 70 71 @Override 72 public void onUpdate(Context context, AppWidgetManager appWidgetManager, 73 int[] appWidgetIds) { 74 // Update each requested appWidgetId 75 RemoteViews view = buildUpdate(context, -1); 76 77 for (int i = 0; i < appWidgetIds.length; i++) { 78 appWidgetManager.updateAppWidget(appWidgetIds[i], view); 79 } 80 } 81 82 @Override 83 public void onEnabled(Context context) { 84 PackageManager pm = context.getPackageManager(); 85 pm.setComponentEnabledSetting( 86 new ComponentName("com.android.settings", ".widget.SettingsAppWidgetProvider"), 87 PackageManager.COMPONENT_ENABLED_STATE_ENABLED, 88 PackageManager.DONT_KILL_APP); 89 } 90 91 @Override 92 public void onDisabled(Context context) { 93 Class clazz = com.android.settings.widget.SettingsAppWidgetProvider.class; 94 PackageManager pm = context.getPackageManager(); 95 pm.setComponentEnabledSetting( 96 new ComponentName("com.android.settings", ".widget.SettingsAppWidgetProvider"), 97 PackageManager.COMPONENT_ENABLED_STATE_DISABLED, 98 PackageManager.DONT_KILL_APP); 99 } 100 101 /** 102 * Load image for given widget and build {@link RemoteViews} for it. 103 */ 104 static RemoteViews buildUpdate(Context context, int appWidgetId) { 105 RemoteViews views = new RemoteViews(context.getPackageName(), 106 R.layout.widget); 107 views.setOnClickPendingIntent(R.id.btn_wifi, getLaunchPendingIntent(context, appWidgetId, 108 BUTTON_WIFI)); 109 views.setOnClickPendingIntent(R.id.btn_brightness, 110 getLaunchPendingIntent(context, 111 appWidgetId, BUTTON_BRIGHTNESS)); 112 views.setOnClickPendingIntent(R.id.btn_sync, 113 getLaunchPendingIntent(context, 114 appWidgetId, BUTTON_SYNC)); 115 views.setOnClickPendingIntent(R.id.btn_gps, 116 getLaunchPendingIntent(context, appWidgetId, BUTTON_GPS)); 117 views.setOnClickPendingIntent(R.id.btn_bluetooth, 118 getLaunchPendingIntent(context, 119 appWidgetId, BUTTON_BLUETOOTH)); 120 121 updateButtons(views, context); 122 return views; 123 } 124 125 /** 126 * Updates the widget when something changes, or when a button is pushed. 127 * 128 * @param context 129 */ 130 public static void updateWidget(Context context) { 131 RemoteViews views = buildUpdate(context, -1); 132 // Update specific list of appWidgetIds if given, otherwise default to all 133 final AppWidgetManager gm = AppWidgetManager.getInstance(context); 134 gm.updateAppWidget(THIS_APPWIDGET, views); 135 } 136 137 /** 138 * Updates the buttons based on the underlying states of wifi, etc. 139 * 140 * @param views The RemoteViews to update. 141 * @param context 142 */ 143 private static void updateButtons(RemoteViews views, Context context) { 144 switch (getWifiState(context)) { 145 case STATE_DISABLED: 146 views.setImageViewResource(R.id.btn_wifi, R.drawable.widget_btn_wifi_off); 147 break; 148 case STATE_ENABLED: 149 views.setImageViewResource(R.id.btn_wifi, R.drawable.widget_btn_wifi); 150 break; 151 case STATE_INTERMEDIATE: 152 views.setImageViewResource(R.id.btn_wifi, R.drawable.widget_btn_wifi_gray); 153 break; 154 } 155 if (getBrightness(context)) { 156 views.setImageViewResource(R.id.btn_brightness, R.drawable.widget_btn_brightness); 157 } else { 158 views.setImageViewResource(R.id.btn_brightness, R.drawable.widget_btn_brightness_off); 159 } 160 if (getBackgroundDataState(context)) { 161 views.setImageViewResource(R.id.btn_sync, R.drawable.widget_btn_sync); 162 } else { 163 views.setImageViewResource(R.id.btn_sync, R.drawable.widget_btn_sync_off); 164 } 165 if (getGpsState(context)) { 166 views.setImageViewResource(R.id.btn_gps, R.drawable.widget_btn_gps); 167 } else { 168 views.setImageViewResource(R.id.btn_gps, R.drawable.widget_btn_gps_off); 169 } 170 switch (getBluetoothState(context)) { 171 case STATE_DISABLED: 172 views.setImageViewResource(R.id.btn_bluetooth, R.drawable.widget_btn_bluetooth_off); 173 break; 174 case STATE_ENABLED: 175 views.setImageViewResource(R.id.btn_bluetooth, R.drawable.widget_btn_bluetooth); 176 break; 177 case STATE_INTERMEDIATE: 178 views.setImageViewResource(R.id.btn_bluetooth, R.drawable.widget_btn_bluetooth_gray); 179 break; 180 } 181 } 182 183 /** 184 * Creates PendingIntent to notify the widget of a button click. 185 * 186 * @param context 187 * @param appWidgetId 188 * @return 189 */ 190 private static PendingIntent getLaunchPendingIntent(Context context, int appWidgetId, int buttonId) { 191 Intent launchIntent = new Intent(); 192 launchIntent.setClass(context, SettingsAppWidgetProvider.class); 193 launchIntent.addCategory(Intent.CATEGORY_ALTERNATIVE); 194 launchIntent.setData(Uri.parse("custom:" + buttonId)); 195 PendingIntent pi = PendingIntent.getBroadcast(context, 0 /* no requestCode */, 196 launchIntent, 0 /* no flags */); 197 return pi; 198 } 199 200 /** 201 * Receives and processes a button pressed intent or state change. 202 * 203 * @param context 204 * @param intent Indicates the pressed button. 205 */ 206 @Override 207 public void onReceive(Context context, Intent intent) { 208 super.onReceive(context, intent); 209 if (intent.hasCategory(Intent.CATEGORY_ALTERNATIVE)) { 210 Uri data = intent.getData(); 211 int buttonId = Integer.parseInt(data.getSchemeSpecificPart()); 212 if (buttonId == BUTTON_WIFI) { 213 toggleWifi(context); 214 } else if (buttonId == BUTTON_BRIGHTNESS) { 215 toggleBrightness(context); 216 } else if (buttonId == BUTTON_SYNC) { 217 toggleBackgroundData(context); 218 } else if (buttonId == BUTTON_GPS) { 219 toggleGps(context); 220 } else if (buttonId == BUTTON_BLUETOOTH) { 221 toggleBluetooth(context); 222 } 223 } 224 // State changes fall through 225 updateWidget(context); 226 } 227 228 /** 229 * Gets the state of Wi-Fi 230 * 231 * @param context 232 * @return STATE_ENABLED, STATE_DISABLED, or STATE_INTERMEDIATE 233 */ 234 private static int getWifiState(Context context) { 235 WifiManager wifiManager = (WifiManager) context.getSystemService(Context.WIFI_SERVICE); 236 int wifiState = wifiManager.getWifiState(); 237 if (wifiState == WifiManager.WIFI_STATE_DISABLED) { 238 return STATE_DISABLED; 239 } else if (wifiState == WifiManager.WIFI_STATE_ENABLED) { 240 return STATE_ENABLED; 241 } else { 242 return STATE_INTERMEDIATE; 243 } 244 } 245 246 /** 247 * Toggles the state of Wi-Fi 248 * 249 * @param context 250 */ 251 private void toggleWifi(Context context) { 252 WifiManager wifiManager = (WifiManager) context.getSystemService(Context.WIFI_SERVICE); 253 int wifiState = getWifiState(context); 254 if (wifiState == STATE_ENABLED) { 255 wifiManager.setWifiEnabled(false); 256 } else if (wifiState == STATE_DISABLED) { 257 wifiManager.setWifiEnabled(true); 258 mLocalBluetoothManager.setBluetoothEnabled(true); 259 } 260 } 261 262 /** 263 * Gets the state of background data. 264 * 265 * @param context 266 * @return true if enabled 267 */ 268 private static boolean getBackgroundDataState(Context context) { 269 ConnectivityManager connManager = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE); 270 return connManager.getBackgroundDataSetting(); 271 } 272 273 /** 274 * Toggle background data and sync tickles. 275 * 276 * @param context 277 */ 278 private void toggleBackgroundData(Context context) { 279 ConnectivityManager connManager = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE); 280 boolean sync = getBackgroundDataState(context); 281 connManager.setBackgroundDataSetting(!sync); 282 283 IContentService contentService = ContentResolver.getContentService(); 284 try { 285 contentService.setListenForNetworkTickles(!sync); 286 } catch (RemoteException e) { 287 Log.d(TAG, "toggleBackgroundData: " + e); 288 } 289 } 290 291 /** 292 * Gets the state of GPS location. 293 * 294 * @param context 295 * @return true if enabled. 296 */ 297 private static boolean getGpsState(Context context) { 298 ContentResolver resolver = context.getContentResolver(); 299 return Settings.Secure.isLocationProviderEnabled(resolver, LocationManager.GPS_PROVIDER); 300 } 301 302 /** 303 * Toggles the state of GPS. 304 * 305 * @param context 306 */ 307 private void toggleGps(Context context) { 308 ContentResolver resolver = context.getContentResolver(); 309 boolean enabled = getGpsState(context); 310 Settings.Secure.setLocationProviderEnabled(resolver, LocationManager.GPS_PROVIDER, !enabled); 311 } 312 313 /** 314 * Gets state of brightness. 315 * 316 * @param context 317 * @return true if more than moderately bright. 318 */ 319 private static boolean getBrightness(Context context) { 320 try { 321 IHardwareService hardware = IHardwareService.Stub.asInterface( 322 ServiceManager.getService("hardware")); 323 if (hardware != null) { 324 int brightness = Settings.System.getInt(context.getContentResolver(), 325 Settings.System.SCREEN_BRIGHTNESS); 326 return brightness > 100; 327 } 328 } catch (Exception e) { 329 Log.d(TAG, "getBrightness: " + e); 330 } 331 return false; 332 } 333 334 /** 335 * Increases or decreases the brightness. 336 * 337 * @param context 338 */ 339 private void toggleBrightness(Context context) { 340 try { 341 IHardwareService hardware = IHardwareService.Stub.asInterface( 342 ServiceManager.getService("hardware")); 343 if (hardware != null) { 344 ContentResolver cr = context.getContentResolver(); 345 int brightness = Settings.System.getInt(cr, 346 Settings.System.SCREEN_BRIGHTNESS); 347 // Rotate MINIMUM -> DEFAULT -> MAXIMUM 348 // Technically, not a toggle... 349 if (brightness < DEFAULT_BACKLIGHT) { 350 brightness = DEFAULT_BACKLIGHT; 351 } else if (brightness < MAXIMUM_BACKLIGHT) { 352 brightness = MAXIMUM_BACKLIGHT; 353 } else { 354 brightness = MINIMUM_BACKLIGHT; 355 } 356 hardware.setBacklights(brightness); 357 Settings.System.putInt(cr, Settings.System.SCREEN_BRIGHTNESS, brightness); 358 brightness = Settings.System.getInt(cr, 359 Settings.System.SCREEN_BRIGHTNESS); 360 } 361 } catch (RemoteException e) { 362 Log.d(TAG, "toggleBrightness: " + e); 363 } catch (Settings.SettingNotFoundException e) { 364 Log.d(TAG, "toggleBrightness: " + e); 365 } 366 } 367 368 /** 369 * Gets state of bluetooth 370 * 371 * @param context 372 * @return STATE_ENABLED, STATE_DISABLED, or STATE_INTERMEDIATE 373 */ 374 private static int getBluetoothState(Context context) { 375 if (mLocalBluetoothManager == null) { 376 mLocalBluetoothManager = LocalBluetoothManager.getInstance(context); 377 if (mLocalBluetoothManager == null) { 378 return STATE_INTERMEDIATE; // On emulator? 379 } 380 } 381 int state = mLocalBluetoothManager.getBluetoothState(); 382 if (state == BluetoothDevice.BLUETOOTH_STATE_OFF) { 383 return STATE_DISABLED; 384 } else if (state == BluetoothDevice.BLUETOOTH_STATE_ON) { 385 return STATE_ENABLED; 386 } else { 387 return STATE_INTERMEDIATE; 388 } 389 } 390 391 /** 392 * Toggles the state of bluetooth 393 * 394 * @param context 395 */ 396 private void toggleBluetooth(Context context) { 397 int state = getBluetoothState(context); 398 if (state == STATE_ENABLED) { 399 mLocalBluetoothManager.setBluetoothEnabled(false); 400 } else if (state == STATE_DISABLED) { 401 mLocalBluetoothManager.setBluetoothEnabled(true); 402 } 403 } 404} 405