【React Native】文件翻譯閱讀紀錄 - 指南(Android) - Headless JS

by - 上午9:00

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清單文件的一部分。
<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());
    }


}


You May Also Like

0 意見