Call native code android & ios

development_aamir
Aamir Muhammad 2 years ago
parent 64efe12784
commit 109fb19d04

@ -336,7 +336,7 @@
// }
// """
// let postData = parameters.data(using: .utf8)
// var request = URLRequest(url: URL(string: "https://apiderichat.hmg.com/api/user/externaluserlogin")!,
// var request = URLRequest(url: URL(string: "https://apiderichat.hmg.com/api/user/`externaluserlogin")!,
// timeoutInterval: Double.infinity)
// request.addValue("application/json", forHTTPHeaderField: "Content-Type")
// request.httpMethod = "POST"

@ -1,3 +1,4 @@
import 'dart:async';
import 'dart:convert';
import 'dart:io';
@ -32,6 +33,7 @@ class ChatApiClient {
"${ApiConsts.chatLoginTokenUrl}externaluserlogin",
{
"employeeNumber": AppState().memberInformationList!.eMPLOYEENUMBER.toString(),
// "employeeNumber": ApiConsts.baseUrl.contains("uat") ? "266642" : AppState().memberInformationList!.eMPLOYEENUMBER.toString(),
"password": "FxIu26rWIKoF8n6mpbOmAjDLphzFGmpG",
"isMobile": true,
"deviceToken": AppState().getIsHuawei ? AppState().getHuaweiPushToken : AppState().getDeviceToken,
@ -47,7 +49,12 @@ class ChatApiClient {
if (response.statusCode == 200) {
userLoginResponse = user.userAutoLoginModelFromJson(response.body);
} else if (response.statusCode == 501 || response.statusCode == 502 || response.statusCode == 503 || response.statusCode == 504) {
getUserLoginToken();
try {
await getUserLoginToken();
} on TimeoutException catch (e) {
return userLoginResponse;
}
;
} else {
userLoginResponse = user.userAutoLoginModelFromJson(response.body);
Utils.showToast(userLoginResponse.errorResponses!.first.message!);
@ -329,7 +336,7 @@ class ChatApiClient {
if (response.statusCode == 200) {
userLoginResponse = user.userAutoLoginModelFromJson(response.body);
} else if (response.statusCode == 501 || response.statusCode == 502 || response.statusCode == 503 || response.statusCode == 504) {
getUserCallToken(userid: userid);
await getUserCallToken(userid: userid);
} else {
userLoginResponse = user.userAutoLoginModelFromJson(response.body);
Utils.showToast(userLoginResponse.errorResponses!.first.message!);

@ -3,7 +3,7 @@ import 'package:mohem_flutter_app/ui/marathon/widgets/question_card.dart';
class ApiConsts {
//static String baseUrl = "http://10.200.204.20:2801/"; // Local server
// static String baseUrl = "https://erptstapp.srca.org.sa"; // SRCA server
// static String baseUrl = "https://uat.hmgwebservices.com"; // UAT server
//static String baseUrl = "https://uat.hmgwebservices.com"; // UAT server
static String baseUrl = "https://hmgwebservices.com"; // Live server
static String baseUrlServices = baseUrl + "/Services/"; // server
// static String baseUrlServices = "https://api.cssynapses.com/tangheem/"; // Live server

@ -1,12 +1,11 @@
import 'dart:convert';
import 'dart:io';
import 'package:firebase_core/firebase_core.dart';
import 'package:firebase_messaging/firebase_messaging.dart';
import 'package:flutter/cupertino.dart';
import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart';
import 'package:flutter_local_notifications/flutter_local_notifications.dart';
// import 'package:huawei_hmsavailability/huawei_hmsavailability.dart';
import 'package:huawei_push/huawei_push.dart' as huawei_push;
import 'package:mohem_flutter_app/app_state/app_state.dart';
@ -50,13 +49,8 @@ class AppNotifications {
}
void init(String? firebaseToken, BuildContext context) async {
// if (Platform.isAndroid) {
// hmsApiAvailability = HmsApiAvailability();
// }
this.context = context;
print("Firebase init");
debugPrint("Firebase init");
await requestPermissions();
AppState().setDeviceToken = firebaseToken;
await Permission.notification.isDenied.then((bool value) {
@ -84,30 +78,60 @@ class AppNotifications {
AppState().setDeviceToken = token;
});
if (Platform.isAndroid) {
// await hmsApiAvailability.isHMSAvailable().then((value) async {
if (!(await Utils.isGoogleServicesAvailable())) {
huawei_push.Push.enableLogger();
var result = await huawei_push.Push.setAutoInitEnabled(true);
huawei_push.Push.onNotificationOpenedApp.listen((message) {
// newMessage(toFirebaseRemoteMessage(message));
}, onError: (e) => print(e.toString()));
huawei_push.Push.onMessageReceivedStream.listen((message) {
// newMessage(toFirebaseRemoteMessage(message));
}, onError: (e) => print(e.toString()));
}
// }).catchError((err) {
// print(err);
// });
}
// if (Platform.isAndroid) {
// // await hmsApiAvailability.isHMSAvailable().then((value) async {
// if (!(await Utils.isGoogleServicesAvailable())) {
// huawei_push.Push.enableLogger();
// var result = await huawei_push.Push.setAutoInitEnabled(true);
//
// huawei_push.Push.onNotificationOpenedApp.listen((message) {
// print("onNotificationOpenedApp");
// print(message);
// // newMessage(toFirebaseRemoteMessage(message));
// }, onError: (e) => print(e.toString()));
//
// huawei_push.Push.onMessageReceivedStream.listen((message) {
// print("onMessageReceivedStream");
// print(message);
// // newMessage(toFirebaseRemoteMessage(message));
// }, onError: (e) => print(e.toString()));
// }
// // }).catchError((err) {
// // print(err);
// // });
// }
}
void initHuaweiPush(Function loginCallback) {
Future<void> initHuaweiPush(Function loginCallback) async {
AppState().setIsHuawei = true;
initTokenStream(loginCallback);
huawei_push.Push.enableLogger();
huawei_push.Push.getToken("");
var result = await huawei_push.Push.setAutoInitEnabled(true);
debugPrint("HUAWEI PUSH TOKEN RESULT: $result");
huawei_push.Push.onMessageReceivedStream.listen(onMessageReceived);
//huawei_push.Push.registerBackgroundMessageHandler(huaweiBackgroundMessage);
bool backgroundMessageHandler = await huawei_push.Push.registerBackgroundMessageHandler(huaweiBackgroundMessage);
debugPrint("Huawei Background Message Handler Registered: $backgroundMessageHandler");
initTokenStream(loginCallback);
}
void onMessageReceived(huawei_push.RemoteMessage remoteMessage) {
dynamic data = remoteMessage.data;
if (data != null) {
huawei_push.Push.localNotification(
<String, String>{
huawei_push.HMSLocalNotificationAttr.TITLE: 'DataMessage Received',
huawei_push.HMSLocalNotificationAttr.MESSAGE: data,
},
);
print('onMessageReceived' + 'Data: $data');
RemoteMessage message = RemoteMessage(
data: jsonDecode(remoteMessage.data!),
);
_handleMessage(message);
} else {
print('onMessageReceived' + 'No data is present.');
}
}
// HUAWEI PUSH TOKEN IMPLEMENTATION
@ -122,8 +146,8 @@ class AppNotifications {
Utils.hideLoading(context);
}
Future<void> initTokenStream(Function loginCallback) async {
huawei_push.Push.getTokenStream.listen(_onTokenEvent, onError: _onTokenError).onData((data) {
void initTokenStream(Function loginCallback) {
huawei_push.Push.getTokenStream.listen(_onTokenEvent, onError: _onTokenError).onData((data) async {
AppState().setHuaweiPushToken = data;
debugPrint("HUAWEI PUSH TOKEN: $data");
loginCallback();
@ -211,3 +235,22 @@ Future<void> backgroundMessageHandler(RemoteMessage message) async {
}
}
}
void huaweiBackgroundMessage(huawei_push.RemoteMessage remoteMessage) async {
dynamic data = remoteMessage.data;
if (data != null) {
print(
'Background message is received, sending local notification.',
);
huawei_push.Push.localNotification(
<String, String>{
huawei_push.HMSLocalNotificationAttr.TITLE: '[Headless] DataMessage Received',
huawei_push.HMSLocalNotificationAttr.MESSAGE: data,
},
);
} else {
print(
'Background message is received. There is no data in the message.',
);
}
}

@ -58,7 +58,7 @@ class ChatCallProvider with ChangeNotifier, DiagnosticableTreeMixin {
chatHubConnection!.on("OnOfferAsync", onOfferAsync);
chatHubConnection!.on("OnAnswerOffer", onAnswerOffer);
chatHubConnection!.on("OnHangUpAsync", onHangUpAsync);
chatHubConnection!.on("OnCallDeclinedAsync", onCallDeclinedAsync);
// chatHubConnection!.on("OnCallDeclinedAsync", onCallDeclinedAsync);
// chatHubConnection!.on("OnIncomingCallAsync", OnIncomingCallAsync);
}
@ -85,6 +85,7 @@ class ChatCallProvider with ChangeNotifier, DiagnosticableTreeMixin {
chatProvModel = chatProvmodel;
outGoingCallData = callData;
await initStreams();
await startCall(callType: isVideoCall ? "Video" : "Audio", context: context);
_pc = await creatOfferWithCon();
connectOutgoing();
@ -147,11 +148,21 @@ class ChatCallProvider with ChangeNotifier, DiagnosticableTreeMixin {
if (isCallStarted) {
isIncomingCallLoader = false;
isOutGoingCall = true;
Navigator.pushReplacement(
providerContext,
MaterialPageRoute(
builder: (BuildContext context) => StartCallPage(),
));
if (Platform.isIOS) {
Future.delayed(Duration(seconds: 2), () {
Navigator.pushReplacement(
providerContext,
MaterialPageRoute(
builder: (BuildContext context) => StartCallPage(),
));
});
} else {
Navigator.pushReplacement(
providerContext,
MaterialPageRoute(
builder: (BuildContext context) => StartCallPage(),
));
}
}
}
}
@ -279,28 +290,77 @@ class ChatCallProvider with ChangeNotifier, DiagnosticableTreeMixin {
}
void onHangUpAsync(List<Object?>? params) {
print("--------------------- onHangUp ASYNC ---------------------------------------");
print("--------------------- onHangUp ASYNC ---------------------------------");
dynamic items = params!.toList();
if (kDebugMode) {
logger.i("res: " + items.toString());
}
endCall(isUserOnline: isUserOnline).then((bool value) {
if (isCallConnected && !AppState().isBackgroundCall) {
// Navigator.of(AppRoutes.navigatorKey.currentContext!).popUntil((route) => false);
Navigator.of(AppRoutes.navigatorKey.currentContext!).popUntil(ModalRoute.withName(AppRoutes.chatDetailed));
isCallConnected = false;
// if (kDebugMode) {
// logger.i("res: " + items.toString());
// }
if (items[0]["id"] != AppState().chatDetails!.response!.id) {
if (kDebugMode) {
print("Call Ended By Other User");
}
if (items[0]["id"] != AppState().chatDetails!.response!.id && !AppState().isBackgroundCall) {
if (kDebugMode) {
print("Popped Due to Another User");
if (isIncomingCall) {
endCall(isUserOnline: isUserOnline).then((bool value) {
if (isCallConnected && isUserOnline) {
isCallConnected = false;
if (!AppState().isLogged) {
Navigator.of(AppRoutes.navigatorKey.currentContext!).pop();
} else {
Navigator.of(AppRoutes.navigatorKey.currentContext!).popUntil(ModalRoute.withName(AppRoutes.dashboard));
}
} else {
Navigator.of(AppRoutes.navigatorKey.currentContext!).pop();
}
});
} else {
if (isOutGoingCall) {
endCall(isUserOnline: isUserOnline).then((bool value) {
if (isCallConnected && isUserOnline) {
isCallConnected = false;
Navigator.of(AppRoutes.navigatorKey.currentContext!).popUntil(ModalRoute.withName(AppRoutes.dashboard));
} else {
Navigator.of(AppRoutes.navigatorKey.currentContext!).pop();
}
});
}
Navigator.of(AppRoutes.navigatorKey.currentContext!).pop();
}
if (AppState().isBackgroundCall) {
Navigator.of(AppRoutes.navigatorKey.currentContext!).pop();
} else {
if (kDebugMode) {
print("Call Ended By Me");
}
isCallEnded = true;
});
if (isOutGoingCall) {
if (isCallConnected && isUserOnline) {
isCallConnected = false;
Navigator.of(AppRoutes.navigatorKey.currentContext!).popUntil(ModalRoute.withName(AppRoutes.chatDetailed));
} else {
Navigator.of(AppRoutes.navigatorKey.currentContext!).pop();
}
}
}
// endCall(isUserOnline: isUserOnline).then((bool value) {
// if (isCallConnected && isUserOnline) {
// Navigator.of(AppRoutes.navigatorKey.currentContext!).popUntil(ModalRoute.withName(AppRoutes.chatDetailed));
// isCallConnected = false;
// }
// if (items[0]["id"] != AppState().chatDetails!.response!.id && !AppState().isBackgroundCall) {
// if (kDebugMode) {
// print("Popped Due to Another User");
// }
// if (AppState().isBackgroundCall) {
// Navigator.of(AppRoutes.navigatorKey.currentContext!).pop();
// // Navigator.of(AppRoutes.navigatorKey.currentContext!).popUntil(ModalRoute.withName(AppRoutes.login));
// } else {
// Navigator.of(AppRoutes.navigatorKey.currentContext!).popUntil(ModalRoute.withName(AppRoutes.chat));
// }
// }
// if (AppState().isBackgroundCall) {
// Navigator.of(AppRoutes.navigatorKey.currentContext!).pop();
// }
//
notifyListeners();
isCallEnded = true;
// });
}
// Future<void> OnIncomingCallAsync(List<Object?>? params) async {
@ -362,15 +422,15 @@ class ChatCallProvider with ChangeNotifier, DiagnosticableTreeMixin {
// notifyListeners();
// }
// });
if (params != null) {
endCall(isUserOnline: isUserOnline).then((bool value) {
// if (isCallConnected) {
Navigator.of(AppRoutes.navigatorKey.currentContext!).pop();
// isCallConnected = false;
// }
isCallEnded = true;
});
}
// if (params != null) {
// endCall(isUserOnline: isUserOnline).then((bool value) {
// if (isCallConnected) {
// // Navigator.of(AppRoutes.navigatorKey.currentContext!).pop();
// isCallConnected = false;
// }
// isCallEnded = true;
// });
// }
}
//// Invoke Methods
@ -593,16 +653,18 @@ class ChatCallProvider with ChangeNotifier, DiagnosticableTreeMixin {
await localVideoRenderer!.initialize();
try {
_localStream = await navigator.mediaDevices.getUserMedia({
'audio': false,
'video': {
'mandatory': {
'minWidth': '640', // Provide your own width, height and frame rate here
'minHeight': '480',
'minFrameRate': '30',
},
'facingMode': 'user',
'optional': [],
}
'audio': true,
'video': isVideoCall
? {
'mandatory': {
'minWidth': '640', // Provide your own width, height and frame rate here
'minHeight': '480',
'minFrameRate': '30',
},
'facingMode': 'user',
'optional': [],
}
: false
});
if (kDebugMode) {
print(_localStream..toString());

@ -29,6 +29,7 @@ class StartCallPage extends StatefulWidget {
IosCallPayload? payload;
StartCallPage({this.payload});
@override
_StartCallPageState createState() => _StartCallPageState();
}
@ -88,6 +89,7 @@ class _StartCallPageState extends State<StartCallPage> {
}
void startIosCall() async {
print("🎈 Call Payload:" + widget.payload!.toRawJson());
// IosCallPayload? iosCallPayload = IosCallPayload.fromRawJson(await Utils.getStringFromPrefs("iosCallPayload"));
IosCallPayload? iosCallPayload = widget.payload;
var userID = iosCallPayload!.incomingCallReciverId;
@ -231,7 +233,7 @@ class _StartCallPageState extends State<StartCallPage> {
),
10.height,
Text(
prov.incomingCallData.targetUserName!,
prov.incomingCallData.targetUserName ?? "",
style: const TextStyle(
fontSize: 21,
decoration: TextDecoration.none,
@ -299,40 +301,42 @@ class _StartCallPageState extends State<StartCallPage> {
size: 30.0,
),
),
RawMaterialButton(
constraints: const BoxConstraints(),
onPressed: () {
prov.camOff();
},
elevation: 2.0,
fillColor: prov.isCamOff ? MyColors.textMixColor : Colors.grey,
padding: const EdgeInsets.all(
10.0,
),
shape: const CircleBorder(),
child: Icon(
prov.isCamOff ? Icons.videocam_off : Icons.videocam,
color: MyColors.white,
size: 30.0,
),
),
RawMaterialButton(
constraints: const BoxConstraints(),
onPressed: () {
prov.switchCamera();
},
elevation: 2.0,
fillColor: prov.isFrontCamera ? Colors.grey : MyColors.textMixColor,
padding: const EdgeInsets.all(
10.0,
if (prov.isVideoCall)
RawMaterialButton(
constraints: const BoxConstraints(),
onPressed: () {
prov.camOff();
},
elevation: 2.0,
fillColor: prov.isCamOff ? MyColors.textMixColor : Colors.grey,
padding: const EdgeInsets.all(
10.0,
),
shape: const CircleBorder(),
child: Icon(
prov.isCamOff ? Icons.videocam_off : Icons.videocam,
color: MyColors.white,
size: 30.0,
),
),
shape: const CircleBorder(),
child: Icon(
prov.isFrontCamera ? Icons.switch_camera_outlined : Icons.switch_camera,
color: MyColors.white,
size: 30.0,
if (prov.isVideoCall)
RawMaterialButton(
constraints: const BoxConstraints(),
onPressed: () {
prov.switchCamera();
},
elevation: 2.0,
fillColor: prov.isFrontCamera ? Colors.grey : MyColors.textMixColor,
padding: const EdgeInsets.all(
10.0,
),
shape: const CircleBorder(),
child: Icon(
prov.isFrontCamera ? Icons.switch_camera_outlined : Icons.switch_camera,
color: MyColors.white,
size: 30.0,
),
),
),
RawMaterialButton(
constraints: const BoxConstraints(),
onPressed: () {
@ -523,40 +527,43 @@ class _StartCallPageState extends State<StartCallPage> {
size: 30.0,
),
),
RawMaterialButton(
constraints: const BoxConstraints(),
onPressed: () {
prov.camOff();
},
elevation: 2.0,
fillColor: prov.isCamOff ? MyColors.textMixColor : Colors.grey,
padding: const EdgeInsets.all(
10.0,
),
shape: const CircleBorder(),
child: Icon(
prov.isCamOff ? Icons.videocam_off : Icons.videocam,
color: MyColors.white,
size: 30.0,
),
),
RawMaterialButton(
constraints: const BoxConstraints(),
onPressed: () {
prov.switchCamera();
},
elevation: 2.0,
fillColor: prov.isFrontCamera ? Colors.grey : MyColors.textMixColor,
padding: const EdgeInsets.all(
10.0,
if (prov.isVideoCall)
RawMaterialButton(
constraints: const BoxConstraints(),
onPressed: () {
prov.camOff();
},
elevation: 2.0,
fillColor: prov.isCamOff ? MyColors.textMixColor : Colors.grey,
padding: const EdgeInsets.all(
10.0,
),
shape: const CircleBorder(),
child: Icon(
prov.isCamOff ? Icons.videocam_off : Icons.videocam,
color: MyColors.white,
size: 30.0,
),
),
shape: const CircleBorder(),
child: Icon(
prov.isFrontCamera ? Icons.switch_camera_outlined : Icons.switch_camera,
color: MyColors.white,
size: 30.0,
if (prov.isVideoCall)
RawMaterialButton(
constraints: const BoxConstraints(),
onPressed: () {
prov.switchCamera();
},
elevation: 2.0,
fillColor: prov.isFrontCamera ? Colors.grey : MyColors.textMixColor,
padding: const EdgeInsets.all(
10.0,
),
shape: const CircleBorder(),
child: Icon(
prov.isFrontCamera ? Icons.switch_camera_outlined : Icons.switch_camera,
color: MyColors.white,
size: 30.0,
),
),
),
RawMaterialButton(
constraints: const BoxConstraints(),
onPressed: () {

@ -57,9 +57,10 @@ class _OutGoingCallState extends State<OutGoingCall> {
init();
return Scaffold(
body: Consumer<ChatCallProvider>(builder: (BuildContext context, ChatCallProvider chatcp, Widget? child) {
if (chatcp.isCallEnded) {
Navigator.pop(context);
}
// if (chatcp.isCallEnded) {
// Navigator.pop(context);
// }
return loader
? const Center(
child: CircularProgressIndicator(),
@ -159,8 +160,6 @@ class _OutGoingCallState extends State<OutGoingCall> {
chatcp.endCall(isUserOnline: chatProvider.isUserOnline).then((bool value) {
if (value) {
Navigator.of(context).pop();
// print("Reintiiiiiiitttzzzz");
// chatcp.initStreams();
}
});
},

@ -112,12 +112,12 @@ class _ChatDetailScreenState extends State<ChatDetailScreen> {
// if (Platform.isAndroid)
SvgPicture.asset("assets/icons/chat/video_call.svg", width: 21, height: 18).onPress(() async {
Future<PermissionStatus> camPer = Permission.camera.request();
if (await camPer.isGranted) {
Future<PermissionStatus> micPer = Permission.microphone.request();
if (await camPer.isGranted && await micPer.isGranted) {
makeCall(callType: "VIDEO");
} else {
Permission.camera.request().isGranted.then((value) {
makeCall(callType: "VIDEO");
});
if (await Permission.camera.request().isGranted && await Permission.microphone.isGranted) makeCall(callType: "VIDEO");
}
}),
// if (Platform.isAndroid)

@ -111,6 +111,8 @@ class _LoginScreenState extends State<LoginScreen> with WidgetsBindingObserver {
voIPKit.onDidReceiveIncomingPush = (
Map<String, dynamic> payload,
) async {
print("🎈 Call Payload Incoming Push:");
print(payload);
_iosCallPayload = IosCallPayload.fromJson(payload);
_timeOut();
};
@ -163,25 +165,35 @@ class _LoginScreenState extends State<LoginScreen> with WidgetsBindingObserver {
}
// _iosCallPayload = IosCallPayload(uuid: "3423434-423423-43-53-5", incomingCallerId: "266642", incomingCallReciverId: "341682", incomingCallerName: null, incomingCallType: "video");
print("🎈 Call Payload callDetails:" + callDetails);
print("🎈 Call Payload Before:" + _iosCallPayload!.toRawJson());
if (_iosCallPayload!.incomingCallerName == null) {
if (Platform.isIOS) {
Utils.hideLoading(context);
}
// await Utils.saveStringFromPrefs("iosCallPayload", jsonEncode(_iosCallPayload));
// Utils.showToast("Name Null", longDuration: true);
MaterialPageRoute pageRoute = await MaterialPageRoute(
builder: (BuildContext context) => StartCallPage(
payload: _iosCallPayload,
));
Navigator.push(context, pageRoute);
if (Platform.isIOS) {
Future.delayed(Duration(seconds: 3), () async {
MaterialPageRoute pageRoute = await MaterialPageRoute(
builder: (BuildContext context) => StartCallPage(
payload: _iosCallPayload,
));
Navigator.push(context, pageRoute);
});
}
} else if (AppState().getisUserOnline) {
// await Utils.saveStringFromPrefs("iosCallPayload", jsonEncode(_iosCallPayload));
BuildContext context = AppRoutes.navigatorKey.currentContext!;
MaterialPageRoute pageRoute = await MaterialPageRoute(
builder: (BuildContext context) => StartCallPage(
payload: _iosCallPayload,
));
Navigator.push(context, pageRoute);
if (Platform.isIOS) {
Future.delayed(Duration(seconds: 3), () async {
MaterialPageRoute pageRoute = await MaterialPageRoute(
builder: (BuildContext context) => StartCallPage(
payload: _iosCallPayload,
));
Navigator.push(context, pageRoute);
});
}
} else {
FlutterCallkitIncoming.endAllCalls();
Utils.showToast("Something wen't wrong");
@ -296,8 +308,8 @@ class _LoginScreenState extends State<LoginScreen> with WidgetsBindingObserver {
if (Platform.isAndroid) {
try {
if (!(await Utils.isGoogleServicesAvailable())) {
print("HUAWEI APPPP GALLERYYYY!!!!");
AppNotifications().init(firebaseToken, context);
debugPrint("HUAWEI APPPP GALLERYYYY!!!!");
// AppNotifications().init(firebaseToken, context);
AppState().setIsHuawei = true;
AppNotifications().initHuaweiPush(checkLoginInfo);
} else {

Loading…
Cancel
Save