【React Native】文件翻譯閱讀紀錄 - 指南(Android) - Headless JS
Facebook Open Source React Native |
Headless JS
Headless JS 是一種在應用程序處於後台時在JavaScript中運行任務的方法。例如,它可用於同步新數據,處理推送通知或播放音樂。
The JS API
任務是在AppRegistry上註冊的簡單異步函數,類似於註冊React應用程序:
AppRegistry.registerHeadlessTask('SomeTaskName', () => require('SomeTaskName'));
然後, 在
SomeTaskName.js
:module.exports = async (taskData) => {
// do stuff
};
只要不觸及UI,您就可以在任務中執行任何操作:網絡請求,計時器等。一旦您的任務完成(即承諾得到解決),React Native將進入“暫停”模式(除非有其他任務在運行,或者有一個前台應用程序)。
The Java API
是的,這仍然需要一些本機代碼,但它非常薄。您需要擴展 HeadlessJsTaskService 並覆蓋 getTaskConfig,例如:
public class MyTaskService extends HeadlessJsTaskService {
@Override
protected @Nullable HeadlessJsTaskConfig getTaskConfig(Intent intent) {
Bundle extras = intent.getExtras();
if (extras != null) {
return new HeadlessJsTaskConfig(
"SomeTaskName",
Arguments.fromBundle(extras),
5000, // timeout for the task
false // optional: defines whether or not the task is allowed in foreground. Default is false
);
}
return null;
}
}
然後將服務添加到 AndroidManifest.xml 文件中:
<service android:name="com.example.MyTaskService" />
現在,無論何時開始提供服務,例如作為一個週期性任務或響應某些系統事件/廣播,JS將啟動,運行您的任務,然後旋轉。
例如:
Intent service = new Intent(getApplicationContext(), MyTaskService.class);
Bundle bundle = new Bundle();
bundle.putString("foo", "bar");
service.putExtras(bundle);
getApplicationContext().startService(service);
注意事項
- 默認情況下,如果您嘗試在應用程序位於前台時運行任務,您的應用程序將崩潰。這是為了防止開發人員通過在任務中完成大量工作並減慢UI來自我攻擊。您可以傳遞第四個布爾參數來控制此行為。
- 如果從 BroadcastReceiver 啟動服務,請確保在從 onReceive() 返回之前調用 HeadlessJsTaskService.acquireWakeLockNow()。
示例用法
可以從Java API啟動服務。首先,您需要確定何時應該啟動服務並相應地實施解決方案。這是一個對網絡連接變化做出反應的簡單示例。
以下行顯示了用於註冊廣播接收器的Android清單文件的一部分。
以下行顯示了用於註冊廣播接收器的Android清單文件的一部分。
<receiver android:name=".NetworkChangeReceiver" >
<intent-filter>
<action android:name="android.net.conn.CONNECTIVITY_CHANGE" />
</intent-filter>
</receiver>
然後,廣播接收器處理在onReceive函數中廣播的意圖。這是一個檢查您的應用是否在前台的好地方。如果應用程序不在前台,我們可以準備啟動的意圖,沒有使用putExtra捆綁的信息或附加信息(請記住,bundle只能處理parcelable值)。最後,服務開始並獲得喚醒鎖。
public class NetworkChangeReceiver extends BroadcastReceiver {
@Override
public void onReceive(final Context context, final Intent intent) {
/**
This part will be called everytime network connection is changed
e.g. Connected -> Not Connected
**/
if (!isAppOnForeground((context))) {
/**
We will start our service and send extra info about
network connections
**/
boolean hasInternet = isNetworkAvailable(context);
Intent serviceIntent = new Intent(context, MyTaskService.class);
serviceIntent.putExtra("hasInternet", hasInternet);
context.startService(serviceIntent);
HeadlessJsTaskService.acquireWakeLockNow(context);
}
}
private boolean isAppOnForeground(Context context) {
/**
We need to check if app is in foreground otherwise the app will crash.
http://stackoverflow.com/questions/8489993/check-android-application-is-in-foreground-or-not
**/
ActivityManager activityManager = (ActivityManager) context.getSystemService(Context.ACTIVITY_SERVICE);
List<ActivityManager.RunningAppProcessInfo> appProcesses =
activityManager.getRunningAppProcesses();
if (appProcesses == null) {
return false;
}
final String packageName = context.getPackageName();
for (ActivityManager.RunningAppProcessInfo appProcess : appProcesses) {
if (appProcess.importance ==
ActivityManager.RunningAppProcessInfo.IMPORTANCE_FOREGROUND &&
appProcess.processName.equals(packageName)) {
return true;
}
}
return false;
}
public static boolean isNetworkAvailable(Context context) {
ConnectivityManager cm = (ConnectivityManager)
context.getSystemService(Context.CONNECTIVITY_SERVICE);
NetworkInfo netInfo = cm.getActiveNetworkInfo();
return (netInfo != null && netInfo.isConnected());
}
}
0 意見