私は最近、システムからのタイムゾーンと時間変更されたブロードキャストをリッスンし、アプリがいくつかの操作を実行できるようにするAndroidネイティブモジュールを自分に追加しました。ネイティブモジュールは次のようになります
public class TimezoneHandlerModule extends ReactContextBaseJavaModule {
private final Context context;
private final TimezoneChangeBroadcastReceiver timezoneChangeBroadcastReceiver;
private Callback onTimezoneChangeCallback;
public TimezoneHandlerModule(ReactApplicationContext reactContext) {
super(reactContext);
this.context = reactContext;
this.timezoneChangeBroadcastReceiver = new TimezoneChangeBroadcastReceiver();
}
private void registerForTimezoneChangeHandler() {
IntentFilter intentFilter = new IntentFilter();
intentFilter.addAction(Intent.ACTION_TIME_CHANGED);
intentFilter.addAction(Intent.ACTION_TIMEZONE_CHANGED);
getReactApplicationContext().registerReceiver(timezoneChangeBroadcastReceiver, intentFilter);
}
private void unregisterTimezoneChangeHandler() {
getReactApplicationContext().unregisterReceiver(timezoneChangeBroadcastReceiver);
}
public void setOnTimezoneChangeCallback(Callback onTimezoneChangeCallback) {
this.onTimezoneChangeCallback = onTimezoneChangeCallback;
}
/**
* @return the name of this module. This will be the name used to {@code require()} this module
* from javascript.
*/
@Override
public String getName() {
return "TimezoneHandler";
}
@ReactMethod
public void start(Callback onChange) {
Log.d(getName(), "Starting the timezone change handler");
this.registerForTimezoneChangeHandler();
this.setOnTimezoneChangeCallback(onChange);
}
@ReactMethod
public void stop() {
Log.d(getName(), "Stopping the timezone change handler");
this.unregisterTimezoneChangeHandler();
}
private class TimezoneChangeBroadcastReceiver extends BroadcastReceiver {
@Override
public void onReceive(Context context, Intent intent) {
Log.d(getName(), "Received broadcast for timezone/time change " + intent.getAction());
final String action = intent.getAction();
if (action.equals(Intent.ACTION_TIME_CHANGED) || action.equals(Intent.ACTION_TIMEZONE_CHANGED)) {
TimezoneHandlerModule.this.onTimezoneChangeCallback.invoke();
}
}
}
}
2つの反応方法が公開されstart
ていstop
ます。start
タイムゾーン変更または時間変更のブロードキャストが受信されるたびに呼び出されるパラメータとして関数を取ります。ネイティブモジュールを接続してエミュレーターでアプリを起動した後Settings
、タイムゾーンを開いて変更すると、関連するログが出力されていることがわかります。
11-24 17:07:21.837 1597-1597/com.xyz D/TimezoneHandler: Received broadcast for timezone/time change
11-24 17:07:21.837 1597-1907/com.xyz I/ReactNativeJS: Detected timezone change
タイムゾーンを再度変更すると、logcatの出力に以下のエラーが表示されます
1-24 17:22:42.356 1597-1597/com.galarmapp D/TimezoneHandler: Received broadcast for timezone/time change
11-24 17:22:42.365 1597-1907/com.galarmapp E/ReactNativeJS: The callback start() exists in module TimezoneHandler, but only one callback may be registered to a function in a native module.
11-24 17:22:42.367 1597-1908/com.galarmapp E/unknown:React: The callback start() exists in module TimezoneHandler, but only one callback may be registered to a function in a native module., stack:
__invokeCallback@12814:10
<unknown>@12685:24
guard@12604:3
invokeCallbackAndReturnFlushedQueue@12684:6
エラーメッセージから、start
関数に別のコールバックをアタッチしようとしているように見えますが、そのようなことは何もしていません。トップレベルコンポーネントのstart
メソッドを呼び出していますが、componentWillMount
2回呼び出されていないことを確認しました。他の人も別のことを試しているときにこのエラーを見たことがありますが、それでも問題の背後にある理由を理解していません。
何か洞察があれば共有してください。
ドキュメントhttp://facebook.github.io/react-native/docs/native-modules-android.html#callbacksによると-「ネイティブモジュールはコールバックを1回だけ呼び出すことになっています。ただし、保存することはできます。コールバックして後で呼び出します。」コールバックでinvoke()を実行すると、それを再度使用することはできません。
タイムゾーン変更のこの特定のユースケースは、イベントをjavascriptに送信することでより適切に解決されます。このドキュメントを参照してくださいhttp://facebook.github.io/react-native/docs/native-modules-android.html#sending-events-to-javascript
この記事はインターネットから収集されたものであり、転載の際にはソースを示してください。
侵害の場合は、連絡してください[email protected]
コメントを追加