diff options
author | Dianne Hackborn <hackbod@google.com> | 2011-08-09 19:35:56 -0700 |
---|---|---|
committer | Dianne Hackborn <hackbod@google.com> | 2011-08-10 17:30:19 -0700 |
commit | 9e9721266feafdf16786b94f6fac4c06220cd422 (patch) | |
tree | 9f3de81d278b82453b86a96e84fdcbed49a780f4 | |
parent | 315ced0cc2ac2f654d2aea3ee78bf9e289c5389d (diff) | |
download | android_packages_apps_PackageInstaller-9e9721266feafdf16786b94f6fac4c06220cd422.tar.gz android_packages_apps_PackageInstaller-9e9721266feafdf16786b94f6fac4c06220cd422.tar.bz2 android_packages_apps_PackageInstaller-9e9721266feafdf16786b94f6fac4c06220cd422.zip |
Implement new extended install/uninstall options.
Change-Id: I60374f937ca3ccf454480b196a7eb4e36d67fe86
-rw-r--r-- | AndroidManifest.xml | 16 | ||||
-rw-r--r-- | res/values/strings.xml | 5 | ||||
-rwxr-xr-x | src/com/android/packageinstaller/InstallAppProgress.java | 12 | ||||
-rw-r--r-- | src/com/android/packageinstaller/PackageInstallerActivity.java | 84 | ||||
-rw-r--r-- | src/com/android/packageinstaller/RemoveReceiver.java | 42 | ||||
-rwxr-xr-x | src/com/android/packageinstaller/UninstallAppProgress.java | 10 | ||||
-rwxr-xr-x | src/com/android/packageinstaller/UninstallerActivity.java | 6 |
7 files changed, 167 insertions, 8 deletions
diff --git a/AndroidManifest.xml b/AndroidManifest.xml index a24b0e1f..a0fc6cd6 100644 --- a/AndroidManifest.xml +++ b/AndroidManifest.xml @@ -17,11 +17,18 @@ android:excludeFromRecents="true"> <intent-filter> <action android:name="android.intent.action.VIEW" /> + <action android:name="android.intent.action.INSTALL_PACKAGE" /> <category android:name="android.intent.category.DEFAULT" /> <data android:scheme="content" /> <data android:scheme="file" /> <data android:mimeType="application/vnd.android.package-archive" /> </intent-filter> + <intent-filter> + <action android:name="android.intent.action.INSTALL_PACKAGE" /> + <category android:name="android.intent.category.DEFAULT" /> + <data android:scheme="content" /> + <data android:scheme="file" /> + </intent-filter> </activity> <activity android:name=".InstallAppProgress" android:configChanges="orientation|keyboardHidden"> @@ -32,6 +39,7 @@ <intent-filter> <action android:name="android.intent.action.VIEW" /> <action android:name="android.intent.action.DELETE" /> + <action android:name="android.intent.action.UNINSTALL_PACKAGE" /> <category android:name="android.intent.category.DEFAULT" /> <data android:scheme="package" /> </intent-filter> @@ -39,5 +47,13 @@ <activity android:name=".UninstallAppProgress" android:configChanges="orientation|keyboardHidden"> </activity> + <!-- + <receiver android:name=".RemoveReceiver"> + <intent-filter> + <action android:name="android.intent.action.PACKAGE_FULLY_REMOVED" /> + <data android:scheme="package" /> + </intent-filter> + </receiver> + --> </application> </manifest> diff --git a/res/values/strings.xml b/res/values/strings.xml index d8749782..9dadd510 100644 --- a/res/values/strings.xml +++ b/res/values/strings.xml @@ -57,6 +57,11 @@ <string name="unknown_apps_dlg_text" product="default">For security, your phone is set to block installation of applications not obtained from Android Market.</string> <string name="ok">OK</string> <string name="settings">Settings</string> + <!-- Title of dialog asking user if they would allow an application to be an install source. --> + <string name="allow_source_dlg_title">Allow new source for apps?</string> + <!-- Message of dialog asking user if they would allow an application to be an install source. --> + <string name="allow_source_dlg_text"><xliff:g id="app_name">%1$s</xliff:g> wants to install other apps.\n\nAllow + this now and in the future?</string> <string name="manage_applications">Manage applications</string> <string name="dlg_app_replacement_title">Replace application</string> <string name="dlg_app_replacement_statement">The application you are installing will replace another application.\n\nAll previous user data will be saved.</string> diff --git a/src/com/android/packageinstaller/InstallAppProgress.java b/src/com/android/packageinstaller/InstallAppProgress.java index 08a6d1dd..a1c07952 100755 --- a/src/com/android/packageinstaller/InstallAppProgress.java +++ b/src/com/android/packageinstaller/InstallAppProgress.java @@ -30,8 +30,6 @@ import android.content.pm.PackageInfo; import android.content.pm.PackageManager; import android.content.pm.ResolveInfo; import android.content.pm.PackageManager.NameNotFoundException; -import android.content.res.Resources; -import android.graphics.drawable.Drawable; import android.graphics.drawable.LevelListDrawable; import android.net.Uri; import android.os.Bundle; @@ -39,7 +37,6 @@ import android.os.Handler; import android.os.Message; import android.util.Log; import android.view.View; -import android.view.Window; import android.widget.Button; import android.widget.ProgressBar; import android.widget.TextView; @@ -74,6 +71,15 @@ public class InstallAppProgress extends Activity implements View.OnClickListener public void handleMessage(Message msg) { switch (msg.what) { case INSTALL_COMPLETE: + if (getIntent().getBooleanExtra(Intent.EXTRA_RETURN_RESULT, false)) { + Intent result = new Intent(); + result.putExtra(Intent.EXTRA_INSTALL_RESULT, msg.arg1); + setResult(msg.arg1 == PackageManager.INSTALL_SUCCEEDED + ? Activity.RESULT_OK : Activity.RESULT_FIRST_USER, + result); + finish(); + return; + } // Update the status text mProgressBar.setVisibility(View.INVISIBLE); // Show the ok button diff --git a/src/com/android/packageinstaller/PackageInstallerActivity.java b/src/com/android/packageinstaller/PackageInstallerActivity.java index 8a009617..d4591601 100644 --- a/src/com/android/packageinstaller/PackageInstallerActivity.java +++ b/src/com/android/packageinstaller/PackageInstallerActivity.java @@ -19,9 +19,11 @@ package com.android.packageinstaller; import android.app.Activity; import android.app.AlertDialog; import android.app.Dialog; +import android.content.Context; import android.content.DialogInterface; import android.content.DialogInterface.OnCancelListener; import android.content.Intent; +import android.content.SharedPreferences; import android.content.pm.ApplicationInfo; import android.content.pm.PackageManager; import android.content.pm.PackageManager.NameNotFoundException; @@ -51,7 +53,8 @@ public class PackageInstallerActivity extends Activity implements OnCancelListen private Uri mPackageURI; private boolean localLOGV = false; PackageManager mPm; - private PackageParser.Package mPkgInfo; + PackageParser.Package mPkgInfo; + ApplicationInfo mSourceInfo; // ApplicationInfo object primarily used for already existing applications private ApplicationInfo mAppInfo = null; @@ -62,6 +65,8 @@ public class PackageInstallerActivity extends Activity implements OnCancelListen private Button mOk; private Button mCancel; + static final String PREFS_ALLOWED_SOURCES = "allowed_sources"; + // Dialog identifiers used in showDialog private static final int DLG_BASE = 0; private static final int DLG_REPLACE_APP = DLG_BASE + 1; @@ -69,6 +74,7 @@ public class PackageInstallerActivity extends Activity implements OnCancelListen private static final int DLG_PACKAGE_ERROR = DLG_BASE + 3; private static final int DLG_OUT_OF_SPACE = DLG_BASE + 4; private static final int DLG_INSTALL_ERROR = DLG_BASE + 5; + private static final int DLG_ALLOW_SOURCE = DLG_BASE + 6; private void startInstallConfirm() { LinearLayout permsSection = (LinearLayout) mInstallConfirm.findViewById(R.id.permissions_section); @@ -116,6 +122,7 @@ public class PackageInstallerActivity extends Activity implements OnCancelListen .setNegativeButton(R.string.cancel, new DialogInterface.OnClickListener() { public void onClick(DialogInterface dialog, int which) { Log.i(TAG, "Canceling installation"); + setResult(RESULT_CANCELED); finish(); }}) .setMessage(msgId) @@ -189,6 +196,28 @@ public class PackageInstallerActivity extends Activity implements OnCancelListen .setMessage(dlgText1) .setOnCancelListener(this) .create(); + case DLG_ALLOW_SOURCE: + CharSequence appTitle2 = mPm.getApplicationLabel(mSourceInfo); + String dlgText2 = getString(R.string.allow_source_dlg_text, + appTitle2.toString()); + return new AlertDialog.Builder(this) + .setTitle(R.string.allow_source_dlg_title) + .setMessage(dlgText2) + .setNegativeButton(R.string.cancel, new DialogInterface.OnClickListener() { + public void onClick(DialogInterface dialog, int which) { + setResult(RESULT_CANCELED); + finish(); + }}) + .setPositiveButton(R.string.ok, new DialogInterface.OnClickListener() { + public void onClick(DialogInterface dialog, int which) { + SharedPreferences prefs = getSharedPreferences(PREFS_ALLOWED_SOURCES, + Context.MODE_PRIVATE); + prefs.edit().putBoolean(mSourceInfo.packageName, true).apply(); + startInstallConfirm(); + } + }) + .setOnCancelListener(this) + .create(); } return null; } @@ -222,7 +251,7 @@ public class PackageInstallerActivity extends Activity implements OnCancelListen } catch (NameNotFoundException e) { mAppInfo = null; } - if (mAppInfo == null) { + if (mAppInfo == null || getIntent().getBooleanExtra(Intent.EXTRA_ALLOW_REPLACE, false)) { startInstallConfirm(); } else { if(localLOGV) Log.i(TAG, "Replacing existing package:"+ @@ -230,7 +259,14 @@ public class PackageInstallerActivity extends Activity implements OnCancelListen showDialogInner(DLG_REPLACE_APP); } } - + + void setPmResult(int pmResult) { + Intent result = new Intent(); + result.putExtra(Intent.EXTRA_INSTALL_RESULT, pmResult); + setResult(pmResult == PackageManager.INSTALL_SUCCEEDED + ? RESULT_OK : RESULT_FIRST_USER, result); + } + @Override protected void onCreate(Bundle icicle) { super.onCreate(icicle); @@ -244,6 +280,7 @@ public class PackageInstallerActivity extends Activity implements OnCancelListen if(mPkgInfo == null) { Log.w(TAG, "Parse error when parsing manifest. Discontinuing installation"); showDialogInner(DLG_PACKAGE_ERROR); + setPmResult(PackageManager.INSTALL_FAILED_INVALID_APK); return; } @@ -254,8 +291,40 @@ public class PackageInstallerActivity extends Activity implements OnCancelListen PackageUtil.AppSnippet as = PackageUtil.getAppSnippet(this, mPkgInfo.applicationInfo, mPackageURI); PackageUtil.initSnippetForNewApp(this, as, R.id.app_snippet); - //check setting - if(!isInstallingUnknownAppsAllowed()) { + + // Deal with install source. + String callerPackage = getCallingPackage(); + if (callerPackage != null && intent.getBooleanExtra( + Intent.EXTRA_NOT_UNKNOWN_SOURCE, false)) { + try { + mSourceInfo = mPm.getApplicationInfo(callerPackage, 0); + if (mSourceInfo != null) { + if ((mSourceInfo.flags&ApplicationInfo.FLAG_SYSTEM) != 0) { + // System apps don't need to be approved. + initiateInstall(); + return; + } + /* for now this is disabled, since the user would need to + * have enabled the global "unknown sources" setting in the + * first place in order to get here. + SharedPreferences prefs = getSharedPreferences(PREFS_ALLOWED_SOURCES, + Context.MODE_PRIVATE); + if (prefs.getBoolean(mSourceInfo.packageName, false)) { + // User has already allowed this one. + initiateInstall(); + return; + } + //ask user to enable setting first + showDialogInner(DLG_ALLOW_SOURCE); + return; + */ + } + } catch (NameNotFoundException e) { + } + } + + // Check unknown sources. + if (!isInstallingUnknownAppsAllowed()) { //ask user to enable setting first showDialogInner(DLG_UNKNOWN_APPS); return; @@ -280,11 +349,16 @@ public class PackageInstallerActivity extends Activity implements OnCancelListen if (installerPackageName != null) { newIntent.putExtra(Intent.EXTRA_INSTALLER_PACKAGE_NAME, installerPackageName); } + if (getIntent().getBooleanExtra(Intent.EXTRA_RETURN_RESULT, false)) { + newIntent.putExtra(Intent.EXTRA_RETURN_RESULT, true); + newIntent.addFlags(Intent.FLAG_ACTIVITY_FORWARD_RESULT); + } if(localLOGV) Log.i(TAG, "downloaded app uri="+mPackageURI); startActivity(newIntent); finish(); } else if(v == mCancel) { // Cancel and finish + setResult(RESULT_CANCELED); finish(); } } diff --git a/src/com/android/packageinstaller/RemoveReceiver.java b/src/com/android/packageinstaller/RemoveReceiver.java new file mode 100644 index 00000000..7d8064dd --- /dev/null +++ b/src/com/android/packageinstaller/RemoveReceiver.java @@ -0,0 +1,42 @@ +/* +** +** Copyright 2007, 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.packageinstaller; + +import android.content.BroadcastReceiver; +import android.content.Context; +import android.content.Intent; +import android.content.SharedPreferences; +import android.net.Uri; + +public class RemoveReceiver extends BroadcastReceiver { + + @Override + public void onReceive(Context context, Intent intent) { + if (Intent.ACTION_PACKAGE_FULLY_REMOVED.equals(intent.getAction())) { + Uri uri = intent.getData(); + String pkg = uri != null ? uri.getSchemeSpecificPart() : null; + if (pkg != null) { + SharedPreferences prefs = context.getSharedPreferences( + PackageInstallerActivity.PREFS_ALLOWED_SOURCES, + Context.MODE_PRIVATE); + if (prefs.getBoolean(pkg, false)) { + prefs.edit().remove(pkg).apply(); + } + } + } + } +} diff --git a/src/com/android/packageinstaller/UninstallAppProgress.java b/src/com/android/packageinstaller/UninstallAppProgress.java index b4d71476..3dfa80f3 100755 --- a/src/com/android/packageinstaller/UninstallAppProgress.java +++ b/src/com/android/packageinstaller/UninstallAppProgress.java @@ -56,6 +56,16 @@ public class UninstallAppProgress extends Activity implements OnClickListener { public void handleMessage(Message msg) { switch (msg.what) { case UNINSTALL_COMPLETE: + if (getIntent().getBooleanExtra(Intent.EXTRA_RETURN_RESULT, false)) { + Intent result = new Intent(); + result.putExtra(Intent.EXTRA_INSTALL_RESULT, msg.arg1); + setResult(msg.arg1 == PackageManager.DELETE_SUCCEEDED + ? Activity.RESULT_OK : Activity.RESULT_FIRST_USER, + result); + finish(); + return; + } + mResultCode = msg.arg1; final String packageName = (String) msg.obj; diff --git a/src/com/android/packageinstaller/UninstallerActivity.java b/src/com/android/packageinstaller/UninstallerActivity.java index d215894b..5a312973 100755 --- a/src/com/android/packageinstaller/UninstallerActivity.java +++ b/src/com/android/packageinstaller/UninstallerActivity.java @@ -71,6 +71,7 @@ public class UninstallerActivity extends Activity implements OnClickListener, .setNeutralButton(getString(R.string.dlg_ok), new DialogInterface.OnClickListener() { public void onClick(DialogInterface dialog, int which) { + setResult(Activity.RESULT_FIRST_USER); finish(); }}) .create(); @@ -87,6 +88,7 @@ public class UninstallerActivity extends Activity implements OnClickListener, .setNeutralButton(getString(R.string.dlg_ok), new DialogInterface.OnClickListener() { public void onClick(DialogInterface dialog, int which) { + setResult(Activity.RESULT_FIRST_USER); finish(); }}) .create(); @@ -98,6 +100,10 @@ public class UninstallerActivity extends Activity implements OnClickListener, Intent newIntent = new Intent(Intent.ACTION_VIEW); newIntent.putExtra(PackageUtil.INTENT_ATTR_APPLICATION_INFO, mAppInfo); + if (getIntent().getBooleanExtra(Intent.EXTRA_RETURN_RESULT, false)) { + newIntent.putExtra(Intent.EXTRA_RETURN_RESULT, true); + newIntent.addFlags(Intent.FLAG_ACTIVITY_FORWARD_RESULT); + } newIntent.setClass(this, UninstallAppProgress.class); startActivity(newIntent); finish(); |