简体   繁体   English

以编程方式设置 Always-On VPN,“管理员不拥有配置文件”

[英]Programatically setting Always-On VPN, "Admin does not own the profile"

I'm trying to figure out how to configure my VPN application to toggle the Always-On flag from within the application with a toggle.我正在尝试弄清楚如何配置我的 VPN 应用程序以通过切换从应用程序内部切换 Always-On 标志。

I'm aware of我知道

DevicePolicyManager#setAlwaysOnVpnPackage

However, it's not very clear how to use this function.但是,目前还不是很清楚如何使用此功能。 I have tried the following:我尝试了以下方法:

Admin.java管理程序

public class Admin extends DeviceAdminReceiver {
    @Override
    public void onEnabled(@NonNull Context context, @NonNull Intent intent) {
        super.onEnabled(context, intent);
    }
}

AdvancedSettings.java高级设置.java

public class AdvancedSettings extends AppCompatActivity 
        implements View.OnClickListener {

    private ComponentName componentName;
    private DevicePolicyManager devicePolicyManager;
    private boolean alwaysOnConfiguredValue;

    private static final int ALWAYS_ON_REQUEST_CODE = 11;

    @Override
    public void onCreate(Bundle savedInstanceState){
        super.onCreate(savedInstanceState);
        setContentView(R.layout.settings_advanced);

        Button button = findViewById(R.id.toggleAlwaysOnButton);
        button.setOnClickListener(this);

        devicePolicyManager = (DevicePolicyManager) this
                .getSystemService(Context.DEVICE_POLICY_SERVICE);
        componentName = new ComponentName(
                this.getApplicationContext(), Admin.class);
    }

    @Override
    public void onClick(View v) {
        if (v.getId() == R.id.toggleAlwaysOnButton) {
            this.setAlwaysOn(true);
        }
    }

    /**
     * Handle the Activity Result.
     */
    @Override
    protected void onActivityResult(
        int requestCode, int resultCode, @Nullable Intent data
    ) {
        if (requestCode == ALWAYS_ON_REQUEST_CODE) {
            if (resultCode == Activity.RESULT_OK) {
                finalizeAlwaysOnToggle();
            } else {
                Log.w(
                    "Invalid result code " + resultCode
                );
            }
        }

        super.onActivityResult(requestCode, resultCode, data);
    }

    /**
     * Start the process of enabling "Always On" for the VPN.
     *
     * @param boolean value
     */
    private void setAlwaysOn(boolean value) {
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
            alwaysOnConfiguredValue = value;

            if (devicePolicyManager.isAdminActive(componentName)) {
                finalizeAlwaysOnToggle();
                return;
            }

            requestAdminAccess();
        } else {
            Toas.makeText(this, "Not supported", Toast.LENGTH_LONG).show();
        }
    }

    /**
     * Request Admin Access for this application 
     * if it has not already been done.
     */
    private void requestAdminAccess() {
        Intent intent = new Intent(DevicePolicyManager.ACTION_ADD_DEVICE_ADMIN);
        intent.putExtra(DevicePolicyManager.EXTRA_DEVICE_ADMIN, componentName);
        intent.putExtra(
            DevicePolicyManager.EXTRA_ADD_EXPLANATION,
            "This is required to modify the Always-On Feature from within the Test Application."
        );
        this.startActivityForResult(intent, ALWAYS_ON_REQUEST_CODE);
    }

    /**
     * Finalize setting the always on toggle after the Admin Access 
     * has been granted for this application.
     */
    private void finalizeAlwaysOnToggle() {
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
            try {
                if (devicePolicyManager.isAdminActive(componentName)) {
                    devicePolicyManager.setAlwaysOnVpnPackage(
                        componentName, (alwaysOnConfiguredValue) ? "com.myapp" : null, true
                    );
                } else {
                    Log.e(
                        "Device Policy Manager Admin is not yet active while " + 
                        "trying to finalize changes to AlwaysOnToggle."
                    );
                }
            } catch (PackageManager.NameNotFoundException e) {
                Log.e("Unable to set always on vpn due to NameNotFound Exception.", e);
            }
        }
    }
}

It processes the request for adding the Device Admin just fine, however after that has completed, when it runs finalizeAlwaysOnToggle() , during the call to devicePolicyManager.setAlwaysOnVpnPackage I receive the following error:它处理添加设备管理员的请求就好了,但是在完成之后,当它运行finalizeAlwaysOnToggle() ,在调用devicePolicyManager.setAlwaysOnVpnPackage期间我收到以下错误:

E/AndroidRuntime: FATAL EXCEPTION: main
    Process: com.myapp, PID: 30778
    java.lang.RuntimeException: Failure delivering result ResultInfo{who=null, request=11, result=-1, data=null} to activity {com.myapp/com.myapp.ui.settings.AdvancedSettings}: java.lang.SecurityException: Admin ComponentInfo{com.myapp/com.myapp.provider.Admin} does not own the profile

You have to differentiate between "Device Admin", "Device Owner" and "Profile Owner".您必须区分“设备管理员”、“设备所有者”和“配置文件所有者”。 As it is stated in the docs you need to be one of the latter twos to be able to call setAlwaysOnVpnPackage :正如文档中所述,您需要成为后两者之一才能调用setAlwaysOnVpnPackage

Called by a device or profile owner to configure an always-on VPN connection through a specific application for the current user.由设备或配置文件所有者调用以通过特定应用程序为当前用户配置始终在线的 VPN 连接。 This connection is automatically granted and persisted after a reboot.重新启动后会自动授予并保留此连接。

( https://developer.android.com/reference/android/app/admin/DevicePolicyManager.html#setAlwaysOnVpnPackage(android.content.ComponentName,%2520java.lang.String,%2520boolean) ) ( https://developer.android.com/reference/android/app/admin/DevicePolicyManager.html#setAlwaysOnVpnPackage(android.content.ComponentName,%2520java.lang.String,%2520boolean) )

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM