/*
* Copyright (C) 2009 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.android.settings.widget;
import android.appwidget.AppWidgetManager;
import android.appwidget.AppWidgetProvider;
import android.bluetooth.BluetoothAdapter;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.SharedPreferences;
import android.content.SharedPreferences.Editor;
import android.content.pm.PackageManager;
import android.net.Uri;
import android.net.wifi.WifiManager;
import android.util.Log;
import android.widget.RemoteViews;
import com.android.settings.R;
import com.android.settings.SecuritySettings;
import com.android.settings.widget.buttons.AirplaneButton;
import com.android.settings.widget.buttons.AutoRotateButton;
import com.android.settings.widget.buttons.BluetoothButton;
import com.android.settings.widget.buttons.BrightnessButton;
import com.android.settings.widget.buttons.FlashlightButton;
import com.android.settings.widget.buttons.GPSButton;
import com.android.settings.widget.buttons.LockScreenButton;
import com.android.settings.widget.buttons.MobileDataButton;
import com.android.settings.widget.buttons.NetworkModeButton;
import com.android.settings.widget.buttons.PowerButton;
import com.android.settings.widget.buttons.ScreenTimeoutButton;
import com.android.settings.widget.buttons.SoundButton;
import com.android.settings.widget.buttons.SyncButton;
import com.android.settings.widget.buttons.WidgetButton;
import com.android.settings.widget.buttons.WifiButton;
import com.android.settings.widget.buttons.WifiApButton;
/**
* Provides control of power-related settings from a widget.
*/
public class SettingsAppWidgetProvider extends AppWidgetProvider {
public static final int STATE_DISABLED = 0;
public static final int STATE_ENABLED = 1;
public static final int STATE_TURNING_ON = 2;
public static final int STATE_TURNING_OFF = 3;
public static final int STATE_UNKNOWN = 4;
public static final int STATE_INTERMEDIATE = 5;
public static final int STATE_DISABLED_RED = 10;
public static final int STATE_ENABLED_RED = 11;
public static final String TAG = "SettingsAppWidgetProvider";
static final ComponentName THIS_APPWIDGET = new ComponentName(
"com.android.settings",
"com.android.settings.widget.SettingsAppWidgetProvider");
private static final boolean DEBUG=true;
//New version that allows moving button position. Increase the WIDGET_PRESENT "version"
public static final int WIDGET_PRESENT = 3;
public static final int WIDGET_NOT_CONFIGURED = 1;
public static final int WIDGET_DELETED = 0;
@Override
public void onEnabled(Context context) {
logD("Received request to enable first widget");
PackageManager pm = context.getPackageManager();
pm.setComponentEnabledSetting(new ComponentName("com.android.settings",
".widget.SettingsAppWidgetProvider"),
PackageManager.COMPONENT_ENABLED_STATE_ENABLED,
PackageManager.DONT_KILL_APP);
}
@Override
public void onDisabled(Context context) {
logD("Received request to remove last widget");
PackageManager pm = context.getPackageManager();
pm.setComponentEnabledSetting(new ComponentName("com.android.settings",
".widget.SettingsAppWidgetProvider"),
PackageManager.COMPONENT_ENABLED_STATE_DISABLED,
PackageManager.DONT_KILL_APP);
}
@Override
public void onDeleted(Context context, int[] appWidgetIds) {
logD("Received request to remove a widget");
for (int appWidgetId:appWidgetIds) {
SharedPreferences widgetPreferences = context.getSharedPreferences(WidgetSettings.WIDGET_PREF_NAME+appWidgetId,
Context.MODE_PRIVATE);
Editor editor = widgetPreferences.edit();
editor.clear();
editor.putInt(WidgetSettings.SAVED, WIDGET_DELETED);
editor.commit();
}
}
/**
* Updates the widget when something changes, or when a button is pushed.
*
* @param context
*/
public static void updateWidget(Context context) {
logD(">> updateWidget IN");
AppWidgetManager manager = AppWidgetManager.getInstance(context);
int[] widgets = manager.getAppWidgetIds(THIS_APPWIDGET);
buildUpdate(context, manager, widgets);
logD("<< updateWidget OUT");
}
@Override
public void onUpdate(Context context, AppWidgetManager appWidgetManager,
int[] appWidgetIds) {
logD(">> onUpdate IN");
buildUpdate(context, appWidgetManager, appWidgetIds);
logD("<< onUpdate OUT");
}
/**
* update main method. Process all widget. Update state and process all widget instances.
*/
static void buildUpdate(Context context, AppWidgetManager appWidgetManager, int[] appWidgetIds) {
logD(">> buildUpdate IN");
SharedPreferences globalPreferences = context.getSharedPreferences(WidgetSettings.WIDGET_PREF_MAIN,Context.MODE_PRIVATE);
// If never initialized before. Populate the widget with defaults
if (!globalPreferences.contains(WidgetSettings.SAVED)) {
Log.d(TAG,"Widget is from a previous version... Let's update");
//It should be just one when the system is clean... but we never now. So let's process all
// We shall get them from the system since the update received can be for a single one.
int[] widgets = appWidgetManager.getAppWidgetIds(THIS_APPWIDGET);
for (int widget:widgets) {
Log.d(TAG,"Will set widget "+widget+" to default settings");
SharedPreferences widgetPreferences = context.getSharedPreferences(WidgetSettings.WIDGET_PREF_NAME+widget,
Context.MODE_PRIVATE);
WidgetSettings.initDefaultWidget(widgetPreferences);
}
if(widgets.length>0) {
WidgetSettings.initDefaultSettings(globalPreferences);
} else {
Log.d(TAG,"No instances yet... Wait for at least one instance to exist before adding global settings");
}
}
//Query for current status of multiple options. Only to be done once
updateStates(context, globalPreferences, appWidgetIds);
//Now process all widgets instances
for (int appWidgetId:appWidgetIds) {
Log.d(TAG,"Call buildUpdate for widget:"+appWidgetId);
RemoteViews views = updateViews(context, globalPreferences, appWidgetId);
if (views!=null) {
appWidgetManager.updateAppWidget(appWidgetId, views);
}
Log.d(TAG,"buildUpdate done for widget:"+appWidgetId);
}
logD("<< buildUpdate OUT");
}
/**
* Method that will trigger the update for all options
*/
private static void updateStates(Context context, SharedPreferences globalPreferences, int[] appWidgetIds) {
WifiButton.getInstance().updateState(context, globalPreferences, appWidgetIds);
WifiApButton.getInstance().updateState(context, globalPreferences, appWidgetIds);
BluetoothButton.getInstance().updateState(context, globalPreferences, appWidgetIds);
GPSButton.getInstance().updateState(context, globalPreferences, appWidgetIds);
MobileDataButton.getInstance().updateState(context, globalPreferences, appWidgetIds);;
NetworkModeButton.getInstance().updateState(context, globalPreferences, appWidgetIds);
SyncButton.getInstance().updateState(context, globalPreferences, appWidgetIds);
SoundButton.getInstance().updateState(context, globalPreferences, appWidgetIds);
AutoRotateButton.getInstance().updateState(context, globalPreferences, appWidgetIds);
ScreenTimeoutButton.getInstance().updateState(context, globalPreferences, appWidgetIds);
AirplaneButton.getInstance().updateState(context, globalPreferences, appWidgetIds);
LockScreenButton.getInstance().updateState(context, globalPreferences, appWidgetIds);
FlashlightButton.getInstance().updateState(context, globalPreferences, appWidgetIds);
BrightnessButton.getInstance().updateState(context, globalPreferences, appWidgetIds);
}
/**
* Update of each widget instance. will check it's configuration
*/
private static RemoteViews updateViews(Context context, SharedPreferences globalPreferences, int appWidgetId) {
logD(">> updateViews IN - Widget:"+appWidgetId);
SharedPreferences widgetPreferences = context.getSharedPreferences(WidgetSettings.WIDGET_PREF_NAME+appWidgetId,
Context.MODE_PRIVATE);
// If not configured do not refresh. Needed due to:
// 1: Ghost instances of the launcher
// 2: Older version no longer compatible. So widget_present was increased
if(widgetPreferences.getInt(WidgetSettings.SAVED,WIDGET_NOT_CONFIGURED)==WIDGET_PRESENT) {
//Set the selected background. On a widget it can only be done by a diferent layout.
int widgetLayout = R.layout.widget;
int backgroundLayout= widgetPreferences.getInt(WidgetSettings.BACKGROUND_IMAGE, 0);
boolean verticalLayout = widgetPreferences.getBoolean(WidgetSettings.USE_VERTICAL, false);
if (!verticalLayout && backgroundLayout==WidgetSettings.TRANSPARENT_BACKGROUND) {
widgetLayout = R.layout.widget_transparent;
}else if (verticalLayout && backgroundLayout==WidgetSettings.TRANSPARENT_BACKGROUND) {
widgetLayout = R.layout.widget_vertical_transparent;
/* }else if (verticalLayout && backgroundLayout==WidgetSettings.WHITE_BACKGROUND) {
widgetLayout = R.layout.widget_white_vertical;
}else if (!verticalLayout && backgroundLayout==WidgetSettings.WHITE_BACKGROUND) {
widgetLayout = R.layout.widget_white;*/
}else if (verticalLayout) {
widgetLayout = R.layout.widget_vertical;
}
// create the new remote views
RemoteViews views = new RemoteViews(context.getPackageName(),
widgetLayout);
//Now call each button to update it's state on this instance.
WifiButton.getInstance().updateView(context, views, globalPreferences, widgetPreferences, appWidgetId);
WifiApButton.getInstance().updateView(context, views, globalPreferences, widgetPreferences, appWidgetId);
BluetoothButton.getInstance().updateView(context, views, globalPreferences, widgetPreferences, appWidgetId);
GPSButton.getInstance().updateView(context, views, globalPreferences, widgetPreferences, appWidgetId);
MobileDataButton.getInstance().updateView(context, views, globalPreferences, widgetPreferences, appWidgetId);
NetworkModeButton.getInstance().updateView(context, views, globalPreferences, widgetPreferences, appWidgetId);
SyncButton.getInstance().updateView(context, views, globalPreferences, widgetPreferences, appWidgetId);
SoundButton.getInstance().updateView(context, views, globalPreferences, widgetPreferences, appWidgetId);
AutoRotateButton.getInstance().updateView(context, views, globalPreferences, widgetPreferences, appWidgetId);
ScreenTimeoutButton.getInstance().updateView(context, views, globalPreferences, widgetPreferences, appWidgetId);
BrightnessButton.getInstance().updateView(context, views, globalPreferences, widgetPreferences, appWidgetId);
FlashlightButton.getInstance().updateView(context, views, globalPreferences, widgetPreferences, appWidgetId);
LockScreenButton.getInstance().updateView(context, views, globalPreferences, widgetPreferences, appWidgetId);
AirplaneButton.getInstance().updateView(context, views, globalPreferences, widgetPreferences, appWidgetId);
return views;
} else {
// Return the layout with widget configuration message.
RemoteViews views = new RemoteViews(context.getPackageName(),
R.layout.widget_configure);
logD(">> updateViews IN - Widget:"+appWidgetId+" no longer present or not configured");
return views;
}
}
/**
* Receives and processes a button pressed intent or state change.
*
* @param context
* @param intent
* Indicates the pressed button.
*/
@Override
public void onReceive(Context context, Intent intent) {
logD(">> onReceive IN");
super.onReceive(context, intent);
if (WifiManager.WIFI_STATE_CHANGED_ACTION.equals(intent.getAction())) {
logD("Received Wifi state change");
WifiButton.getInstance().onReceive(context, intent);
} else if (WifiManager.WIFI_AP_STATE_CHANGED_ACTION.equals(intent.getAction())) {
logD("Received Wifi AP state change");
WifiApButton.getInstance().onReceive(context, intent);
} else if (BluetoothAdapter.ACTION_STATE_CHANGED.equals(intent.getAction())) {
logD("Received Bluetooth state change");
BluetoothButton.getInstance().onReceive(context, intent);
} else if (NetworkModeButton.NETWORK_MODE_CHANGED.equals(intent.getAction())) {
logD("Received Network mode state change");
NetworkModeButton.getInstance().onReceive(context, intent);
} else if (Intent.ACTION_POWER_CONNECTED.equals(intent.getAction()) ||
Intent.ACTION_POWER_DISCONNECTED.equals(intent.getAction())) {
logD("Received power mode state change");
PowerButton.getInstance().onReceive(context, intent);
} else if (intent.hasCategory(Intent.CATEGORY_ALTERNATIVE)) {
Uri data = intent.getData();
int buttonId = Integer.parseInt(data.getSchemeSpecificPart());
if (buttonId == WidgetButton.BUTTON_WIFI) {
logD("Received wifi button change request");
WifiButton.getInstance().toggleState(context);
} else if (buttonId == WidgetButton.BUTTON_WIFI_AP) {
logD("Received wifi ap button change request");
WifiApButton.getInstance().toggleState(context);
} else if (buttonId == WidgetButton.BUTTON_BLUETOOTH) {
logD("Received bluetooth button change request");
BluetoothButton.getInstance().toggleState(context);
} else if (buttonId == WidgetButton.BUTTON_GPS) {
logD("Received GPS button change request");
GPSButton.getInstance().toggleState(context);
} else if (buttonId == WidgetButton.BUTTON_DATA) {
logD("Received mobile data button change request");
MobileDataButton.getInstance().toggleState(context);
} else if (buttonId == WidgetButton.BUTTON_2G3G) {
logD("Received network mode button change request");
NetworkModeButton.getInstance().toggleState(context);
} else if (buttonId == WidgetButton.BUTTON_SYNC) {
logD("Received sync button change request");
SyncButton.getInstance().toggleState(context);
} else if (buttonId == WidgetButton.BUTTON_SOUND) {
logD("Received sound button change request");
SoundButton.getInstance().toggleState(context);
} else if (buttonId == WidgetButton.BUTTON_SCREEN_TIMEOUT) {
logD("Received screen timeout change request");
ScreenTimeoutButton.getInstance().toggleState(context);
} else if (buttonId == WidgetButton.BUTTON_AUTO_ROTATE) {
logD("Received auto rotate change request");
AutoRotateButton.getInstance().toggleState(context);
} else if (buttonId == WidgetButton.BUTTON_BRIGHTNESS) {
logD("Received brightness change request");
BrightnessButton.getInstance().toggleState(context);
} else if (buttonId == WidgetButton.BUTTON_FLASHLIGHT) {
logD("Received flahslight change request");
FlashlightButton.getInstance().toggleState(context);
} else if (buttonId == WidgetButton.BUTTON_LOCK_SCREEN) {
logD("Received Lock Screen change request");
LockScreenButton.getInstance().toggleState(context);
} else if (buttonId == WidgetButton.BUTTON_AIRPLANE) {
logD("Received airplane change request");
AirplaneButton.getInstance().toggleState(context);
}
} else if (MobileDataButton.MOBILE_DATA_CHANGED.equals(intent.getAction())||
Intent.ACTION_USER_PRESENT.equals(intent.getAction()) ||
SecuritySettings.GPS_STATUS_CHANGED.equals(intent.getAction())) {
} else {
logD("Ignoring Action: "+intent.getAction());
// Don't fall-through to updating the widget. The Intent
// was something unrelated or that our super class took
// care of.
logD("<< onReceive OUT");
return;
}
updateWidget(context);
// State changes fall through
logD("<< onReceive OUT");
}
public static void logD(String message) {
if (DEBUG) Log.d(TAG,message);
}
}