From fc4ddc0f304b9a38b8a7d16936e58e64e57b9ad4 Mon Sep 17 00:00:00 2001 From: Alfonso Lasa Date: Thu, 19 May 2022 13:55:10 +0200 Subject: [PATCH 01/11] docs: update headless-js-android --- docs/headless-js-android.md | 231 +++++++++++++++++- .../version-0.68/headless-js-android.md | 231 +++++++++++++++++- 2 files changed, 436 insertions(+), 26 deletions(-) diff --git a/docs/headless-js-android.md b/docs/headless-js-android.md index 8199ec28ec5..60ad8783037 100644 --- a/docs/headless-js-android.md +++ b/docs/headless-js-android.md @@ -3,6 +3,9 @@ id: headless-js-android title: Headless JS --- +import Tabs from '@theme/Tabs'; import TabItem from '@theme/TabItem'; +import constants from '@site/core/TabsConstants'; + Headless JS is a way to run tasks in JavaScript while your app is in the background. It can be used, for example, to sync fresh data, handle push notifications, or play music. ## The JS API @@ -26,12 +29,16 @@ module.exports = async (taskData) => { You can do anything in your task such as network requests, timers and so on, as long as it doesn't touch UI. Once your task completes (i.e. the promise is resolved), React Native will go into "paused" mode (unless there are other tasks running, or there is a foreground app). -## The Java API +## The Native API Yes, this does still require some native code, but it's pretty thin. You need to extend `HeadlessJsTaskService` and override `getTaskConfig`, e.g.: + + + ```java package com.your_application_name; + import android.content.Intent; import android.os.Bundle; import com.facebook.react.HeadlessJsTaskService; @@ -57,6 +64,39 @@ public class MyTaskService extends HeadlessJsTaskService { } ``` + + + +```kotlin +package com.your_application_name; + +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 + +class MyTaskService : HeadlessJsTaskService() { + override fun getTaskConfig(intent: Intent): HeadlessJsTaskConfig? { + val extras: Bundle? = intent.extras + if (extras != null) { + return 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 + } +} + +``` + + + + Then add the service to your `AndroidManifest.xml` file: ``` @@ -67,6 +107,9 @@ Now, whenever you [start your service][0], e.g. as a periodic task or in respons Example: + + + ```java Intent service = new Intent(getApplicationContext(), MyTaskService.class); Bundle bundle = new Bundle(); @@ -77,12 +120,32 @@ service.putExtras(bundle); getApplicationContext().startService(service); ``` + + + +```kotlin +val service = Intent(getApplicationContext(), MyTaskService::class.java) +val bundle = Bundle() + +bundle.putString("foo", "bar") + +service.putExtras(bundle) + +getApplicationContext().startService(service) +``` + + + + ## Retries By default, the headless JS task will not perform any retries. In order to do so, you need to create a `HeadlessJsRetryPolicy` and throw a specific `Error`. `LinearCountingRetryPolicy` is an implementation of `HeadlessJsRetryPolicy` that allows you to specify a maximum number of retries with a fixed delay between each attempt. If that does not suit your needs then you can implement your own `HeadlessJsRetryPolicy`. These policies can be passed as an extra argument to the `HeadlessJsTaskConfig` constructor, e.g. + + + ```java HeadlessJsRetryPolicy retryPolicy = new LinearCountingRetryPolicy( 3, // Max number of retry attempts @@ -98,6 +161,22 @@ return new HeadlessJsTaskConfig( ); ``` + + + +```kotlin +val retryPolicy: HeadlessJsTaskRetryPolicy = + LinearCountingRetryPolicy( + 3, // Max number of retry attempts + 1000 // Delay between each retry attempt + ) + +return HeadlessJsTaskConfig('SomeTaskName', Arguments.fromBundle(extras), 5000, false, retryPolicy) +``` + + + + A retry attempt will only be made when a specific `Error` is thrown. Inside a headless JS task, you can import the error and throw it when a retry attempt is required. Example: @@ -137,20 +216,35 @@ Following lines shows part of Android manifest file for registering broadcast re Broadcast receiver then handles intent that was broadcasted in onReceive function. This is a great place to check whether your app is on foreground or not. If app is not on foreground we can prepare our intent to be started, with no information or additional information bundled using `putExtra` (keep in mind bundle can handle only parcelable values). In the end service is started and wakelock is acquired. + + + ```java +import android.app.ActivityManager; +import android.content.BroadcastReceiver; +import android.content.Context; +import android.content.Intent; +import android.net.ConnectivityManager; +import android.net.Network; +import android.net.NetworkCapabilities; +import android.net.NetworkInfo; +import android.os.Build; + +import com.facebook.react.HeadlessJsTaskService; + public class NetworkChangeReceiver extends BroadcastReceiver { @Override public void onReceive(final Context context, final Intent intent) { /** - This part will be called every time network connection is changed - e.g. Connected -> Not Connected - **/ + This part will be called every time network connection is changed + e.g. Connected -> Not Connected + **/ if (!isAppOnForeground((context))) { /** - We will start our service and send extra info about - network connections - **/ + 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); @@ -161,20 +255,20 @@ public class NetworkChangeReceiver extends BroadcastReceiver { private boolean isAppOnForeground(Context context) { /** - We need to check if app is in foreground otherwise the app will crash. + 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 appProcesses = - activityManager.getRunningAppProcesses(); + 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)) { + ActivityManager.RunningAppProcessInfo.IMPORTANCE_FOREGROUND && + appProcess.processName.equals(packageName)) { return true; } } @@ -183,13 +277,124 @@ public class NetworkChangeReceiver extends BroadcastReceiver { public static boolean isNetworkAvailable(Context context) { ConnectivityManager cm = (ConnectivityManager) - context.getSystemService(Context.CONNECTIVITY_SERVICE); + context.getSystemService(Context.CONNECTIVITY_SERVICE); + + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) { + Network networkCapabilities = cm.getActiveNetwork(); + + if(networkCapabilities == null) { + return false; + } + + NetworkCapabilities actNw = cm.getNetworkCapabilities(networkCapabilities); + + if(actNw == null) { + return false; + } + + if(actNw.hasTransport(NetworkCapabilities.TRANSPORT_WIFI) || actNw.hasTransport(NetworkCapabilities.TRANSPORT_CELLULAR) || actNw.hasTransport(NetworkCapabilities.TRANSPORT_ETHERNET)) { + return true; + } + + return false; + } + + // deprecated in API level 28 NetworkInfo netInfo = cm.getActiveNetworkInfo(); return (netInfo != null && netInfo.isConnected()); } +} +``` + + + +```kotlin +import android.app.ActivityManager +import android.app.ActivityManager.RunningAppProcessInfo +import android.content.BroadcastReceiver +import android.content.Context +import android.content.Intent +import android.net.ConnectivityManager +import android.net.NetworkCapabilities +import android.os.Build +import com.facebook.react.HeadlessJsTaskService + +class NetworkChangeReceiver : BroadcastReceiver() { + override fun onReceive(context: Context, intent: Intent?) { + /** + * This part will be called every time network connection is changed e.g. Connected -> Not + * Connected + */ + if (!isAppOnForeground(context)) { + /** We will start our service and send extra info about network connections */ + val hasInternet = isNetworkAvailable(context) + val serviceIntent = Intent(context, MyTaskService::class.java) + serviceIntent.putExtra("hasInternet", hasInternet) + context.startService(serviceIntent) + HeadlessJsTaskService.acquireWakeLockNow(context) + } + } + private fun isAppOnForeground(context: Context): Boolean { + /** + * 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 + */ + val activityManager = context.getSystemService(Context.ACTIVITY_SERVICE) as ActivityManager + val appProcesses = activityManager.runningAppProcesses ?: return false + val packageName: String = context.getPackageName() + for (appProcess in appProcesses) { + if (appProcess.importance == RunningAppProcessInfo.IMPORTANCE_FOREGROUND && + appProcess.processName == packageName + ) { + return true + } + } + return false + } + + companion object { + fun isNetworkAvailable(context: Context): Boolean { + val cm = context.getSystemService(Context.CONNECTIVITY_SERVICE) as ConnectivityManager + var result = false + + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) { + val networkCapabilities = cm.activeNetwork ?: return false + + val actNw = cm.getNetworkCapabilities(networkCapabilities) ?: return false + + result = + when { + actNw.hasTransport(NetworkCapabilities.TRANSPORT_WIFI) -> true + actNw.hasTransport(NetworkCapabilities.TRANSPORT_CELLULAR) -> true + actNw.hasTransport(NetworkCapabilities.TRANSPORT_ETHERNET) -> true + else -> false + } + + return result + } else { + cm.run { + // deprecated in API level 28 + cm.activeNetworkInfo?.run { + result = + when (type) { + ConnectivityManager.TYPE_WIFI -> true + ConnectivityManager.TYPE_MOBILE -> true + ConnectivityManager.TYPE_ETHERNET -> true + else -> false + } + } + } + } + return result + } + } } + ``` + + + [0]: https://developer.android.com/reference/android/content/Context.html#startService(android.content.Intent) diff --git a/website/versioned_docs/version-0.68/headless-js-android.md b/website/versioned_docs/version-0.68/headless-js-android.md index 8199ec28ec5..60ad8783037 100644 --- a/website/versioned_docs/version-0.68/headless-js-android.md +++ b/website/versioned_docs/version-0.68/headless-js-android.md @@ -3,6 +3,9 @@ id: headless-js-android title: Headless JS --- +import Tabs from '@theme/Tabs'; import TabItem from '@theme/TabItem'; +import constants from '@site/core/TabsConstants'; + Headless JS is a way to run tasks in JavaScript while your app is in the background. It can be used, for example, to sync fresh data, handle push notifications, or play music. ## The JS API @@ -26,12 +29,16 @@ module.exports = async (taskData) => { You can do anything in your task such as network requests, timers and so on, as long as it doesn't touch UI. Once your task completes (i.e. the promise is resolved), React Native will go into "paused" mode (unless there are other tasks running, or there is a foreground app). -## The Java API +## The Native API Yes, this does still require some native code, but it's pretty thin. You need to extend `HeadlessJsTaskService` and override `getTaskConfig`, e.g.: + + + ```java package com.your_application_name; + import android.content.Intent; import android.os.Bundle; import com.facebook.react.HeadlessJsTaskService; @@ -57,6 +64,39 @@ public class MyTaskService extends HeadlessJsTaskService { } ``` + + + +```kotlin +package com.your_application_name; + +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 + +class MyTaskService : HeadlessJsTaskService() { + override fun getTaskConfig(intent: Intent): HeadlessJsTaskConfig? { + val extras: Bundle? = intent.extras + if (extras != null) { + return 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 + } +} + +``` + + + + Then add the service to your `AndroidManifest.xml` file: ``` @@ -67,6 +107,9 @@ Now, whenever you [start your service][0], e.g. as a periodic task or in respons Example: + + + ```java Intent service = new Intent(getApplicationContext(), MyTaskService.class); Bundle bundle = new Bundle(); @@ -77,12 +120,32 @@ service.putExtras(bundle); getApplicationContext().startService(service); ``` + + + +```kotlin +val service = Intent(getApplicationContext(), MyTaskService::class.java) +val bundle = Bundle() + +bundle.putString("foo", "bar") + +service.putExtras(bundle) + +getApplicationContext().startService(service) +``` + + + + ## Retries By default, the headless JS task will not perform any retries. In order to do so, you need to create a `HeadlessJsRetryPolicy` and throw a specific `Error`. `LinearCountingRetryPolicy` is an implementation of `HeadlessJsRetryPolicy` that allows you to specify a maximum number of retries with a fixed delay between each attempt. If that does not suit your needs then you can implement your own `HeadlessJsRetryPolicy`. These policies can be passed as an extra argument to the `HeadlessJsTaskConfig` constructor, e.g. + + + ```java HeadlessJsRetryPolicy retryPolicy = new LinearCountingRetryPolicy( 3, // Max number of retry attempts @@ -98,6 +161,22 @@ return new HeadlessJsTaskConfig( ); ``` + + + +```kotlin +val retryPolicy: HeadlessJsTaskRetryPolicy = + LinearCountingRetryPolicy( + 3, // Max number of retry attempts + 1000 // Delay between each retry attempt + ) + +return HeadlessJsTaskConfig('SomeTaskName', Arguments.fromBundle(extras), 5000, false, retryPolicy) +``` + + + + A retry attempt will only be made when a specific `Error` is thrown. Inside a headless JS task, you can import the error and throw it when a retry attempt is required. Example: @@ -137,20 +216,35 @@ Following lines shows part of Android manifest file for registering broadcast re Broadcast receiver then handles intent that was broadcasted in onReceive function. This is a great place to check whether your app is on foreground or not. If app is not on foreground we can prepare our intent to be started, with no information or additional information bundled using `putExtra` (keep in mind bundle can handle only parcelable values). In the end service is started and wakelock is acquired. + + + ```java +import android.app.ActivityManager; +import android.content.BroadcastReceiver; +import android.content.Context; +import android.content.Intent; +import android.net.ConnectivityManager; +import android.net.Network; +import android.net.NetworkCapabilities; +import android.net.NetworkInfo; +import android.os.Build; + +import com.facebook.react.HeadlessJsTaskService; + public class NetworkChangeReceiver extends BroadcastReceiver { @Override public void onReceive(final Context context, final Intent intent) { /** - This part will be called every time network connection is changed - e.g. Connected -> Not Connected - **/ + This part will be called every time network connection is changed + e.g. Connected -> Not Connected + **/ if (!isAppOnForeground((context))) { /** - We will start our service and send extra info about - network connections - **/ + 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); @@ -161,20 +255,20 @@ public class NetworkChangeReceiver extends BroadcastReceiver { private boolean isAppOnForeground(Context context) { /** - We need to check if app is in foreground otherwise the app will crash. + 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 appProcesses = - activityManager.getRunningAppProcesses(); + 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)) { + ActivityManager.RunningAppProcessInfo.IMPORTANCE_FOREGROUND && + appProcess.processName.equals(packageName)) { return true; } } @@ -183,13 +277,124 @@ public class NetworkChangeReceiver extends BroadcastReceiver { public static boolean isNetworkAvailable(Context context) { ConnectivityManager cm = (ConnectivityManager) - context.getSystemService(Context.CONNECTIVITY_SERVICE); + context.getSystemService(Context.CONNECTIVITY_SERVICE); + + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) { + Network networkCapabilities = cm.getActiveNetwork(); + + if(networkCapabilities == null) { + return false; + } + + NetworkCapabilities actNw = cm.getNetworkCapabilities(networkCapabilities); + + if(actNw == null) { + return false; + } + + if(actNw.hasTransport(NetworkCapabilities.TRANSPORT_WIFI) || actNw.hasTransport(NetworkCapabilities.TRANSPORT_CELLULAR) || actNw.hasTransport(NetworkCapabilities.TRANSPORT_ETHERNET)) { + return true; + } + + return false; + } + + // deprecated in API level 28 NetworkInfo netInfo = cm.getActiveNetworkInfo(); return (netInfo != null && netInfo.isConnected()); } +} +``` + + + +```kotlin +import android.app.ActivityManager +import android.app.ActivityManager.RunningAppProcessInfo +import android.content.BroadcastReceiver +import android.content.Context +import android.content.Intent +import android.net.ConnectivityManager +import android.net.NetworkCapabilities +import android.os.Build +import com.facebook.react.HeadlessJsTaskService + +class NetworkChangeReceiver : BroadcastReceiver() { + override fun onReceive(context: Context, intent: Intent?) { + /** + * This part will be called every time network connection is changed e.g. Connected -> Not + * Connected + */ + if (!isAppOnForeground(context)) { + /** We will start our service and send extra info about network connections */ + val hasInternet = isNetworkAvailable(context) + val serviceIntent = Intent(context, MyTaskService::class.java) + serviceIntent.putExtra("hasInternet", hasInternet) + context.startService(serviceIntent) + HeadlessJsTaskService.acquireWakeLockNow(context) + } + } + private fun isAppOnForeground(context: Context): Boolean { + /** + * 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 + */ + val activityManager = context.getSystemService(Context.ACTIVITY_SERVICE) as ActivityManager + val appProcesses = activityManager.runningAppProcesses ?: return false + val packageName: String = context.getPackageName() + for (appProcess in appProcesses) { + if (appProcess.importance == RunningAppProcessInfo.IMPORTANCE_FOREGROUND && + appProcess.processName == packageName + ) { + return true + } + } + return false + } + + companion object { + fun isNetworkAvailable(context: Context): Boolean { + val cm = context.getSystemService(Context.CONNECTIVITY_SERVICE) as ConnectivityManager + var result = false + + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) { + val networkCapabilities = cm.activeNetwork ?: return false + + val actNw = cm.getNetworkCapabilities(networkCapabilities) ?: return false + + result = + when { + actNw.hasTransport(NetworkCapabilities.TRANSPORT_WIFI) -> true + actNw.hasTransport(NetworkCapabilities.TRANSPORT_CELLULAR) -> true + actNw.hasTransport(NetworkCapabilities.TRANSPORT_ETHERNET) -> true + else -> false + } + + return result + } else { + cm.run { + // deprecated in API level 28 + cm.activeNetworkInfo?.run { + result = + when (type) { + ConnectivityManager.TYPE_WIFI -> true + ConnectivityManager.TYPE_MOBILE -> true + ConnectivityManager.TYPE_ETHERNET -> true + else -> false + } + } + } + } + return result + } + } } + ``` + + + [0]: https://developer.android.com/reference/android/content/Context.html#startService(android.content.Intent) From 2ec6e987e67148df0567680fa96eb0ee2f0e8a15 Mon Sep 17 00:00:00 2001 From: Alfonso Lasa Date: Sat, 11 Jun 2022 12:15:50 +0200 Subject: [PATCH 02/11] change: title --- docs/headless-js-android.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/headless-js-android.md b/docs/headless-js-android.md index 60ad8783037..d4a247cd8c6 100644 --- a/docs/headless-js-android.md +++ b/docs/headless-js-android.md @@ -29,7 +29,7 @@ module.exports = async (taskData) => { You can do anything in your task such as network requests, timers and so on, as long as it doesn't touch UI. Once your task completes (i.e. the promise is resolved), React Native will go into "paused" mode (unless there are other tasks running, or there is a foreground app). -## The Native API +## The Platform API Yes, this does still require some native code, but it's pretty thin. You need to extend `HeadlessJsTaskService` and override `getTaskConfig`, e.g.: From d4e70bed18f777460fbd7589db5aec47ed7bfcc3 Mon Sep 17 00:00:00 2001 From: Alfonso Lasa Date: Sat, 11 Jun 2022 12:37:01 +0200 Subject: [PATCH 03/11] refactor: use let instead of if condition --- docs/headless-js-android.md | 11 ++++------- 1 file changed, 4 insertions(+), 7 deletions(-) diff --git a/docs/headless-js-android.md b/docs/headless-js-android.md index d4a247cd8c6..82740007e9c 100644 --- a/docs/headless-js-android.md +++ b/docs/headless-js-android.md @@ -71,24 +71,21 @@ public class MyTaskService extends HeadlessJsTaskService { package com.your_application_name; 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 class MyTaskService : HeadlessJsTaskService() { override fun getTaskConfig(intent: Intent): HeadlessJsTaskConfig? { - val extras: Bundle? = intent.extras - if (extras != null) { - return HeadlessJsTaskConfig( - "SomeTaskName", - Arguments.fromBundle(extras), + return intent.extras?.let { + HeadlessJsTaskConfig( + "SomeT askName", + Arguments.fromBundle(it), 5000, // timeout for the task false // optional: defines whether or not the task is allowed in foreground. // Default is false ) } - return null } } From 7d7d6382e49e458bbe789fba92e1407423b625ed Mon Sep 17 00:00:00 2001 From: Alfonso Lasa Date: Sat, 11 Jun 2022 12:41:03 +0200 Subject: [PATCH 04/11] refactor: applicationContext getApplicationContext --- docs/headless-js-android.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/headless-js-android.md b/docs/headless-js-android.md index 82740007e9c..39eebcfde03 100644 --- a/docs/headless-js-android.md +++ b/docs/headless-js-android.md @@ -121,7 +121,7 @@ getApplicationContext().startService(service); ```kotlin -val service = Intent(getApplicationContext(), MyTaskService::class.java) +val service = Intent(applicationContext, MyTaskService::class.java) val bundle = Bundle() bundle.putString("foo", "bar") From b82566def4709982ba6ece7f81ea6e52e581df79 Mon Sep 17 00:00:00 2001 From: Alfonso Lasa Date: Sat, 11 Jun 2022 12:43:36 +0200 Subject: [PATCH 05/11] fix: double quotes on kotlin code --- docs/headless-js-android.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/headless-js-android.md b/docs/headless-js-android.md index 39eebcfde03..773e2ce4871 100644 --- a/docs/headless-js-android.md +++ b/docs/headless-js-android.md @@ -168,7 +168,7 @@ val retryPolicy: HeadlessJsTaskRetryPolicy = 1000 // Delay between each retry attempt ) -return HeadlessJsTaskConfig('SomeTaskName', Arguments.fromBundle(extras), 5000, false, retryPolicy) +return HeadlessJsTaskConfig("SomeTaskName", Arguments.fromBundle(extras), 5000, false, retryPolicy) ``` From 0b3be987d5ac3773cd42618edced38f8c8f957d4 Mon Sep 17 00:00:00 2001 From: Alfonso Lasa Date: Sat, 11 Jun 2022 13:07:00 +0200 Subject: [PATCH 06/11] fix: build version check --- website/versioned_docs/version-0.68/headless-js-android.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/website/versioned_docs/version-0.68/headless-js-android.md b/website/versioned_docs/version-0.68/headless-js-android.md index 60ad8783037..53a6e5ba2e3 100644 --- a/website/versioned_docs/version-0.68/headless-js-android.md +++ b/website/versioned_docs/version-0.68/headless-js-android.md @@ -279,7 +279,7 @@ public class NetworkChangeReceiver extends BroadcastReceiver { ConnectivityManager cm = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE); - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) { + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) { Network networkCapabilities = cm.getActiveNetwork(); if(networkCapabilities == null) { @@ -299,7 +299,7 @@ public class NetworkChangeReceiver extends BroadcastReceiver { return false; } - // deprecated in API level 28 + // deprecated in API level 29 NetworkInfo netInfo = cm.getActiveNetworkInfo(); return (netInfo != null && netInfo.isConnected()); } From 395afa2a1e0dbf312e739eecc090b38dbdddbc54 Mon Sep 17 00:00:00 2001 From: Alfonso Lasa Date: Sat, 11 Jun 2022 13:12:40 +0200 Subject: [PATCH 07/11] fix: extra space --- website/versioned_docs/version-0.68/headless-js-android.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/website/versioned_docs/version-0.68/headless-js-android.md b/website/versioned_docs/version-0.68/headless-js-android.md index 53a6e5ba2e3..a636681da76 100644 --- a/website/versioned_docs/version-0.68/headless-js-android.md +++ b/website/versioned_docs/version-0.68/headless-js-android.md @@ -84,7 +84,7 @@ class MyTaskService : HeadlessJsTaskService() { "SomeTaskName", Arguments.fromBundle(extras), 5000, // timeout for the task - false // optional: defines whether or not the task is allowed in foreground. + false // optional: defines whether or not the task is allowed in foreground. // Default is false ) } From 1eb8fc41d2f3aecd1b3591c57ce67704c73d0b61 Mon Sep 17 00:00:00 2001 From: Alfonso Lasa Date: Sat, 11 Jun 2022 13:13:41 +0200 Subject: [PATCH 08/11] fix: version docs --- .../version-0.68/headless-js-android.md | 23 ++++++++----------- 1 file changed, 10 insertions(+), 13 deletions(-) diff --git a/website/versioned_docs/version-0.68/headless-js-android.md b/website/versioned_docs/version-0.68/headless-js-android.md index a636681da76..773e2ce4871 100644 --- a/website/versioned_docs/version-0.68/headless-js-android.md +++ b/website/versioned_docs/version-0.68/headless-js-android.md @@ -29,7 +29,7 @@ module.exports = async (taskData) => { You can do anything in your task such as network requests, timers and so on, as long as it doesn't touch UI. Once your task completes (i.e. the promise is resolved), React Native will go into "paused" mode (unless there are other tasks running, or there is a foreground app). -## The Native API +## The Platform API Yes, this does still require some native code, but it's pretty thin. You need to extend `HeadlessJsTaskService` and override `getTaskConfig`, e.g.: @@ -71,24 +71,21 @@ public class MyTaskService extends HeadlessJsTaskService { package com.your_application_name; 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 class MyTaskService : HeadlessJsTaskService() { override fun getTaskConfig(intent: Intent): HeadlessJsTaskConfig? { - val extras: Bundle? = intent.extras - if (extras != null) { - return HeadlessJsTaskConfig( - "SomeTaskName", - Arguments.fromBundle(extras), + return intent.extras?.let { + HeadlessJsTaskConfig( + "SomeT askName", + Arguments.fromBundle(it), 5000, // timeout for the task - false // optional: defines whether or not the task is allowed in foreground. + false // optional: defines whether or not the task is allowed in foreground. // Default is false ) } - return null } } @@ -124,7 +121,7 @@ getApplicationContext().startService(service); ```kotlin -val service = Intent(getApplicationContext(), MyTaskService::class.java) +val service = Intent(applicationContext, MyTaskService::class.java) val bundle = Bundle() bundle.putString("foo", "bar") @@ -171,7 +168,7 @@ val retryPolicy: HeadlessJsTaskRetryPolicy = 1000 // Delay between each retry attempt ) -return HeadlessJsTaskConfig('SomeTaskName', Arguments.fromBundle(extras), 5000, false, retryPolicy) +return HeadlessJsTaskConfig("SomeTaskName", Arguments.fromBundle(extras), 5000, false, retryPolicy) ``` @@ -279,7 +276,7 @@ public class NetworkChangeReceiver extends BroadcastReceiver { ConnectivityManager cm = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE); - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) { + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) { Network networkCapabilities = cm.getActiveNetwork(); if(networkCapabilities == null) { @@ -299,7 +296,7 @@ public class NetworkChangeReceiver extends BroadcastReceiver { return false; } - // deprecated in API level 29 + // deprecated in API level 28 NetworkInfo netInfo = cm.getActiveNetworkInfo(); return (netInfo != null && netInfo.isConnected()); } From a94bcce9a6ee1ffdcbd995fc53d36c0d475f5b73 Mon Sep 17 00:00:00 2001 From: Alfonso Lasa Date: Sat, 11 Jun 2022 13:23:14 +0200 Subject: [PATCH 09/11] fix: deprecatin version docs --- docs/headless-js-android.md | 4 ++-- website/versioned_docs/version-0.68/headless-js-android.md | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/docs/headless-js-android.md b/docs/headless-js-android.md index 773e2ce4871..48523ac14ed 100644 --- a/docs/headless-js-android.md +++ b/docs/headless-js-android.md @@ -296,7 +296,7 @@ public class NetworkChangeReceiver extends BroadcastReceiver { return false; } - // deprecated in API level 28 + // deprecated in API level 29 NetworkInfo netInfo = cm.getActiveNetworkInfo(); return (netInfo != null && netInfo.isConnected()); } @@ -372,7 +372,7 @@ class NetworkChangeReceiver : BroadcastReceiver() { return result } else { cm.run { - // deprecated in API level 28 + // deprecated in API level 29 cm.activeNetworkInfo?.run { result = when (type) { diff --git a/website/versioned_docs/version-0.68/headless-js-android.md b/website/versioned_docs/version-0.68/headless-js-android.md index 773e2ce4871..48523ac14ed 100644 --- a/website/versioned_docs/version-0.68/headless-js-android.md +++ b/website/versioned_docs/version-0.68/headless-js-android.md @@ -296,7 +296,7 @@ public class NetworkChangeReceiver extends BroadcastReceiver { return false; } - // deprecated in API level 28 + // deprecated in API level 29 NetworkInfo netInfo = cm.getActiveNetworkInfo(); return (netInfo != null && netInfo.isConnected()); } @@ -372,7 +372,7 @@ class NetworkChangeReceiver : BroadcastReceiver() { return result } else { cm.run { - // deprecated in API level 28 + // deprecated in API level 29 cm.activeNetworkInfo?.run { result = when (type) { From aeb9aa711c6cf57e8ab21db190aeff4abcdb3036 Mon Sep 17 00:00:00 2001 From: Alfonso Lasa Date: Thu, 16 Jun 2022 11:12:40 +0200 Subject: [PATCH 10/11] fix: wrongformat spacing --- docs/headless-js-android.md | 2 +- website/versioned_docs/version-0.68/headless-js-android.md | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/headless-js-android.md b/docs/headless-js-android.md index 48523ac14ed..adf438f09b0 100644 --- a/docs/headless-js-android.md +++ b/docs/headless-js-android.md @@ -84,7 +84,7 @@ class MyTaskService : HeadlessJsTaskService() { 5000, // timeout for the task false // optional: defines whether or not the task is allowed in foreground. // Default is false - ) + ) } } } diff --git a/website/versioned_docs/version-0.68/headless-js-android.md b/website/versioned_docs/version-0.68/headless-js-android.md index 48523ac14ed..adf438f09b0 100644 --- a/website/versioned_docs/version-0.68/headless-js-android.md +++ b/website/versioned_docs/version-0.68/headless-js-android.md @@ -84,7 +84,7 @@ class MyTaskService : HeadlessJsTaskService() { 5000, // timeout for the task false // optional: defines whether or not the task is allowed in foreground. // Default is false - ) + ) } } } From 872739881727ae53e77c8a43794395b76777064a Mon Sep 17 00:00:00 2001 From: Alfonso Lasa Date: Thu, 16 Jun 2022 11:15:51 +0200 Subject: [PATCH 11/11] refactor: application context --- docs/headless-js-android.md | 2 +- website/versioned_docs/version-0.68/headless-js-android.md | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/headless-js-android.md b/docs/headless-js-android.md index adf438f09b0..61bf1181e3b 100644 --- a/docs/headless-js-android.md +++ b/docs/headless-js-android.md @@ -128,7 +128,7 @@ bundle.putString("foo", "bar") service.putExtras(bundle) -getApplicationContext().startService(service) +applicationContext.startService(service) ``` diff --git a/website/versioned_docs/version-0.68/headless-js-android.md b/website/versioned_docs/version-0.68/headless-js-android.md index adf438f09b0..61bf1181e3b 100644 --- a/website/versioned_docs/version-0.68/headless-js-android.md +++ b/website/versioned_docs/version-0.68/headless-js-android.md @@ -128,7 +128,7 @@ bundle.putString("foo", "bar") service.putExtras(bundle) -getApplicationContext().startService(service) +applicationContext.startService(service) ```