Skip to content

Commit

Permalink
implement SinchService
Browse files Browse the repository at this point in the history
  • Loading branch information
nagyszili committed May 17, 2022
1 parent 3abab97 commit e4278f5
Show file tree
Hide file tree
Showing 16 changed files with 6,950 additions and 6,446 deletions.
3 changes: 2 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ DerivedData
*.ipa
*.xcuserstate
project.xcworkspace

.env*
# Android/IntelliJ
#
build/
Expand All @@ -30,6 +30,7 @@ build/
local.properties
*.iml
*.hprof
android/app/src/main/assets/config.json

# node.js
#
Expand Down
23 changes: 23 additions & 0 deletions App.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,11 +6,14 @@ import {
View,
TouchableOpacity,
ScrollView,
TextInput,
Button,
} from "react-native";
import uuid from "uuid";
import RNCallKeep from "react-native-callkeep";
import BackgroundTimer from "react-native-background-timer";
import DeviceInfo from "react-native-device-info";
import CallManager from "./src/services/call-manager/CallManager";

BackgroundTimer.start();

Expand Down Expand Up @@ -41,6 +44,7 @@ export default function App() {
const [heldCalls, setHeldCalls] = useState({}); // callKeep uuid: held
const [mutedCalls, setMutedCalls] = useState({}); // callKeep uuid: muted
const [calls, setCalls] = useState({}); // callKeep uuid: number
const [userName, setUserName] = useState("");

const log = (text) => {
console.info(text);
Expand Down Expand Up @@ -253,6 +257,22 @@ export default function App() {
<Text>Display incoming call now in 3s</Text>
</TouchableOpacity>

<View style={styles.row}>
<TextInput
placeholder="Set User Name"
value={userName}
onChangeText={(text) => {
setUserName(text);
}}
/>
<Button
title="Connect"
onPress={() => {
CallManager.setup(userName);
}}
/>
</View>

{Object.keys(calls).map((callUUID) => (
<View key={callUUID} style={styles.callButtons}>
<TouchableOpacity
Expand Down Expand Up @@ -325,4 +345,7 @@ const styles = StyleSheet.create({
log: {
fontSize: 10,
},
row: {
flexDirection: "row",
},
});
11 changes: 7 additions & 4 deletions android/app/src/main/AndroidManifest.xml
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,9 @@
<uses-permission android:name="android.permission.RECORD_AUDIO" />
<uses-permission android:name="android.permission.MANAGE_OWN_CALLS" />
<uses-permission android:name="android.permission.READ_CALL_LOG" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.MODIFY_AUDIO_SETTINGS" />
<uses-permission android:name="android.permission.CAMERA" />

<queries>
<intent>
Expand All @@ -33,11 +36,11 @@
android:roundIcon="@mipmap/ic_launcher_round"
android:theme="@style/AppTheme"
android:usesCleartextTraffic="true">
<activity
android:name=".StartCallActivity"
android:exported="false" />

<service
android:name=".sinch.SinchService"
android:enabled="true"
android:exported="true" />
<service android:name=".sinch.SinchService" />

<meta-data
android:name="expo.modules.updates.ENABLED"
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,98 @@
package com.kadeno.reactnativecallpoc;

import android.app.Activity;
import android.content.ComponentName;
import android.content.Intent;
import android.content.ServiceConnection;
import android.content.pm.PackageManager;
import android.os.Bundle;
import android.os.Handler;
import android.os.IBinder;
import android.os.Message;
import android.os.Messenger;
import android.view.Window;
import android.view.WindowManager;
import android.widget.Toast;

import androidx.core.app.ActivityCompat;

import com.kadeno.reactnativecallpoc.sinch.SinchService;

public abstract class BaseActivity extends Activity implements ServiceConnection {

private SinchService.SinchServiceInterface mSinchServiceInterface;

@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
bindService();
requestWindowFeature(Window.FEATURE_NO_TITLE);
getWindow().addFlags(
WindowManager.LayoutParams.FLAG_FULLSCREEN
| WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON
| WindowManager.LayoutParams.FLAG_DISMISS_KEYGUARD
| WindowManager.LayoutParams.FLAG_SHOW_WHEN_LOCKED
| WindowManager.LayoutParams.FLAG_TURN_SCREEN_ON);
}

@Override
public void onServiceConnected(ComponentName componentName, IBinder iBinder) {
if (SinchService.class.getName().equals(componentName.getClassName())) {
mSinchServiceInterface = (SinchService.SinchServiceInterface) iBinder;
onServiceConnected();
}
}

@Override
public void onServiceDisconnected(ComponentName componentName) {
if (SinchService.class.getName().equals(componentName.getClassName())) {
mSinchServiceInterface = null;
onServiceDisconnected();
}
}

protected void onServiceConnected() {
// for subclasses
}

protected void onServiceDisconnected() {
// for subclasses
}

protected SinchService.SinchServiceInterface getSinchServiceInterface() {
return mSinchServiceInterface;
}

private Messenger messenger = new Messenger(new Handler() {
@Override
public void handleMessage(Message msg) {
switch (msg.what) {
case SinchService.MESSAGE_PERMISSIONS_NEEDED:
Bundle bundle = msg.getData();
String requiredPermission = bundle.getString(SinchService.REQUIRED_PERMISSION);
ActivityCompat.requestPermissions(BaseActivity.this, new String[]{requiredPermission}, 0);
break;
}
}
});

public void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults) {
boolean granted = grantResults.length > 0;
for (int grantResult : grantResults) {
granted &= grantResult == PackageManager.PERMISSION_GRANTED;
}
if (granted) {
Toast.makeText(this, "You may now place a call", Toast.LENGTH_LONG).show();
} else {
Toast.makeText(this, "This application needs permission to use your microphone and camera to function properly.", Toast.LENGTH_LONG).show();
}
mSinchServiceInterface.retryStartAfterPermissionGranted();
}

private void bindService() {
Intent serviceIntent = new Intent(this, SinchService.class);
serviceIntent.putExtra(SinchService.MESSENGER, messenger);
getApplicationContext().bindService(serviceIntent, this, BIND_AUTO_CREATE);
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,105 @@
package com.kadeno.reactnativecallpoc.CallManager;

import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.ServiceConnection;
import android.content.pm.PackageManager;
import android.os.Bundle;
import android.os.Handler;
import android.os.IBinder;
import android.os.Message;
import android.os.Messenger;
import android.util.Log;
import android.widget.Toast;

import androidx.annotation.NonNull;
import androidx.core.app.ActivityCompat;

import com.facebook.react.bridge.LifecycleEventListener;
import com.facebook.react.bridge.Promise;
import com.facebook.react.bridge.ReactApplicationContext;
import com.facebook.react.bridge.ReactContext;
import com.facebook.react.bridge.ReactContextBaseJavaModule;
import com.facebook.react.bridge.ReactMethod;
import com.kadeno.reactnativecallpoc.MainActivity;
import com.kadeno.reactnativecallpoc.sinch.SinchService;
import com.sinch.android.rtc.MissingPermissionException;
import com.sinch.android.rtc.SinchClient;
import com.sinch.android.rtc.calling.Call;

public class CallManager extends ReactContextBaseJavaModule implements LifecycleEventListener {

private static final String TAG = "CallManager";

private static ReactContext reactContext;
private static Context context;

// private SinchService sinchService= new SinchService();
// private SinchService.SinchServiceInterface mSinchServiceInterface;


public CallManager(@NonNull ReactApplicationContext reactContext) {
super(reactContext);
this.reactContext = reactContext;
this.context = reactContext.getApplicationContext();

reactContext.addLifecycleEventListener(this);



}


/**
* Called either when the host activity receives a resume event (e.g.
* if the native module that implements this is initialized while the host activity is already
* resumed. Always called for the most current activity.
*/
@Override
public void onHostResume() {
Log.d(TAG, "onHostResume");
}

/**
* Called when host activity receives pause event (e.g.Always called
* for the most current activity.
*/
@Override
public void onHostPause() {
Log.d(TAG, "onHostPause");
}

/**
* Called when host activity receives destroy event (e.g. Only called
* for the last React activity to be destroyed.
*/
@Override
public void onHostDestroy() {
Log.d(TAG, "onHostDestroy");
}

/**
* @return the name of this module. This will be the name used to {@code require()} this module
* from javascript.
*/
@NonNull
@Override
public String getName() {
return "CallManager";
}


@ReactMethod
public void setup(String userName) {
Log.d(TAG, "setup username:" + userName);
// this.sinchService.start(userName);
}

@ReactMethod
public void callUser(String userName) {
Log.d(TAG, "callUser username:" + userName);

}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
package com.kadeno.reactnativecallpoc.CallManager;

import androidx.annotation.NonNull;

import com.facebook.react.ReactPackage;
import com.facebook.react.bridge.NativeModule;
import com.facebook.react.bridge.ReactApplicationContext;
import com.facebook.react.uimanager.ViewManager;

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

public class CallManagerPackage implements ReactPackage {
/**
* @param reactContext react application context that can be used to create modules
* @return list of native modules to register with the newly created catalyst instance
*/
@NonNull
@Override
public List<NativeModule> createNativeModules(@NonNull ReactApplicationContext reactContext) {
List<NativeModule> modules = new ArrayList<>();

modules.add(new CallManager(reactContext));

return modules;
}

/**
* @param reactContext
* @return a list of view managers that should be registered with {@link com.facebook.react.uimanager.UIManagerModule}
*/
@NonNull
@Override
public List<ViewManager> createViewManagers(@NonNull ReactApplicationContext reactContext) {
return Collections.emptyList();
}
}
34 changes: 34 additions & 0 deletions android/app/src/main/java/com/kadeno/reactnativecallpoc/Hmac.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
package com.kadeno.reactnativecallpoc;

import java.io.UnsupportedEncodingException;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;

import javax.crypto.Mac;
import javax.crypto.spec.SecretKeySpec;

final class Hmac {

private Hmac() {}

public static byte[] hmacSha256(byte[] key, String message) {
if (null == key || key.length == 0)
throw new IllegalArgumentException("Invaid input key to HMAC-256");

if (null == message)
throw new IllegalArgumentException("Input message to HMAC-256 must not be null");

try {
Mac mac = Mac.getInstance("HmacSHA256");
SecretKeySpec keySpec = new SecretKeySpec(key, "HmacSHA256");
mac.init(keySpec);
return mac.doFinal(message.getBytes("UTF-8"));
} catch (NoSuchAlgorithmException e) {
throw new RuntimeException(e);
} catch (InvalidKeyException e) {
throw new RuntimeException(e);
} catch (UnsupportedEncodingException e) {
throw new RuntimeException(e);
}
}
}
Loading

0 comments on commit e4278f5

Please sign in to comment.