在卸载应用程序之前请求密码

时间:2014-02-13 13:52:39

标签: android service uninstall

首先,我已经研究了很多关于我的问题,但我找不到合适的解决方案,所以我在这里发布我的查询。希望能够更好地解决这个问题:

我有一个要求,在用户从设置或任何其他应用程序(如MyAppSharer)删除我的应用程序之前,我需要向用户请求密码。我找到了一个解决方案,当用户点击卸载按钮时,我可以成功地调用我的活动。我在这里申请了技巧,并致电服务。在服务中,我运行计时器,每1秒运行一次,在那一秒,它检查运行任务的最顶层活动。这按照预期完美运行。

现在,我的问题是,此活动适用于每个应用程序用户尝试卸载。我需要我调用的活动只应在用户尝试卸载我的应用程序时显示给我的应用程序。

这是我的代码:

public static final String PACKAGE_INSTALLER = "com.android.packageinstaller";
public static final String PACKAGE_INSTALLER_UNINSTALL_ACTIVITY = "com.android.packageinstaller.UninstallerActivity";


alarmTimer.scheduleAtFixedRate(new TimerTask() {
        public void run() {
            mActivityManager = (ActivityManager) getSystemService(Context.ACTIVITY_SERVICE);;
            ComponentName topActivity = mActivityManager.getRunningTasks(1).get(0).topActivity;

            final String packageName = topActivity.getPackageName();
            String className = topActivity.getClassName();

            Log.v(TAG, "packageName:" + packageName);
            Log.v(TAG, "className:" + className);

            if (PACKAGE_INSTALLER.equals(packageName)
                && PACKAGE_INSTALLER_UNINSTALL_ACTIVITY.equals(className)) {

                //Here I need to apply one condition where package name received to be matched with my package name. But I am not sure how to fetch package name of selected application for uninstalling 
                //To Cancel Existing UninstallerActivity and redirect user to home.
                Intent homeIntent = new Intent();
                homeIntent.setAction(Intent.ACTION_MAIN);
                homeIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK
                        | Intent.FLAG_ACTIVITY_CLEAR_TOP | Intent.FLAG_ACTIVITY_SINGLE_TOP);
                homeIntent.addCategory(Intent.CATEGORY_HOME);
                startActivity(homeIntent);

                //To open my activity
                    Intent loginActivity = new Intent(UninstallService.this, Act_Login.class);
                    loginActivity.putExtra(Constants.KEY_IS_FROM_SERVICE, true);
                    loginActivity.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
                    startActivity(loginActivity); 

            }
        }
    }, 0, 1000);

4 个答案:

答案 0 :(得分:5)

您应该尝试以下内容:

1st - 在Manifest文件中声明你的广播接收者,它将收听QUERY_PACKAGE_RESTART:

  <receiver android:name=".UninstallReceiver">
          <intent-filter android:priority="999999">
                <action android:name="android.intent.action.QUERY_PACKAGE_RESTART" />
                <data android:scheme="package" />
          </intent-filter>
     </receiver>

2nd - 你的UnunstallIntentReceiver java类如下:

public class UninstallReceiver extends BroadcastReceiver{

    @Override
    public void onReceive(Context context, Intent intent) {
        // fetching package names from extras
        String[] packageNames = intent.getStringArrayExtra("android.intent.extra.PACKAGES"); 

        if(packageNames!=null){
            for(String packageName: packageNames){
                if(packageName!=null && packageName.equals("application_package")){
                   // start your activity here and ask the user for the password 
                }
            }
        }
    }

    }

请给我一些反馈

希望有助于此。

答案 1 :(得分:1)

如果这是公司要求(如果您想阻止普通用户卸载您的应用,那么,由于Google保护我们免受恶意开发者的攻击,没有机会),您应该创建一个设备管理员应用程序。这样,虽然用户仍然可以删除应用程序,但如果您想要防止意外删除,这是一个额外的步骤。

在删除您的应用之前,如果它已作为设备管理员启用,则用户必须首先以管理员身份停用该应用,并且应用会收到此广播。

在您的XML中,输入

<activity android:name=".app.DeviceAdminSample"
            android:label="@string/activity_sample_device_admin">
    <intent-filter>
        <action android:name="android.intent.action.MAIN" />
        <category android:name="android.intent.category.SAMPLE_CODE" />
    </intent-filter>
</activity>
<receiver android:name=".app.DeviceAdminSample$DeviceAdminSampleReceiver"
        android:label="@string/sample_device_admin"
        android:description="@string/sample_device_admin_description"
        android:permission="android.permission.BIND_DEVICE_ADMIN">
    <meta-data android:name="android.app.device_admin"
            android:resource="@xml/device_admin_sample" />
    <intent-filter>
        <action android:name="android.app.action.DEVICE_ADMIN_ENABLED" />
    </intent-filter>
</receiver>

在接收器中,至少有两种值得注意的方法:

@Override
public CharSequence onDisableRequested(Context context, Intent intent) {
    …
}

@Override
public void onDisabled(Context context, Intent intent) {
    …
}

这样您就知道用户可能会删除您的应用。

设备管理完整指南位于https://developer.android.com/guide/topics/admin/device-admin.html

答案 2 :(得分:1)

如果您拥有root权限,请创建您的应用系统(将您的apk文件从/data移至/system目录)。然后重启设备。重启后,您的应用程序无法被用户删除(非超级用户)。

答案 3 :(得分:1)

我看到的唯一方法是将您自己的卸载程序作为应用程序的一部分(=列出所有应用程序并允许卸载它们的活动)。然后,您的服务可以检查您的应用是否是启动packageinstaller的应用,如果没有重定向用户。

不可能(至少在我测试的Android 4.4上)获取没有root或作为系统应用程序的卸载程序活动数据。这是因为卸载程序不是作为独立任务调用的,而是作为启动任务堆栈上的活动(从设置卸载时的设置应用程序等)。您只能看到调用任务的任务详细信息。

然而,可能存在一些非常脏的可能性,我没有测试到最后:您可以使用隐藏的三个参数版本IThumbnailReceiver注册隐藏的接口ActivityManager.getRunningTasks [1] [ 2]。看起来只需要GET_TASKS权限来获取缩略图(参见[3])。应该可以找出哪个应用程序将从应用程序缩略图中删除... - 但由于此解决方案使用隐藏的API,因此无法保证它将适用于较旧/较新/销售的Android版本。

  1. https://github.com/omnirom/android_frameworks_base/blob/android-4.4/core/java/android/app/IThumbnailReceiver.aidl
  2. https://github.com/omnirom/android_frameworks_base/blob/android-4.4/core/java/android/app/ActivityManager.java#L766
  3. https://github.com/omnirom/android_frameworks_base/blob/android-4.4/services/java/com/android/server/am/ActivityManagerService.java#L6725