mirror of https://github.com/jitsi/jitsi-meet
[WIP] adds BroadcastService (#8336)
feat(external_api) exposes more events from JS to native and adds the ability to send actions from native to JS.pull/8406/head jitsi-meet_5412
parent
1196ede961
commit
5ef60c3a7d
@ -0,0 +1,84 @@ |
|||||||
|
package org.jitsi.meet.sdk; |
||||||
|
|
||||||
|
import android.content.Intent; |
||||||
|
import android.os.Bundle; |
||||||
|
|
||||||
|
import com.facebook.react.bridge.WritableNativeMap; |
||||||
|
|
||||||
|
import org.jitsi.meet.sdk.log.JitsiMeetLogger; |
||||||
|
|
||||||
|
import java.util.HashMap; |
||||||
|
|
||||||
|
/** |
||||||
|
* Wraps the name and extra data for events that were broadcasted locally. |
||||||
|
*/ |
||||||
|
public class BroadcastAction { |
||||||
|
private static final String TAG = BroadcastAction.class.getSimpleName(); |
||||||
|
|
||||||
|
private final Type type; |
||||||
|
private final HashMap<String, Object> data; |
||||||
|
|
||||||
|
public BroadcastAction(Intent intent) { |
||||||
|
this.type = Type.buildTypeFromAction(intent.getAction()); |
||||||
|
this.data = buildDataFromBundle(intent.getExtras()); |
||||||
|
} |
||||||
|
|
||||||
|
public Type getType() { |
||||||
|
return this.type; |
||||||
|
} |
||||||
|
|
||||||
|
public HashMap<String, Object> getData() { |
||||||
|
return this.data; |
||||||
|
} |
||||||
|
|
||||||
|
public WritableNativeMap getDataAsWritableNativeMap() { |
||||||
|
WritableNativeMap nativeMap = new WritableNativeMap(); |
||||||
|
|
||||||
|
for (String key : this.data.keySet()) { |
||||||
|
try { |
||||||
|
// TODO add support for different types of objects
|
||||||
|
nativeMap.putString(key, this.data.get(key).toString()); |
||||||
|
} catch (Exception e) { |
||||||
|
JitsiMeetLogger.w(TAG + " invalid extra data in event", e); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
return nativeMap; |
||||||
|
} |
||||||
|
|
||||||
|
private static HashMap<String, Object> buildDataFromBundle(Bundle bundle) { |
||||||
|
HashMap<String, Object> map = new HashMap<>(); |
||||||
|
|
||||||
|
if (bundle != null) { |
||||||
|
for (String key : bundle.keySet()) { |
||||||
|
map.put(key, bundle.get(key)); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
return map; |
||||||
|
} |
||||||
|
|
||||||
|
enum Type { |
||||||
|
SET_AUDIO_MUTED("org.jitsi.meet.SET_AUDIO_MUTED"), |
||||||
|
HANG_UP("org.jitsi.meet.HANG_UP"); |
||||||
|
|
||||||
|
private final String action; |
||||||
|
|
||||||
|
Type(String action) { |
||||||
|
this.action = action; |
||||||
|
} |
||||||
|
|
||||||
|
public String getAction() { |
||||||
|
return action; |
||||||
|
} |
||||||
|
|
||||||
|
private static Type buildTypeFromAction(String action) { |
||||||
|
for (Type type : Type.values()) { |
||||||
|
if (type.action.equalsIgnoreCase(action)) { |
||||||
|
return type; |
||||||
|
} |
||||||
|
} |
||||||
|
return null; |
||||||
|
} |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,30 @@ |
|||||||
|
package org.jitsi.meet.sdk; |
||||||
|
|
||||||
|
import android.content.Context; |
||||||
|
import android.content.Intent; |
||||||
|
|
||||||
|
import androidx.localbroadcastmanager.content.LocalBroadcastManager; |
||||||
|
|
||||||
|
import com.facebook.react.bridge.ReadableMap; |
||||||
|
|
||||||
|
/** |
||||||
|
* Class used to emit events through the LocalBroadcastManager, called when events |
||||||
|
* from JS occurred. Takes an action name from JS, builds and broadcasts the {@link BroadcastEvent} |
||||||
|
*/ |
||||||
|
public class BroadcastEmitter { |
||||||
|
private final LocalBroadcastManager localBroadcastManager; |
||||||
|
|
||||||
|
public BroadcastEmitter(Context context) { |
||||||
|
localBroadcastManager = LocalBroadcastManager.getInstance(context); |
||||||
|
} |
||||||
|
|
||||||
|
public void sendBroadcast(String name, ReadableMap data) { |
||||||
|
BroadcastEvent event = new BroadcastEvent(name, data); |
||||||
|
|
||||||
|
Intent intent = event.buildIntent(); |
||||||
|
|
||||||
|
if (intent != null) { |
||||||
|
localBroadcastManager.sendBroadcast(intent); |
||||||
|
} |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,130 @@ |
|||||||
|
package org.jitsi.meet.sdk; |
||||||
|
|
||||||
|
import android.content.Intent; |
||||||
|
import android.os.Bundle; |
||||||
|
|
||||||
|
import com.facebook.react.bridge.ReadableMap; |
||||||
|
|
||||||
|
import org.jitsi.meet.sdk.log.JitsiMeetLogger; |
||||||
|
|
||||||
|
import java.util.HashMap; |
||||||
|
|
||||||
|
/** |
||||||
|
* Wraps the name and extra data for the events that occur on the JS side and are |
||||||
|
* to be broadcasted. |
||||||
|
*/ |
||||||
|
public class BroadcastEvent { |
||||||
|
|
||||||
|
private static final String TAG = BroadcastEvent.class.getSimpleName(); |
||||||
|
|
||||||
|
private final Type type; |
||||||
|
private final HashMap<String, Object> data; |
||||||
|
|
||||||
|
public BroadcastEvent(String name, ReadableMap data) { |
||||||
|
this.type = Type.buildTypeFromName(name); |
||||||
|
this.data = data.toHashMap(); |
||||||
|
} |
||||||
|
|
||||||
|
public BroadcastEvent(Intent intent) { |
||||||
|
this.type = Type.buildTypeFromAction(intent.getAction()); |
||||||
|
this.data = buildDataFromBundle(intent.getExtras()); |
||||||
|
} |
||||||
|
|
||||||
|
public Type getType() { |
||||||
|
return this.type; |
||||||
|
} |
||||||
|
|
||||||
|
public HashMap<String, Object> getData() { |
||||||
|
return this.data; |
||||||
|
} |
||||||
|
|
||||||
|
public Intent buildIntent() { |
||||||
|
if (type != null && type.action != null) { |
||||||
|
Intent intent = new Intent(type.action); |
||||||
|
|
||||||
|
for (String key : this.data.keySet()) { |
||||||
|
try { |
||||||
|
intent.putExtra(key, this.data.get(key).toString()); |
||||||
|
} catch (Exception e) { |
||||||
|
JitsiMeetLogger.w(TAG + " invalid extra data in event", e); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
return intent; |
||||||
|
} |
||||||
|
|
||||||
|
return null; |
||||||
|
} |
||||||
|
|
||||||
|
private static HashMap<String, Object> buildDataFromBundle(Bundle bundle) { |
||||||
|
if (bundle != null) { |
||||||
|
try { |
||||||
|
HashMap<String, Object> map = new HashMap<>(); |
||||||
|
|
||||||
|
for (String key : bundle.keySet()) { |
||||||
|
map.put(key, bundle.get(key)); |
||||||
|
} |
||||||
|
|
||||||
|
return map; |
||||||
|
} catch (Exception e) { |
||||||
|
JitsiMeetLogger.w(TAG + " invalid extra data", e); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
return null; |
||||||
|
} |
||||||
|
|
||||||
|
public enum Type { |
||||||
|
CONFERENCE_JOINED("org.jitsi.meet.CONFERENCE_JOINED"), |
||||||
|
CONFERENCE_TERMINATED("org.jitsi.meet.CONFERENCE_TERMINATED"), |
||||||
|
CONFERENCE_WILL_JOIN("org.jitsi.meet.CONFERENCE_WILL_JOIN"), |
||||||
|
AUDIO_MUTED_CHANGED("org.jitsi.meet.AUDIO_MUTED_CHANGED"), |
||||||
|
PARTICIPANT_JOINED("org.jitsi.meet.PARTICIPANT_JOINED"), |
||||||
|
PARTICIPANT_LEFT("org.jitsi.meet.PARTICIPANT_LEFT"); |
||||||
|
|
||||||
|
private static final String CONFERENCE_WILL_JOIN_NAME = "CONFERENCE_WILL_JOIN"; |
||||||
|
private static final String CONFERENCE_JOINED_NAME = "CONFERENCE_JOINED"; |
||||||
|
private static final String CONFERENCE_TERMINATED_NAME = "CONFERENCE_TERMINATED"; |
||||||
|
private static final String AUDIO_MUTED_CHANGED_NAME = "AUDIO_MUTED_CHANGED"; |
||||||
|
private static final String PARTICIPANT_JOINED_NAME = "PARTICIPANT_JOINED"; |
||||||
|
private static final String PARTICIPANT_LEFT_NAME = "PARTICIPANT_LEFT"; |
||||||
|
|
||||||
|
private final String action; |
||||||
|
|
||||||
|
Type(String action) { |
||||||
|
this.action = action; |
||||||
|
} |
||||||
|
|
||||||
|
public String getAction() { |
||||||
|
return action; |
||||||
|
} |
||||||
|
|
||||||
|
private static Type buildTypeFromAction(String action) { |
||||||
|
for (Type type : Type.values()) { |
||||||
|
if (type.action.equalsIgnoreCase(action)) { |
||||||
|
return type; |
||||||
|
} |
||||||
|
} |
||||||
|
return null; |
||||||
|
} |
||||||
|
|
||||||
|
private static Type buildTypeFromName(String name) { |
||||||
|
switch (name) { |
||||||
|
case CONFERENCE_WILL_JOIN_NAME: |
||||||
|
return CONFERENCE_WILL_JOIN; |
||||||
|
case CONFERENCE_JOINED_NAME: |
||||||
|
return CONFERENCE_JOINED; |
||||||
|
case CONFERENCE_TERMINATED_NAME: |
||||||
|
return CONFERENCE_TERMINATED; |
||||||
|
case AUDIO_MUTED_CHANGED_NAME: |
||||||
|
return AUDIO_MUTED_CHANGED; |
||||||
|
case PARTICIPANT_JOINED_NAME: |
||||||
|
return PARTICIPANT_JOINED; |
||||||
|
case PARTICIPANT_LEFT_NAME: |
||||||
|
return PARTICIPANT_LEFT; |
||||||
|
} |
||||||
|
|
||||||
|
return null; |
||||||
|
} |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,15 @@ |
|||||||
|
package org.jitsi.meet.sdk; |
||||||
|
|
||||||
|
import android.content.Intent; |
||||||
|
|
||||||
|
public class BroadcastIntentHelper { |
||||||
|
public static Intent buildSetAudioMutedIntent(boolean muted) { |
||||||
|
Intent intent = new Intent(BroadcastAction.Type.SET_AUDIO_MUTED.getAction()); |
||||||
|
intent.putExtra("muted", muted); |
||||||
|
return intent; |
||||||
|
} |
||||||
|
|
||||||
|
public static Intent buildHangUpIntent() { |
||||||
|
return new Intent(BroadcastAction.Type.HANG_UP.getAction()); |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,32 @@ |
|||||||
|
package org.jitsi.meet.sdk; |
||||||
|
|
||||||
|
import android.content.Context; |
||||||
|
import android.content.Intent; |
||||||
|
import android.content.IntentFilter; |
||||||
|
|
||||||
|
import androidx.localbroadcastmanager.content.LocalBroadcastManager; |
||||||
|
|
||||||
|
/** |
||||||
|
* Listens for {@link BroadcastAction}s on LocalBroadcastManager. When one occurs, |
||||||
|
* it emits it to JS. |
||||||
|
*/ |
||||||
|
public class BroadcastReceiver extends android.content.BroadcastReceiver { |
||||||
|
|
||||||
|
public BroadcastReceiver(Context context) { |
||||||
|
LocalBroadcastManager localBroadcastManager = LocalBroadcastManager.getInstance(context); |
||||||
|
|
||||||
|
IntentFilter intentFilter = new IntentFilter(); |
||||||
|
intentFilter.addAction(BroadcastAction.Type.SET_AUDIO_MUTED.getAction()); |
||||||
|
intentFilter.addAction(BroadcastAction.Type.HANG_UP.getAction()); |
||||||
|
|
||||||
|
localBroadcastManager.registerReceiver(this, intentFilter); |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public void onReceive(Context context, Intent intent) { |
||||||
|
BroadcastAction action = new BroadcastAction(intent); |
||||||
|
String actionName = action.getType().getAction(); |
||||||
|
|
||||||
|
ReactInstanceManagerHolder.emitEvent(actionName, action.getDataAsWritableNativeMap()); |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,24 @@ |
|||||||
|
/* Copyright @ 2021-present 8x8, Inc.
|
||||||
|
* |
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License"); |
||||||
|
* you may not use this file except in compliance with the License. |
||||||
|
* You may obtain a copy of the License at |
||||||
|
* |
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
* |
||||||
|
* Unless required by applicable law or agreed to in writing, software |
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS, |
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
||||||
|
* See the License for the specific language governing permissions and |
||||||
|
* limitations under the License. |
||||||
|
*/ |
||||||
|
|
||||||
|
#import <React/RCTBridgeModule.h> |
||||||
|
#import <React/RCTEventEmitter.h> |
||||||
|
|
||||||
|
@interface ExternalAPI : RCTEventEmitter<RCTBridgeModule> |
||||||
|
|
||||||
|
- (void)sendHangUp; |
||||||
|
- (void)sendSetAudioMuted: (BOOL)muted; |
||||||
|
|
||||||
|
@end |
Loading…
Reference in new issue