diff options
-rw-r--r-- | AndroidManifest.xml | 10 | ||||
-rw-r--r-- | res/layout/installed_app_details.xml | 2 | ||||
-rwxr-xr-x | res/values/dimens.xml | 2 | ||||
-rw-r--r-- | res/values/strings.xml | 16 | ||||
-rw-r--r-- | src/com/android/settings/AllowBindAppWidgetActivity.java | 130 | ||||
-rw-r--r-- | src/com/android/settings/applications/InstalledAppDetails.java | 70 |
6 files changed, 220 insertions, 10 deletions
diff --git a/AndroidManifest.xml b/AndroidManifest.xml index ae6826b..c3f8e29 100644 --- a/AndroidManifest.xml +++ b/AndroidManifest.xml @@ -1319,6 +1319,16 @@ </intent-filter> </activity> + <activity android:name="AllowBindAppWidgetActivity" + android:theme="@*android:style/Theme.Holo.Dialog.Alert" + android:finishOnCloseSystemDialogs="true" + android:excludeFromRecents="true"> + <intent-filter> + <action android:name="android.appwidget.action.APPWIDGET_BIND" /> + <category android:name="android.intent.category.DEFAULT" /> + </intent-filter> + </activity> + <activity android:name="UsageStats" android:label="@string/usage_stats_label" android:parentActivityName="Settings"> <intent-filter> diff --git a/res/layout/installed_app_details.xml b/res/layout/installed_app_details.xml index 5c6867c..099df64 100644 --- a/res/layout/installed_app_details.xml +++ b/res/layout/installed_app_details.xml @@ -342,7 +342,7 @@ </RelativeLayout> <!-- Prefered activities section --> - <TextView + <TextView android:id="@+id/auto_launch_title" style="?android:attr/listSeparatorTextViewStyle" android:layout_marginTop="8dip" android:text="@string/auto_launch_label" /> diff --git a/res/values/dimens.xml b/res/values/dimens.xml index 9649ed3..ba69f13 100755 --- a/res/values/dimens.xml +++ b/res/values/dimens.xml @@ -27,6 +27,8 @@ <dimen name="content_margin_left">16dip</dimen> <dimen name="description_margin_top">26dip</dimen> <dimen name="description_margin_sides">40dip</dimen> + <dimen name="bind_app_widget_dialog_checkbox_bottom_padding">16dip</dimen> + <dimen name="installed_app_details_bullet_offset">8dip</dimen> <dimen name="data_usage_chart_height">252dip</dimen> <dimen name="data_usage_chart_optimalWidth">440dip</dimen> diff --git a/res/values/strings.xml b/res/values/strings.xml index 7ce4c25..58e2cfb 100644 --- a/res/values/strings.xml +++ b/res/values/strings.xml @@ -20,6 +20,9 @@ <!-- Strings for Dialog no button --> <string name="no">"No"</string> + <!-- Strings for Dialog create button --> + <string name="create">Create</string> + <!-- Device Info --> <skip /> <!-- Device Info screen. Used for a status item's value when the proper value is not known --> <string name="device_info_default">Unknown</string> @@ -2328,6 +2331,8 @@ <string name="storage_label">Storage</string> <!-- Manage applications, individual application info screen, heading for settings related to controlling whether this app is the default for some actions --> <string name="auto_launch_label">Launch by default</string> + <!-- Manage applications, individual application info screen, heading for settings related to controlling whether this app is the default for some actions *and* whether the app was given permission by the user to create widgets --> + <string name="auto_launch_label_generic">Defaults</string> <!-- Manage applications, individual application info screen, heading for settings related to controlling application screen compatibility --> <string name="screen_compatibility_label">Screen compatibility</string> <!-- Manage applications, individual application info screen, heading for settings related to the app's permissions. for example, it may list all the permissions the app has. --> @@ -2366,6 +2371,8 @@ <string name="app_factory_reset">Uninstall updates</string> <!-- Manage applications, individual application info screen, screen, message text under Launch by default heading. This is present if the app is set as a default for some actions. --> <string name="auto_launch_enable_text">You\'ve chosen to launch this app by default for some actions.</string> + <!-- Manage applications, individual application info screen, screen, message text under Launch by default heading. This is present if the app was given user permission to create widgets. --> + <string name="always_allow_bind_appwidgets_text">You\'ve chosen to allow this app to create widgets and access their data.</string> <!-- Manage applications, individual application screen, text under Launch by default heading if the app is NOT a default for actions --> <string name="auto_launch_disable_text">No defaults set.</string> <!-- Manage applications, individual application screen, button label under Launch by default heading. This is used to clear any default actions that may be assigned to this app. --> @@ -2788,6 +2795,15 @@ the final name for Gadgets/Widgets, so please translate both for now. --> <string name="widget_picker_title">Choose widget</string> + <!-- Title in dialog that pops up when an app requests permission to bind a widget [CHAR LIMIT=NONE] --> + <string name="allow_bind_app_widget_activity_allow_bind_title">Create widget and allow access?</string> + + <!-- Message in dialog that pops up when an app requests permission to bind a widget [CHAR LIMIT=NONE] --> + <string name="allow_bind_app_widget_activity_allow_bind">After you create the widget, <xliff:g id="widget_host_name">%1$s</xliff:g> can access all data it displays.</string> + + <!-- Text for checkbox that pops up when an app requests permission to bind a widget [CHAR LIMIT=NONE] --> + <string name="allow_bind_app_widget_activity_always_allow_bind">Always allow <xliff:g id="widget_host_name">%1$s</xliff:g> to create widgets and access their data</string> + <!-- Used to show an amount of time in the form "d days, h hours, m minutes, s seconds" in BatteryHistory --> <string name="battery_history_days"><xliff:g id="days">%1$d</xliff:g>d <xliff:g id="hours">%2$d</xliff:g>h <xliff:g id="minutes">%3$d</xliff:g>m <xliff:g id="seconds">%4$d</xliff:g>s</string> diff --git a/src/com/android/settings/AllowBindAppWidgetActivity.java b/src/com/android/settings/AllowBindAppWidgetActivity.java new file mode 100644 index 0000000..2f54f8e --- /dev/null +++ b/src/com/android/settings/AllowBindAppWidgetActivity.java @@ -0,0 +1,130 @@ +/* + * Copyright (C) 2012 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; + +import android.app.AlertDialog; +import android.appwidget.AppWidgetManager; +import android.content.ComponentName; +import android.content.Context; +import android.content.DialogInterface; +import android.content.Intent; +import android.content.pm.ApplicationInfo; +import android.content.pm.PackageManager; +import android.os.Bundle; +import android.util.DisplayMetrics; +import android.util.Log; +import android.view.LayoutInflater; +import android.widget.CheckBox; + +import com.android.internal.app.AlertActivity; +import com.android.internal.app.AlertController; + +/** + * This activity is displayed when an app launches the BIND_APPWIDGET intent. This allows apps + * that don't have the BIND_APPWIDGET permission to bind specific widgets. + */ +public class AllowBindAppWidgetActivity extends AlertActivity implements + DialogInterface.OnClickListener { + + private CheckBox mAlwaysUse; + private int mAppWidgetId; + private ComponentName mComponentName; + private String mCallingPackage; + private AppWidgetManager mAppWidgetManager; + + // Indicates whether this activity was closed because of a click + private boolean mClicked; + + public void onClick(DialogInterface dialog, int which) { + if (which == AlertDialog.BUTTON_POSITIVE) { + // By default, set the result to cancelled + setResult(RESULT_CANCELED); + if (mAppWidgetId != -1 && mComponentName != null && mCallingPackage != null) { + try { + mAppWidgetManager.bindAppWidgetId(mAppWidgetId, mComponentName); + Intent result = new Intent(); + result.putExtra("EXTRA_APPWIDGET_ID", mAppWidgetId); + setResult(RESULT_OK); + } catch (Exception e) { + Log.v("BIND_APPWIDGET", "Error binding widget with id " + + mAppWidgetId + " and component " + mComponentName); + } + } + boolean alwaysAllowBind = mAlwaysUse.isChecked(); + if (alwaysAllowBind != mAppWidgetManager.hasBindAppWidgetPermission(mCallingPackage)) { + mAppWidgetManager.setBindAppWidgetPermission(mCallingPackage, alwaysAllowBind); + } + } + finish(); + } + + protected void onDestroy() { + if (!mClicked) { + setResult(RESULT_CANCELED); + finish(); + } + super.onDestroy(); + } + + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + Intent intent = getIntent(); + CharSequence label = ""; + if (intent != null) { + try { + mAppWidgetId = intent.getIntExtra(AppWidgetManager.EXTRA_APPWIDGET_ID, -1); + mComponentName = (ComponentName) + intent.getParcelableExtra(AppWidgetManager.EXTRA_APPWIDGET_PROVIDER); + mCallingPackage = getCallingPackage(); + PackageManager pm = getPackageManager(); + ApplicationInfo ai = pm.getApplicationInfo(mCallingPackage, 0); + label = pm.getApplicationLabel(ai); + } catch (Exception e) { + mAppWidgetId = -1; + mComponentName = null; + mCallingPackage = null; + Log.v("BIND_APPWIDGET", "Error getting parameters"); + setResult(RESULT_CANCELED); + finish(); + return; + } + } + AlertController.AlertParams ap = mAlertParams; + ap.mTitle = getString(R.string.allow_bind_app_widget_activity_allow_bind_title); + ap.mMessage = getString(R.string.allow_bind_app_widget_activity_allow_bind, label); + ap.mPositiveButtonText = getString(R.string.create); + ap.mNegativeButtonText = getString(android.R.string.cancel); + ap.mPositiveButtonListener = this; + ap.mNegativeButtonListener = this; + LayoutInflater inflater = + (LayoutInflater) getSystemService(Context.LAYOUT_INFLATER_SERVICE); + ap.mView = inflater.inflate(com.android.internal.R.layout.always_use_checkbox, null); + mAlwaysUse = (CheckBox) ap.mView.findViewById(com.android.internal.R.id.alwaysUse); + mAlwaysUse.setText(getString(R.string.allow_bind_app_widget_activity_always_allow_bind, label)); + + mAlwaysUse.setPadding(mAlwaysUse.getPaddingLeft(), + mAlwaysUse.getPaddingTop(), + mAlwaysUse.getPaddingRight(), + (int) (mAlwaysUse.getPaddingBottom() + + getResources().getDimension(R.dimen.bind_app_widget_dialog_checkbox_bottom_padding))); + + mAppWidgetManager = AppWidgetManager.getInstance(this); + mAlwaysUse.setChecked(mAppWidgetManager.hasBindAppWidgetPermission(mCallingPackage)); + + setupAlert(); + } +} diff --git a/src/com/android/settings/applications/InstalledAppDetails.java b/src/com/android/settings/applications/InstalledAppDetails.java index fcdf899..6fa20ce 100644 --- a/src/com/android/settings/applications/InstalledAppDetails.java +++ b/src/com/android/settings/applications/InstalledAppDetails.java @@ -29,7 +29,9 @@ import android.app.Fragment; import android.app.INotificationManager; import android.app.NotificationManager; import android.app.admin.DevicePolicyManager; +import android.appwidget.AppWidgetManager; import android.content.BroadcastReceiver; +import android.content.ComponentName; import android.content.Context; import android.content.DialogInterface; import android.content.Intent; @@ -52,13 +54,15 @@ import android.os.Message; import android.os.RemoteException; import android.os.ServiceManager; import android.preference.PreferenceActivity; +import android.text.SpannableString; +import android.text.TextUtils; import android.text.format.Formatter; +import android.text.style.BulletSpan; import android.util.Log; import java.lang.ref.WeakReference; import java.util.ArrayList; import java.util.List; -import android.content.ComponentName; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; @@ -91,6 +95,7 @@ public class InstalledAppDetails extends Fragment private PackageManager mPm; private IUsbManager mUsbManager; + private AppWidgetManager mAppWidgetManager; private DevicePolicyManager mDpm; private ApplicationsState mState; private ApplicationsState.AppEntry mAppEntry; @@ -346,6 +351,7 @@ public class InstalledAppDetails extends Fragment mPm = getActivity().getPackageManager(); IBinder b = ServiceManager.getService(Context.USB_SERVICE); mUsbManager = IUsbManager.Stub.asInterface(b); + mAppWidgetManager = AppWidgetManager.getInstance(getActivity()); mDpm = (DevicePolicyManager)getActivity().getSystemService(Context.DEVICE_POLICY_SERVICE); mCanBeOnSdCardChecker = new CanBeOnSdCardChecker(); @@ -493,20 +499,55 @@ public class InstalledAppDetails extends Fragment // Intent list cannot be null. so pass empty list List<IntentFilter> intentList = new ArrayList<IntentFilter>(); mPm.getPreferredActivities(intentList, prefActList, packageName); - if(localLOGV) Log.i(TAG, "Have "+prefActList.size()+" number of activities in prefered list"); + if (localLOGV) + Log.i(TAG, "Have " + prefActList.size() + " number of activities in preferred list"); boolean hasUsbDefaults = false; try { hasUsbDefaults = mUsbManager.hasDefaults(packageName); } catch (RemoteException e) { Log.e(TAG, "mUsbManager.hasDefaults", e); } - TextView autoLaunchView = (TextView)mRootView.findViewById(R.id.auto_launch); - if (prefActList.size() <= 0 && !hasUsbDefaults) { - // Disable clear activities button - autoLaunchView.setText(R.string.auto_launch_disable_text); - mActivitiesButton.setEnabled(false); + boolean hasBindAppWidgetPermission = + mAppWidgetManager.hasBindAppWidgetPermission(mAppEntry.info.packageName); + + TextView autoLaunchTitleView = (TextView) mRootView.findViewById(R.id.auto_launch_title); + TextView autoLaunchView = (TextView) mRootView.findViewById(R.id.auto_launch); + boolean autoLaunchEnabled = prefActList.size() > 0 || hasUsbDefaults; + if (!autoLaunchEnabled && !hasBindAppWidgetPermission) { + resetLaunchDefaultsUi(autoLaunchTitleView, autoLaunchView); } else { - autoLaunchView.setText(R.string.auto_launch_enable_text); + boolean useBullets = hasBindAppWidgetPermission && autoLaunchEnabled; + + if (hasBindAppWidgetPermission) { + autoLaunchTitleView.setText(R.string.auto_launch_label_generic); + } else { + autoLaunchTitleView.setText(R.string.auto_launch_label); + } + + CharSequence text = null; + int bulletIndent = getResources() + .getDimensionPixelSize(R.dimen.installed_app_details_bullet_offset); + if (autoLaunchEnabled) { + CharSequence autoLaunchEnableText = getText(R.string.auto_launch_enable_text); + SpannableString s = new SpannableString(autoLaunchEnableText); + if (useBullets) { + s.setSpan(new BulletSpan(bulletIndent), 0, autoLaunchEnableText.length(), 0); + } + text = (text == null) ? + TextUtils.concat(s, "\n") : TextUtils.concat(text, "\n", s, "\n"); + } + if (hasBindAppWidgetPermission) { + CharSequence alwaysAllowBindAppWidgetsText = + getText(R.string.always_allow_bind_appwidgets_text); + SpannableString s = new SpannableString(alwaysAllowBindAppWidgetsText); + if (useBullets) { + s.setSpan(new BulletSpan(bulletIndent), + 0, alwaysAllowBindAppWidgetsText.length(), 0); + } + text = (text == null) ? + TextUtils.concat(s, "\n") : TextUtils.concat(text, "\n", s, "\n"); + } + autoLaunchView.setText(text); mActivitiesButton.setEnabled(true); mActivitiesButton.setOnClickListener(this); } @@ -549,6 +590,13 @@ public class InstalledAppDetails extends Fragment return true; } + private void resetLaunchDefaultsUi(TextView title, TextView autoLaunchView) { + title.setText(R.string.auto_launch_label); + autoLaunchView.setText(R.string.auto_launch_disable_text); + // Disable clear activities button + mActivitiesButton.setEnabled(false); + } + private void setIntentAndFinish(boolean finish, boolean appChanged) { if(localLOGV) Log.i(TAG, "appChanged="+appChanged); Intent intent = new Intent(); @@ -905,7 +953,11 @@ public class InstalledAppDetails extends Fragment } catch (RemoteException e) { Log.e(TAG, "mUsbManager.clearDefaults", e); } - mActivitiesButton.setEnabled(false); + mAppWidgetManager.setBindAppWidgetPermission(packageName, false); + TextView autoLaunchTitleView = + (TextView) mRootView.findViewById(R.id.auto_launch_title); + TextView autoLaunchView = (TextView) mRootView.findViewById(R.id.auto_launch); + resetLaunchDefaultsUi(autoLaunchTitleView, autoLaunchView); } else if(v == mClearDataButton) { if (mAppEntry.info.manageSpaceActivityName != null) { if (!Utils.isMonkeyRunning()) { |