I've written a native android module in React Native that consists of a broadcast receiver to listen to ACTION_SCREEN_OFF, ACTION_SCREEN_ON and ACTION_USER_PRESENT. I've created a headless service that is called by the receiver which executes the JS code, but the receiver is not being triggered to begin with.
phoneScreenOnOffModule.java:
package com.tracker;
import com.facebook.react.bridge.NativeModule;
import com.facebook.react.bridge.ReactApplicationContext;
import com.facebook.react.bridge.ReactContext;
import com.facebook.react.bridge.ReactContextBaseJavaModule;
import com.facebook.react.HeadlessJsTaskService;
import com.facebook.react.bridge.ReactMethod;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.util.Log;
import java.util.Map;
import java.util.HashMap;
public class phoneScreenOnOffModule extends ReactContextBaseJavaModule {
private ReactApplicationContext reactContext;
phoneScreenOnOffModule(ReactApplicationContext context) {
super(context);
reactContext=context;
registerBroadcastReceiver();
}
@Override
public String getName() {
return "phoneScreenOnOffModule";
}
private final BroadcastReceiver phoneScreenReceiver = new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
if (intent.getAction().equals(Intent.ACTION_SCREEN_OFF)) {
Log.d("StackOverflow", "screen_off");
} else if (intent.getAction().equals(Intent.ACTION_SCREEN_ON)) {
Log.d("StackOverflow", "screen_on");
} else if (intent.getAction().equals(Intent.ACTION_USER_PRESENT)) {
Log.d("StackOverflow", "user_present");
}
Intent serviceIntent = new Intent(context, phoneScreenService.class);
context.startService(serviceIntent);
HeadlessJsTaskService.acquireWakeLockNow(context);
}
};
private void registerBroadcastReceiver() {
IntentFilter filter = new IntentFilter();
filter.addAction(Intent.ACTION_SCREEN_OFF);
filter.addAction(Intent.ACTION_SCREEN_ON);
filter.addAction(Intent.ACTION_USER_PRESENT);
reactContext.registerReceiver(phoneScreenReceiver, filter);
}
}
phoneScreenService.java:
package com.tracker;
import android.content.Intent;
import android.os.Bundle;
import com.facebook.react.HeadlessJsTaskService;
import com.facebook.react.bridge.Arguments;
import com.facebook.react.jstasks.HeadlessJsTaskConfig;
import javax.annotation.Nullable;
public class phoneScreenService extends HeadlessJsTaskService {
@Override
protected @Nullable HeadlessJsTaskConfig getTaskConfig(Intent intent) {
Bundle extras = intent.getExtras();
if (extras != null) {
return new HeadlessJsTaskConfig(
"phoneScreen",
Arguments.fromBundle(extras),
5000, // timeout for the task
true // optional: defines whether or not the task is allowed in foreground. Default is false
);
}
return null;
}
}
Manifest:
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.tracker">
<uses-permission android:name="android.permission.INTERNET" />
<application
android:name=".MainApplication"
android:label="@string/app_name"
android:icon="@mipmap/ic_launcher"
android:roundIcon="@mipmap/ic_launcher_round"
android:allowBackup="false"
android:theme="@style/AppTheme">
<service android:name="com.tracker.phoneScreenService" />
<receiver
android:name="com.tracker.phoneScreenReceiver"
android:enabled="true"
android:exported="true"
android:permission="android.permission.RECEIVE_BOOT_COMPLETED"
android:label="phoneScreenReceiver">
<intent-filter>
<action android:name="android.intent.action.BOOT_COMPLETED" />
<action android:name="android.intent.action.SCREEN_OFF" />
<action android:name="android.intent.action.SCREEN_ON" />
<action android:name="android.intent.action.USER_PRESENT" />
<category android:name="android.intent.category.HOME" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</receiver>
<activity
android:name=".MainActivity"
android:label="@string/app_name"
android:configChanges="keyboard|keyboardHidden|orientation|screenSize|uiMode"
android:launchMode="singleTask"
android:windowSoftInputMode="adjustResize">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
</application>
</manifest>
Relevant JS code:
import { AppRegistry } from 'react-native';
const phoneScreen = async (data) => {
console.log("works", data);
}
AppRegistry.registerHeadlessTask('phoneScreen', () => phoneScreen);