So at this moment (september 2022) Android Development Guide says, that there are restrictions on starting activities from the background. There are some exceptions.
In my case (inventory management app with dedicated barcode/RFID reader hardware) I should make use of exception for dedicated devices or use some Device Policy Controller:
The app is a device policy controller running in device owner mode.
Example use cases include fully managed enterprise devices, as well as dedicated devices like digital signage and kiosks.
https://developer.android.com/work/dpc/dedicated-devices
However, for development purposes I have tried the AccessibilityService, as suggested here: link
I have added startActivity when the key 293
is pressed (trigger key on device). In comparison to answer linked above - I have choosen diffrent name for service class. Rename has to be done also in XML file.
src/AccessibilityKeyDetectorService.java
public class AccessibilityKeyDetectorService extends AccessibilityService {
private final String TAG = "AccessKeyDetector";
@Override
public boolean onKeyEvent(KeyEvent event) {
Log.d(TAG,"Key pressed via accessibility is: "+event.getKeyCode());
if (event.getKeyCode() == 293)
{
Intent intent = new Intent(this, MainActivity.class);
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK); // this is required to open Activity from service
startActivity(intent);
}
return super.onKeyEvent(event);
}
@Override
protected void onServiceConnected() {
Log.i(TAG,"Service connected");
}
@Override
public void onAccessibilityEvent(AccessibilityEvent event) {
}
@Override
public void onInterrupt() {
}
}
My res/xml/accessibility_service.xml:
<accessibility-service
xmlns:android="http://schemas.android.com/apk/res/android"
android:accessibilityFlags="flagRequestFilterKeyEvents"
android:accessibilityEventTypes="typeAllMask"
android:accessibilityFeedbackType="feedbackAllMask"
android:notificationTimeout="100"
android:canRetrieveWindowContent="true"
android:settingsActivity=""
android:packageNames="pl.globalsystem.rflow"
android:canRequestFilterKeyEvents="true" />
And my manifest entry:
<service android:name=".services.AccessibilityKeyDetectorService"
android:permission="android.permission.BIND_ACCESSIBILITY_SERVICE"
android:exported="true">
<intent-filter>
<action android:name="android.accessibilityservice.AccessibilityService" />
</intent-filter>
<meta-data android:name="android.accessibilityservice"
android:resource="@xml/accessibility_service" />
</service>
And my MainActivity method for accessibility permissions:
public boolean checkAccessibilityPermission() {
int accessEnabled=0;
try {
accessEnabled = Settings.Secure.getInt(this.getContentResolver(), Settings.Secure.ACCESSIBILITY_ENABLED);
} catch (Settings.SettingNotFoundException e) {
e.printStackTrace();
}
if (accessEnabled==0) {
/** if not construct intent to request permission */
Intent intent = new Intent(Settings.ACTION_ACCESSIBILITY_SETTINGS);
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
/** request permission via start activity for result */
startActivity(intent);
return false;
} else {
return true;
}
}