You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Android Kiosk模式下Delphi设备所有者应用无法启动第三方应用求助

问题:Android Kiosk模式下无法从Delphi应用启动第三方应用

我基于Embarcadero的Advanced Android Kiosk Mode模板开发Kiosk应用,原本模板可启动设备Wi-Fi设置页面,现在想替换成启动另一应用。参考相关方法编写了启动代码,但遇到如下问题:

我的启动代码

procedure TDashboard.StartSA7;
var
  Intent: JIntent;
begin

  FKioskApp.ActiveOtherActivity := True;

  Intent := TJIntent.Create;

  Intent := MainActivity.getPackageManager.getLaunchIntentForPackage(StringToJString('com.embarcadero.SA7mp'));
  Intent.addFlags(TJIntent.JavaClass.FLAG_ACTIVITY_NEW_TASK); // <-- 可能可选

  if MainActivity.getPackageManager.queryIntentActivities(Intent, TJPackageManager.JavaClass.MATCH_ALL).size > 0 then
    begin
      TAndroidHelper.Context.startActivity(Intent);
      Label2.Text := 'OK!!';
    end
  else
    begin
      Label2.Text := 'NO!!!';
    end;
end;

问题现象

  • 主Kiosk应用未设为device-owner(非Kiosk模式)时,能正常启动com.embarcadero.SA7mp应用;
  • 设置为device-owner进入Kiosk模式后,无法启动该应用。

对比:原启动Wi-Fi设置的代码(Kiosk模式下正常运行)

procedure TDashboard.GoToSettings;
var
  LIntent: JIntent;
begin
  FKioskApp.ActiveOtherActivity := True;
  // 在Kiosk模式下打开其他应用前,设置ActiveOtherActivity标记很重要

  LIntent := TJIntent.JavaClass.init(TJSettings.JavaClass.ACTION_WIFI_SETTINGS);
  LIntent.addFlags(TJIntent.JavaClass.FLAG_ACTIVITY_NEW_TASK); // <-- 可能可选
  TAndroidHelper.Context.startActivity(LIntent);
end;

环境:目标设备运行Android 11,使用Delphi 12.2补丁2。


解决方案

这是Android Kiosk模式(设备所有者模式)的权限限制导致的——默认情况下,设备所有者应用只能启动系统设置类特定Activity,第三方应用不在允许列表内。解决需完成以下步骤:

1. 在设备所有者策略中添加允许的应用包名

通过DevicePolicyManager将目标应用包名加入允许应用列表,Delphi实现代码如下:

uses
  Androidapi.JNI.App, Androidapi.JNI.Os, Androidapi.Helpers;

procedure AllowThirdPartyApp(const APackageName: string);
var
  DPM: JDevicePolicyManager;
  AdminComponent: JComponentName;
  AllowedPackages: JList;
begin
  // 获取DevicePolicyManager实例
  DPM := TJDevicePolicyManager.Wrap(
    TAndroidHelper.Context.getSystemService(TJContext.JavaClass.DEVICE_POLICY_SERVICE));
  // 替换为你的设备所有者组件名(通常是主Activity的ComponentName)
  AdminComponent := TJComponentName.JavaClass.init(TAndroidHelper.Context.getPackageName(),
    StringToJString('com.embarcadero.kiosk.DeviceAdminReceiver'));

  // 获取当前允许的应用列表
  AllowedPackages := DPM.getAllowedPackages(AdminComponent);
  if AllowedPackages = nil then
    AllowedPackages := TJArrayList.JavaClass.init;

  // 添加目标应用包名(若尚未存在)
  if not AllowedPackages.contains(StringToJString(APackageName)) then
  begin
    AllowedPackages.add(StringToJString(APackageName));
    // 更新允许列表
    DPM.setAllowedPackages(AdminComponent, AllowedPackages);
  end;
end;

注意:替换代码中的com.embarcadero.kiosk.DeviceAdminReceiver为你实际的设备管理员接收器类名,Kiosk模板中默认已存在该类。

2. 调整启动Intent的方式

确保ActiveOtherActivity标记已设置(你已完成此步骤),建议使用MainActivity.startActivity而非TAndroidHelper.Context.startActivity,Kiosk模式下主Activity的上下文权限更适配:

procedure TDashboard.StartSA7;
var
  Intent: JIntent;
  PM: JPackageManager;
begin
  FKioskApp.ActiveOtherActivity := True;

  PM := MainActivity.getPackageManager;
  Intent := PM.getLaunchIntentForPackage(StringToJString('com.embarcadero.SA7mp'));

  if Assigned(Intent) then
  begin
    Intent.addFlags(TJIntent.JavaClass.FLAG_ACTIVITY_NEW_TASK);
    // 先确保目标应用已被允许
    AllowThirdPartyApp('com.embarcadero.SA7mp');
    // 使用MainActivity启动
    MainActivity.startActivity(Intent);
    Label2.Text := 'OK!!';
  end
  else
  begin
    Label2.Text := 'NO!!!';
  end;
end;

3. 验证设备所有者配置

若问题仍存在,检查以下配置:

  • 确认应用已通过ADB命令或其他方式设置为设备所有者;
  • 在设备安全设置中,确认你的应用被标记为设备所有者;
  • Android 11对设备所有者权限控制更严格,确保应用拥有BIND_DEVICE_ADMIN权限(Kiosk模板默认已在AndroidManifest.xml中配置)。

内容的提问来源于stack exchange,提问作者steve.b

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.15 18:47:31