USB权限没有提示

USB Permissions without prompt

我的应用程序中有 2 个活动。说 FirstActivitySecondActivityFirstActivity 是 MAIN 和 LAUNCHER activity。 SecondActivity 使用 USB 设备。我希望 USB 权限提示在应用程序的生命周期内只出现一次。

如果只有一个 Activity,清单中的以下几行解决了我的目的:

<activity android:name=".FirstActivity">
    <intent-filter>
        <action android:name="android.intent.action.MAIN" />
        <category android:name="android.intent.category.LAUNCHER" />
        <action android:name="android.hardware.usb.action.USB_DEVICE_ATTACHED" />
    </intent-filter>

    <meta-data
        android:name="android.hardware.usb.action.USB_DEVICE_ATTACHED"
        android:resource="@xml/usb_device_filter" />
</activity>

这是在做以下事情:

  1. 首先启动Activity 只要 USB 设备(在 xml 中提到)已连接且应用程序尚未打开。
  2. USB 设备权限提示仅出现一次。

如何修改它以实现以下目标:

  1. 如果 SecondActivity 已经 运行 并且连接了新的 USB 设备,我必须能够在不重新启动应用程序的情况下使用该设备。所以我写了一个广播接收器,如下所示:

    public class TriggerReceiver extends BroadcastReceiver {
    
        @Override
        public void onReceive(Context context, Intent intent) {
            if (intent.getAction().equals(UsbManager.ACTION_USB_DEVICE_ATTACHED)) { 
            read connected usb devices and register serial port call listener back.
        }
    }    
    

但问题是当 SecondActivity 为 运行 时连接 USB 设备时 FirstActivity 再次重新启动。我该如何避免这种情况?

如果需要,将添加更多信息。将不胜感激任何帮助。

尝试 "remove" 来自 FirstActivity 的意图过滤器 <action android:name="android.hardware.usb.action.USB_DEVICE_ATTACHED" /> 就像 this 问题

更新

FirstActivity 在每个 USB_DEVICE_ATTACHED 上触发(甚至 SecondActivity 是 运行),因为您在 AndroidManifest.xml 文件中为其设置了 <action android:name="android.hardware.usb.action.USB_DEVICE_ATTACHED" /> 过滤器。所以你应该在 SecondActivity 运行 时禁用这个过滤器。你可以通过这种方式做到这一点:

1) 将 AndroidManifest.xml 中的(例如 AliasFirstActivity)添加到您的 FirstActivity 并将 <action android:name="android.hardware.usb.action.USB_DEVICE_ATTACHED" /> 过滤器移动到别名描述(您应该从中删除 <action android:name="android.hardware.usb.action.USB_DEVICE_ATTACHED" /> FirstActivity 描述)像这样:

        <activity-alias
            android:targetActivity=".FirstActivity"
            android:name=".AliasFirstActivity"
            android:label="@string/app_name">
            <intent-filter>
                <action android:name="android.intent.action.MAIN"/>
                <category android:name="android.intent.category.LAUNCHER"/>
            </intent-filter>

            <intent-filter>
                <action android:name="android.hardware.usb.action.USB_DEVICE_ATTACHED" />
            </intent-filter>

            <meta-data android:name="android.hardware.usb.action.USB_DEVICE_ATTACHED"
                       android:resource="@xml/device_filter" />
        </activity-alias>

2) 将此代码添加到 SecondActivity onCreate()(或 onResume()

PackageManager pm = getApplicationContext().getPackageManager();
        ComponentName compName =
                new ComponentName(getPackageName(), getPackageName() + ".AliasFirstActivity");
        pm.setComponentEnabledSetting(
                compName,
                PackageManager.COMPONENT_ENABLED_STATE_DISABLED,
                PackageManager.DONT_KILL_APP);

抑制 FirstActivity 的 Intent 过滤器 USB_DEVICE_ATTACHED。你应该在 SecondActivity 中有这样的东西:

@Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_second);

        triggerReceiver = new TriggerReceiver();

        IntentFilter filter = new IntentFilter();
        filter.addAction(UsbManager.ACTION_USB_DEVICE_ATTACHED);
        registerReceiver(triggerReceiver, filter);

        PackageManager pm = getApplicationContext().getPackageManager();
        ComponentName compName =
                new ComponentName(getPackageName(), getPackageName() + ".AliasFirstActivity");
        pm.setComponentEnabledSetting(
                compName,
                PackageManager.COMPONENT_ENABLED_STATE_DISABLED,
                PackageManager.DONT_KILL_APP);
    }

这应该可以解决您的问题。 3) 如果需要,您可以使用以下代码在 SecondActivityonDestroy()(或 onPause())中为 FirstActivity 恢复 <action android:name="android.hardware.usb.action.USB_DEVICE_ATTACHED" /> 过滤器:

    PackageManager pm = getApplicationContext().getPackageManager();
    ComponentName compName =
            new ComponentName(getPackageName(), getPackageName() + ".AliasFirstActivity");
    pm.setComponentEnabledSetting(
            compName,
            PackageManager.COMPONENT_ENABLED_STATE_ENABLED,
            PackageManager.DONT_KILL_APP);

But the problem is FirstActivity gets relaunched again when usb device is attached while SecondActivity is running. How do I avoid this?

这不难回答。在您的 AndroidManifest.xml 中,您从字面上声明您的 FirstActivity 应该在事件 android.hardware.usb.action.USB_DEVICE_ATTACHED 发生时启动。

如果你只想在SecondActivity中处理这个事件,那么你必须相应地在清单中声明它,例如:

    <activity android:name=".FirstActivity">
        <intent-filter>
            <action android:name="android.intent.action.MAIN" />
            <category android:name="android.intent.category.LAUNCHER" />
        </intent-filter>
    </activity>

    <activity android:name=".SecondActivity" android:launchMode="singleTask">
        <intent-filter>
            <action android:name="android.hardware.usb.action.USB_DEVICE_ATTACHED" />
        </intent-filter>

        <meta-data
            android:name="android.hardware.usb.action.USB_DEVICE_ATTACHED"
            android:resource="@xml/device_filter" />
    </activity>

现在,只要插入 USB 设备,SecondActivity 将只启动。如果 SecondActivity 已经 运行,那么它将不会再次启动(或多次),因为为 [=] 指定的属性 android:launchMode="singleTask" 12=]。如果您有兴趣,可以阅读更多关于不同启动模式的信息 here

由于您在清单中声明 SecondActivity 应在插入 USB 设备时启动,因此 Android 系统将询问您以下问题:

勾选复选框"Use by default for this USB device"后,它不会再询问您。现在,每次插入 USB 设备时,您的 SecondActivity 都会启动,它也会自动接收所需的 USB 权限。

如果这回答了您的问题,请告诉我。

这个答案可能会有帮助: USB device access pop-up suppression?

代码片段:

 public class UsbEventReceiverActivity extends Activity
     {   
        public static final String ACTION_USB_DEVICE_ATTACHED = "com.example.ACTION_USB_DEVICE_ATTACHED";
        @Override
        protected void onCreate(Bundle savedInstanceState)
        {
            super.onCreate(savedInstanceState);
        }

    @Override
    protected void onResume()
    {
        super.onResume();

        Intent intent = getIntent();
        if (intent != null)
        {
            if (intent.getAction().equals(UsbManager.ACTION_USB_DEVICE_ATTACHED))
            {
                Parcelable usbDevice = intent.getParcelableExtra(UsbManager.EXTRA_DEVICE);

                // Create a new intent and put the usb device in as an extra
                Intent broadcastIntent = new Intent(ACTION_USB_DEVICE_ATTACHED);
                broadcastIntent.putExtra(UsbManager.EXTRA_DEVICE, usbDevice);

                // Broadcast this event so we can receive it
                sendBroadcast(broadcastIntent);
            }
        }

        // Close the activity
        finish();
    }
}