zoukankan      html  css  js  c++  java
  • RN服务

    https://facebook.github.io/react-native/docs/headless-js-android.html

      当app在 后台运行 时,我们可以使用RN服务来同时地刷新数据、推送或者播放音乐。

    JS API

      在JS中注册一个后台任务(不能操作UI,一般是网络请求、定时器等)

    AppRegistry.registerHeadlessTask('SomeTaskName', () => require('SomeTaskName'));
    
    // SomeTaskName.js:
    module.exports = async (taskData) => {
      // do stuff
    };

    Java API

      定义一个服务类,继承HeadlessJsTaskService

    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;
      }
    }

      在清单文件中声明这个服务

    <service android:name="com.example.MyTaskService" />

      在Java中开启这个服务

    Intent service = new Intent(getApplicationContext(), MyTaskService.class);
    Bundle bundle = new Bundle();
    
    bundle.putString("foo", "bar");
    service.putExtras(bundle);
    
    getApplicationContext().startService(service);

    警告

    1. 默认情况下,当app前台运行时,开启这个服务会导致app崩溃。这是为了防止app在展示界面的同时运行大量的后台工作,可以通过第四个参数来改变这种行为(默认为false,不允许任务在前台运行)
    2. 如果从广播接收者中开启服务,必须保证在onReceive结束前调用HeadlessJsTaskService.aquireWakeLockNow()

    例子

      这是一个可以响应网络连接变化的例子。首先在清单文件中配置广播接收者

    <receiver android:name=".NetworkChangeReceiver" >
      <intent-filter>
        <action android:name="android.net.conn.CONNECTIVITY_CHANGE" />
      </intent-filter>
    </receiver>

      广播接收者在onReceive中处理广播,可以在这里检查app是否运行在前台:

    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());
        }
    }

    实践

       测试发现必须要多加一个权限:

    <uses-permission android:name="android.permission.WAKE_LOCK"/>

      对于以下代码:

    module.exports = async (taskData) => {
        await getData()
        await getData()
        await getData()
        await getData()
        await getData()
        await getData()
    };
    
    function getData(){
        return new Promise((resolve)=>{
            setTimeout(()=>{
                console.log("get data from server")
                resolve(1)
            },5000)
        });
    }

      当设置允许运行在前台时(allowedInForeground=true),前台或者后台开启服务都没问题,只是只要app进入后台,以上的代码就会被暂停,恢复前后后继续执行。

      当不允许前台运行时,前台开启服务则闪退,后台开启不会。后台开启后,仅仅执行了一个promise,就暂停了,恢复前台后剩余的代码继续执行,再次进入后台,则代码暂停,恢复前后剩余代码继续执行。

      以上运行的环境是夜神模拟器,还没到真机上测试。

  • 相关阅读:
    iOS多线程编程之NSThread的使用
    在 VS 2013/2015 中禁用 nuget 包的源代码管理
    【转】辽宁北斗TV直播源
    Xamarin Crack
    在VisualStudio 编辑器文本替换中使用正则表达式
    Camtasia 录屏说明
    简化MSI在WIN10的安装
    在WPF中使用变通方法实现枚举类型的XAML绑定
    XAML UserControl的继承
    ArcGIS 10.1 BUG记录
  • 原文地址:https://www.cnblogs.com/hellohello/p/8323919.html
Copyright © 2011-2022 走看看