美文网首页
【React-Native】通知激活App

【React-Native】通知激活App

作者: 猎手Andy | 来源:发表于2019-08-23 13:54 被阅读0次

    iOS

    PushNotificationIOS.getInitialNotification 获取时机不对,无法正确处理这种情况,不知道是我哪里没弄对。因此需要自己实现,把Notification传递给App.js.

    App未激活时,发送一个通知,点击激活App,在AppDeletegate.m的

    - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
    {
      NSURL *jsCodeLocation;
    #ifdef DEBUG
      jsCodeLocation = [[RCTBundleURLProvider sharedSettings]
                        jsBundleURLForBundleRoot:@"index"
                        fallbackResource:@"main"];
    #else
      jsCodeLocation = [[NSBundle mainBundle] URLForResource:@"main"
                                               withExtension:@"jsbundle"];
    #endif
      
      RCTBridge *bridge = [[RCTBridge alloc] initWithBundleURL:jsCodeLocation
                                                moduleProvider:nil
                                                 launchOptions:launchOptions];
      
      NSDictionary *params;
    // 如果是通过Notification激活App的
      if (launchOptions.count > 0 && launchOptions[UIApplicationLaunchOptionsRemoteNotificationKey]) {
        params = @{@"notification":launchOptions[UIApplicationLaunchOptionsRemoteNotificationKey]};
      }
      
    #if RCT_DEV
      [bridge moduleForClass:[RCTDevLoadingView  class]];
    #endif
      RCTRootView *rootView = [[RCTRootView alloc] initWithBridge:bridge
                                                       moduleName:@"yourmobileapp"
                                                initialProperties:params]; //这里传递过去
    }
    

    Android

    有个问题,当App未启动(Killed)时,来了一个消息激活App,此时会把Notification相关内容传递给第一个启动的Activity的Intent.
    我们如何传递给React的App.js呢?

    1. 获取通知相关内容
    public class LaunchScreenActivity extends AppCompatActivity {
    
        private static final String TAG = LaunchScreenActivity.class.getSimpleName();
    
        @Override
        protected void onCreate(@Nullable Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setTheme(R.style.LaunchScreenTheme);
            setContentView(R.layout.activity_launch_screen);
    
            // Check initial notification
            Intent initIntent = getIntent();
            if (initIntent != null) {
                Bundle extras = initIntent.getExtras();
                if (extras != null) { //save to singleton
                    MMInitialNotification.getInstance().setNotification(extras);
                }
            }
    
            Intent intent = new Intent(getApplicationContext(),
                    MainActivity.class);
            startActivity(intent);
            finish();
    
        }
    }
    

    ReactActivityDelegate有个方法getLaunchOptions 在启动ReactNativeApp时传递参数给App.js

    protected void loadApp(String appKey) {
        if (mReactRootView != null) {
          throw new IllegalStateException("Cannot loadApp while app is already running.");
        }
        mReactRootView = createRootView();
    // 启动App.js,通过第三个参数传入options,我们把Notification通过这个参数传入。
        mReactRootView.startReactApplication(
          getReactNativeHost().getReactInstanceManager(),
          appKey,
          getLaunchOptions());
        getPlainActivity().setContentView(mReactRootView);
      }
    
     protected @Nullable Bundle getLaunchOptions() {
        return null;
      }
    

    然而ReactActivityDelegate的实例初始化是在ReactActivity的构造方法中,

    public abstract class ReactActivity extends Activity
        implements DefaultHardwareBackBtnHandler, PermissionAwareActivity {
    
      private final ReactActivityDelegate mDelegate;
    
      protected ReactActivity() {
        mDelegate = createReactActivityDelegate();
      }
    
      /**
       * Returns the name of the main component registered from JavaScript.
       * This is used to schedule rendering of the component.
       * e.g. "MoviesApp"
       */
      protected @Nullable String getMainComponentName() {
        return null;
      }
    
      /**
       * Called at construction time, override if you have a custom delegate implementation.
       */
      protected ReactActivityDelegate createReactActivityDelegate() {
        return new ReactActivityDelegate(this, getMainComponentName());
      }
    
    

    因此要解决这个问题,就是要改写getLaunchOptions的结果,因此实现一个子类来扩展它。

    public class MMReactActivityDelegate extends ReactActivityDelegate {
        public MMReactActivityDelegate(Activity activity, @Nullable String mainComponentName) {
            super(activity, mainComponentName);
        }
    
        public @Nullable
        Bundle getLaunchOptions() {
            Bundle notification = MMInitialNotification.getInstance().getNotification();
            if (notification != null) {
                Bundle options = new Bundle();
                options.putBundle("notification", notification);
                return options;
            }
            return null;
        }
    }
    
    // 覆盖这个方法,使用自定义的MMReactActivityDelegate
    public class MMReactActivity extends ReactActivity {
        public ReactActivityDelegate createReactActivityDelegate() {
            return new MMReactActivityDelegate(this, getMainComponentName());
        }
    }
    

    测试:
    杀掉App,发送一个通知(Notification,不是Message),点击通知激活App,
    在App.js打印相关内容

    export default class App extends Component {
      constructor(props) {
        super(props);
        console.warn(`initial options:${props ? JSON.stringify(props) : 'empty'}`);
      }
    }
    

    相关文章

      网友评论

          本文标题:【React-Native】通知激活App

          本文链接:https://www.haomeiwen.com/subject/tbvzsctx.html