在应用程序中以编程方式执行 adb shell dpm 命令产生无法 运行 程序 "adb":错误=13,权限被拒绝
programmatically executing adb shell dpm command within app yields Cannot run program "adb": error=13, Permission denied
我正在尝试执行以下命令:
Process process = Runtime.getRuntime().exec("adb shell dpm set-device-owner com.example.package/.DeviceAdmin", null,null);
并得到以下异常
W/System.err:java.io.IOException: Cannot run program "adb": error=13, Permission denied
W/System.err: at java.lang.ProcessBuilder.start(ProcessBuilder.java:1048)
W/System.err: at java.lang.Runtime.exec(Runtime.java:692)
W/System.err: at java.lang.Runtime.exec(Runtime.java:525)
我正在尝试通过编程执行 "adb shell dpm set-device-owner com.example.package/.DeviceAdmin" 将我的设备设置为所有者。
我一直在参考以下 SO 链接,但我似乎无法解决此错误。
注意:我已经尝试 运行 命令 w/o adb shell 前缀,但是它返回 null 并且没有应用任何更改。
下面的代码执行我的命令。
try {
StringBuffer output = new StringBuffer();
Process process = Runtime.getRuntime().exec("dpm set-device-owner com.example.package/.DeviceAdmin", null,null);
process.waitFor();
BufferedReader reader = new BufferedReader(new InputStreamReader(process.getInputStream()));
String line = "";
while ((line = reader.readLine()) != null) {
output.append(line + "n");
Log.d("OUTPUT = ", output.toString());
}
} catch (Exception e) {
Log.e("LOGINACTIVITY ", "device owner not set");
Log.e("LOGINACTIVITY ", e.toString());
e.printStackTrace();
}
下面是我的 DeviceAdminReceiver 子类
public class DeviceAdmin extends DeviceAdminReceiver {
public ComponentName getComponentName(Context context){
return new ComponentName(context.getApplicationContext(), DeviceAdmin.class);
}
void showToast(Context context, String msg) {
String status = msg;
Toast.makeText(context, status, Toast.LENGTH_SHORT).show();
}
@Override
public void onEnabled(Context context, Intent intent) {
showToast(context, "Enabled");
}
@Override
public void onDisabled(Context context, Intent intent) {
showToast(context,"Disabled");
}
}
我的清单正在注册我的接收者
<application
android:allowBackup="true"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:roundIcon="@mipmap/ic_launcher_round"
android:supportsRtl="true"
android:theme="@style/AppTheme">
<activity android:name=".MainActivity">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<receiver
android:name=".DeviceAdmin"
android:permission="android.permission.BIND_DEVICE_ADMIN">
<meta-data
android:name="android.app.device_admin"
android:resource="@xml/policies"/>
<intent-filter>
<action android:name="android.app.action.DEVICE_ADMIN_ENABLED"/>
</intent-filter>
</receiver>
</application>
已检查设置,设备没有帐户(这是一个 android 设备,没有任何 google 播放服务,也没有 root。)。该应用程序的 minSdkVersion 为 21/targetSdkVersion 为 27。
最终,我希望将设备设置为所有者(没有 NFC),其唯一目的是在不征求用户许可的情况下固定屏幕。(这是一个 POS 应用程序)。如何执行命令以便我可以毫无例外地将设备设置为所有者?
简短的回答是:您的应用无法 运行 ADB 命令。 巨大的 安全漏洞 Android 允许这样做。
如果您想以编程方式将设备设置为设备管理员,请查看 the documentation
上的示例
Intent intent = new Intent(DevicePolicyManager.ACTION_ADD_DEVICE_ADMIN);
intent.putExtra(DevicePolicyManager.EXTRA_DEVICE_ADMIN, mDeviceAdminSample);
intent.putExtra(DevicePolicyManager.EXTRA_ADD_EXPLANATION, getString(R.string.add_admin_extra_app_text));
startActivityForResult(intent, REQUEST_CODE_ENABLE_ADMIN);
I'm trying to set my device as the owner by programmatically
只有两种合法方式可以将应用设置为设备所有者。
a) 设备配置
将设备拆箱后,您可以使用专门准备的 NFC 标签轻触它。 NFC 标签上存储的指令指定的应用程序现在被设置为设备所有者。
b) 亚行
只要满足这些条件就可以使用问题中提到的命令:
- 没有设置设备所有者
- 设备上没有注册帐户
dpm set-device-owner
命令只能是运行来自用户打开的shell(即来自开发机器的ADB)。 它不适用于 Runtime.exec()
打开的 shell。而且,显然,即使您可以从设备到自身进行 ADB,它也会受到相同的限制。
来源:
- https://github.com/aosp-mirror/platform_frameworks_base/blob/2d82493ded10d88cb44e84b90a1b485d3a895d75/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java#L7172
- https://github.com/aosp-mirror/platform_frameworks_base/blob/2d82493ded10d88cb44e84b90a1b485d3a895d75/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java#L12184
Ultimately, I wish to set device as owner(without NFC) for the sole purpose of pinning the screen without asking user permission
您可以使用隐藏系统 API (android.app.StatusBarManager
) 自己隐藏状态栏和导航按钮,并拥有您的应用程序由设备制造商使用平台签名 签名。您需要 android.permission.STATUS_BAR
权限的签名。
我正在尝试执行以下命令:
Process process = Runtime.getRuntime().exec("adb shell dpm set-device-owner com.example.package/.DeviceAdmin", null,null);
并得到以下异常
W/System.err:java.io.IOException: Cannot run program "adb": error=13, Permission denied
W/System.err: at java.lang.ProcessBuilder.start(ProcessBuilder.java:1048)
W/System.err: at java.lang.Runtime.exec(Runtime.java:692)
W/System.err: at java.lang.Runtime.exec(Runtime.java:525)
我正在尝试通过编程执行 "adb shell dpm set-device-owner com.example.package/.DeviceAdmin" 将我的设备设置为所有者。
我一直在参考以下 SO 链接,但我似乎无法解决此错误。
注意:我已经尝试 运行 命令 w/o adb shell 前缀,但是它返回 null 并且没有应用任何更改。
下面的代码执行我的命令。
try {
StringBuffer output = new StringBuffer();
Process process = Runtime.getRuntime().exec("dpm set-device-owner com.example.package/.DeviceAdmin", null,null);
process.waitFor();
BufferedReader reader = new BufferedReader(new InputStreamReader(process.getInputStream()));
String line = "";
while ((line = reader.readLine()) != null) {
output.append(line + "n");
Log.d("OUTPUT = ", output.toString());
}
} catch (Exception e) {
Log.e("LOGINACTIVITY ", "device owner not set");
Log.e("LOGINACTIVITY ", e.toString());
e.printStackTrace();
}
下面是我的 DeviceAdminReceiver 子类
public class DeviceAdmin extends DeviceAdminReceiver {
public ComponentName getComponentName(Context context){
return new ComponentName(context.getApplicationContext(), DeviceAdmin.class);
}
void showToast(Context context, String msg) {
String status = msg;
Toast.makeText(context, status, Toast.LENGTH_SHORT).show();
}
@Override
public void onEnabled(Context context, Intent intent) {
showToast(context, "Enabled");
}
@Override
public void onDisabled(Context context, Intent intent) {
showToast(context,"Disabled");
}
}
我的清单正在注册我的接收者
<application
android:allowBackup="true"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:roundIcon="@mipmap/ic_launcher_round"
android:supportsRtl="true"
android:theme="@style/AppTheme">
<activity android:name=".MainActivity">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<receiver
android:name=".DeviceAdmin"
android:permission="android.permission.BIND_DEVICE_ADMIN">
<meta-data
android:name="android.app.device_admin"
android:resource="@xml/policies"/>
<intent-filter>
<action android:name="android.app.action.DEVICE_ADMIN_ENABLED"/>
</intent-filter>
</receiver>
</application>
已检查设置,设备没有帐户(这是一个 android 设备,没有任何 google 播放服务,也没有 root。)。该应用程序的 minSdkVersion 为 21/targetSdkVersion 为 27。
最终,我希望将设备设置为所有者(没有 NFC),其唯一目的是在不征求用户许可的情况下固定屏幕。(这是一个 POS 应用程序)。如何执行命令以便我可以毫无例外地将设备设置为所有者?
简短的回答是:您的应用无法 运行 ADB 命令。 巨大的 安全漏洞 Android 允许这样做。
如果您想以编程方式将设备设置为设备管理员,请查看 the documentation
上的示例Intent intent = new Intent(DevicePolicyManager.ACTION_ADD_DEVICE_ADMIN);
intent.putExtra(DevicePolicyManager.EXTRA_DEVICE_ADMIN, mDeviceAdminSample);
intent.putExtra(DevicePolicyManager.EXTRA_ADD_EXPLANATION, getString(R.string.add_admin_extra_app_text));
startActivityForResult(intent, REQUEST_CODE_ENABLE_ADMIN);
I'm trying to set my device as the owner by programmatically
只有两种合法方式可以将应用设置为设备所有者。
a) 设备配置
将设备拆箱后,您可以使用专门准备的 NFC 标签轻触它。 NFC 标签上存储的指令指定的应用程序现在被设置为设备所有者。
b) 亚行
只要满足这些条件就可以使用问题中提到的命令:
- 没有设置设备所有者
- 设备上没有注册帐户
dpm set-device-owner
命令只能是运行来自用户打开的shell(即来自开发机器的ADB)。 它不适用于 Runtime.exec()
打开的 shell。而且,显然,即使您可以从设备到自身进行 ADB,它也会受到相同的限制。
来源:
- https://github.com/aosp-mirror/platform_frameworks_base/blob/2d82493ded10d88cb44e84b90a1b485d3a895d75/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java#L7172
- https://github.com/aosp-mirror/platform_frameworks_base/blob/2d82493ded10d88cb44e84b90a1b485d3a895d75/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java#L12184
Ultimately, I wish to set device as owner(without NFC) for the sole purpose of pinning the screen without asking user permission
您可以使用隐藏系统 API (android.app.StatusBarManager
) 自己隐藏状态栏和导航按钮,并拥有您的应用程序由设备制造商使用平台签名 签名。您需要 android.permission.STATUS_BAR
权限的签名。