Merge branch 'zik_new_design_flutter_v2.5' into 'development_v2.5'
Zik new design flutter v2.5 See merge request Cloud_Solution/diplomatic-quarter!570merge-requests/571/merge
commit
0ae4a13c02
@ -1,4 +1,27 @@
|
||||
-keep class tvi.webrtc.** { *; }
|
||||
-keep class com.twilio.video.** { *; }
|
||||
-keep class com.twilio.common.** { *; }
|
||||
-keepattributes InnerClasses
|
||||
-keepattributes InnerClasses
|
||||
|
||||
-keep class com.ejada.** { *; }
|
||||
-keep class org.webrtc.** { *; }
|
||||
|
||||
-ignorewarnings
|
||||
-keepattributes *Annotation*
|
||||
-keepattributes Exceptions
|
||||
-keepattributes InnerClasses
|
||||
-keepattributes Signature
|
||||
-keep class com.hianalytics.android.**{*;}
|
||||
-keep class com.huawei.updatesdk.**{*;}
|
||||
-keep class com.huawei.hms.**{*;}
|
||||
|
||||
## Flutter wrapper
|
||||
-keep class io.flutter.app.** { *; }
|
||||
-keep class io.flutter.plugin.** { *; }
|
||||
-keep class io.flutter.util.** { *; }
|
||||
-keep class io.flutter.view.** { *; }
|
||||
-keep class io.flutter.** { *; }
|
||||
-keep class io.flutter.plugins.** { *; }
|
||||
-dontwarn io.flutter.embedding.**
|
||||
-keep class com.huawei.hms.flutter.** { *; }
|
||||
-repackageclasses
|
||||
@ -0,0 +1,56 @@
|
||||
/*
|
||||
* ---------------
|
||||
* Note: Todo
|
||||
* ---------------
|
||||
* Need to be place in huawei_push (package com.huawei.hms.flutter.push.hms) and define in huawei_push manifest.xml
|
||||
* */
|
||||
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.content.SharedPreferences;
|
||||
import android.util.Log;
|
||||
|
||||
import com.huawei.hms.flutter.push.hms.FlutterHmsMessageService;
|
||||
import com.huawei.hms.flutter.push.utils.ApplicationUtils;
|
||||
|
||||
import org.json.JSONObject;
|
||||
|
||||
//package com.huawei.hms.flutter.push.hms
|
||||
//
|
||||
//
|
||||
//import android.content.Context;
|
||||
//import android.content.Intent;
|
||||
//import android.content.SharedPreferences;
|
||||
//
|
||||
//import com.huawei.hms.flutter.push.hms.FlutterHmsMessageService;
|
||||
//import com.huawei.hms.flutter.push.utils.ApplicationUtils;
|
||||
//import com.huawei.hms.push.RemoteMessage;
|
||||
//
|
||||
//import org.json.JSONObject;
|
||||
//
|
||||
//public class CustomFlutterHmsMessageService extends FlutterHmsMessageService {
|
||||
// @Override
|
||||
// public void onMessageReceived(RemoteMessage remoteMessage) {
|
||||
// super.onMessageReceived(remoteMessage);
|
||||
// try {
|
||||
// String jsonStr = remoteMessage.getData();
|
||||
// JSONObject json_data = new JSONObject(jsonStr);
|
||||
// JSONObject json_data_data = new JSONObject(json_data.getString("data"));
|
||||
// if(json_data_data.getString("is_call").equalsIgnoreCase("true")){
|
||||
// boolean isApplicationInForeground = ApplicationUtils.isApplicationInForeground(this);
|
||||
// if(!isApplicationInForeground){
|
||||
// SharedPreferences preferences = getSharedPreferences("FlutterSharedPreferences", Context.MODE_PRIVATE);
|
||||
// preferences.edit().putString("flutter.call_data", json_data.getString("data")).apply();
|
||||
//
|
||||
// Intent intent = getPackageManager().getLaunchIntentForPackage(getPackageName());
|
||||
// intent.addFlags(Intent.FLAG_ACTIVITY_REORDER_TO_FRONT);
|
||||
// startActivity(intent);
|
||||
// Log.v("onMessageReceived", "startActivity(intent) called");
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// } catch (Exception e) {
|
||||
// e.printStackTrace();
|
||||
// }
|
||||
// }
|
||||
//}
|
||||
File diff suppressed because it is too large
Load Diff
@ -1,216 +1,61 @@
|
||||
import 'dart:async';
|
||||
|
||||
import 'package:diplomaticquarterapp/pages/conference/web_rtc/widgets/cam_view_widget.dart';
|
||||
import 'package:diplomaticquarterapp/pages/conference/widgets/noise_box.dart';
|
||||
import 'package:diplomaticquarterapp/pages/webRTC/call_page.dart';
|
||||
import 'package:diplomaticquarterapp/pages/webRTC/signaling.dart';
|
||||
import 'package:diplomaticquarterapp/uitl/SignalRUtil.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter/services.dart';
|
||||
import 'package:flutter_webrtc/flutter_webrtc.dart';
|
||||
|
||||
import '../conference_button_bar.dart';
|
||||
|
||||
class CallHomePage extends StatefulWidget {
|
||||
final String receiverId;
|
||||
final String callerId;
|
||||
|
||||
const CallHomePage({Key key, this.receiverId, this.callerId}) : super(key: key);
|
||||
|
||||
@override
|
||||
_CallHomePageState createState() => _CallHomePageState();
|
||||
}
|
||||
|
||||
class _CallHomePageState extends State<CallHomePage> {
|
||||
bool showNoise = false;
|
||||
RTCVideoRenderer _localRenderer = RTCVideoRenderer();
|
||||
RTCVideoRenderer _remoteRenderer = RTCVideoRenderer();
|
||||
|
||||
final StreamController<bool> _audioButton = StreamController<bool>.broadcast();
|
||||
final StreamController<bool> _videoButton = StreamController<bool>.broadcast();
|
||||
final StreamController<bool> _onButtonBarVisibleStreamController = StreamController<bool>.broadcast();
|
||||
final StreamController<double> _onButtonBarHeightStreamController = StreamController<double>.broadcast();
|
||||
|
||||
//Stream to enable video
|
||||
MediaStream localMediaStream;
|
||||
MediaStream remoteMediaStream;
|
||||
Signaling signaling = Signaling()..init();
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
// TODO: implement initState
|
||||
super.initState();
|
||||
startCall();
|
||||
}
|
||||
|
||||
startCall() async{
|
||||
await _localRenderer.initialize();
|
||||
await _remoteRenderer.initialize();
|
||||
final connected = await receivedCall();
|
||||
}
|
||||
|
||||
|
||||
Future<bool> receivedCall() async {
|
||||
//Stream local media
|
||||
localMediaStream = await navigator.mediaDevices.getUserMedia({'video': true, 'audio': true});
|
||||
_localRenderer.srcObject = localMediaStream;
|
||||
|
||||
final connected = await signaling.acceptCall(widget.callerId, widget.receiverId, localMediaStream: localMediaStream, onRemoteMediaStream: (remoteMediaStream){
|
||||
this.remoteMediaStream = remoteMediaStream;
|
||||
_remoteRenderer.srcObject = remoteMediaStream;
|
||||
});
|
||||
|
||||
if(connected){
|
||||
signaling.signalR.listen(
|
||||
onAcceptCall: (arg0){
|
||||
print(arg0.toString());
|
||||
},
|
||||
onCandidate: (candidateJson){
|
||||
signaling.addCandidate(candidateJson);
|
||||
},
|
||||
onDeclineCall: (arg0,arg1){
|
||||
// _onHangup();
|
||||
},
|
||||
onHangupCall: (arg0){
|
||||
// _onHangup();
|
||||
},
|
||||
|
||||
onOffer: (offerSdp, callerUser) async{
|
||||
print('${offerSdp.toString()} | ${callerUser.toString()}');
|
||||
await signaling.answerOffer(offerSdp);
|
||||
}
|
||||
);
|
||||
}
|
||||
return connected;
|
||||
}
|
||||
|
||||
@override
|
||||
void dispose() {
|
||||
// TODO: implement dispose
|
||||
super.dispose();
|
||||
_localRenderer?.dispose();
|
||||
_remoteRenderer?.dispose();
|
||||
_audioButton?.close();
|
||||
_videoButton?.close();
|
||||
localMediaStream?.dispose();
|
||||
remoteMediaStream?.dispose();
|
||||
_disposeStreamsAndSubscriptions();
|
||||
}
|
||||
|
||||
Future<void> _disposeStreamsAndSubscriptions() async {
|
||||
if (_onButtonBarVisibleStreamController != null) await _onButtonBarVisibleStreamController.close();
|
||||
if (_onButtonBarHeightStreamController != null) await _onButtonBarHeightStreamController.close();
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
// return WillPopScope(
|
||||
// onWillPop: () async => false,
|
||||
// child: Scaffold(
|
||||
// backgroundColor: Colors.black,
|
||||
// // body: ,
|
||||
// ),
|
||||
// );
|
||||
|
||||
return Scaffold(
|
||||
backgroundColor: Colors.white,
|
||||
body: showNoise ? _buildNoiseBox() : buildLayout(),
|
||||
);
|
||||
}
|
||||
|
||||
LayoutBuilder buildLayout() {
|
||||
return LayoutBuilder(
|
||||
builder: (BuildContext context, BoxConstraints constraints) {
|
||||
return Stack(
|
||||
children: [
|
||||
CamViewWidget(
|
||||
localRenderer: _localRenderer,
|
||||
remoteRenderer: _remoteRenderer,
|
||||
constraints: constraints,
|
||||
onButtonBarVisibleStreamController: _onButtonBarVisibleStreamController,
|
||||
onButtonBarHeightStreamController: _onButtonBarHeightStreamController,
|
||||
),
|
||||
ConferenceButtonBar(
|
||||
audioEnabled: _audioButton.stream,
|
||||
videoEnabled: _videoButton.stream,
|
||||
onAudioEnabled: _onAudioEnable,
|
||||
onVideoEnabled: _onVideoEnabled,
|
||||
onSwitchCamera: _onSwitchCamera,
|
||||
onHangup: _onHangup,
|
||||
onPersonAdd: () {},
|
||||
onPersonRemove: () {},
|
||||
onHeight: _onHeightBar,
|
||||
onShow: _onShowBar,
|
||||
onHide: _onHideBar,
|
||||
),
|
||||
],
|
||||
);
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
NoiseBox _buildNoiseBox() {
|
||||
return NoiseBox(
|
||||
density: NoiseBoxDensity.xLow,
|
||||
backgroundColor: Colors.grey.shade900,
|
||||
child: Center(
|
||||
child: Container(
|
||||
color: Colors.black54,
|
||||
width: double.infinity,
|
||||
height: 40,
|
||||
child: Center(
|
||||
child: Text(
|
||||
'Waiting for another participant to connect to the call...',
|
||||
key: Key('text-wait'),
|
||||
textAlign: TextAlign.center,
|
||||
style: TextStyle(color: Colors.white),
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
Function _onAudioEnable() {
|
||||
final audioTrack = localMediaStream.getAudioTracks()[0];
|
||||
final mute = audioTrack.muted;
|
||||
Helper.setMicrophoneMute(!mute, audioTrack);
|
||||
_audioButton.add(mute);
|
||||
}
|
||||
|
||||
Function _onVideoEnabled() {
|
||||
final videoTrack = localMediaStream.getVideoTracks()[0];
|
||||
bool videoEnabled = videoTrack.enabled;
|
||||
localMediaStream.getVideoTracks()[0].enabled = !videoEnabled;
|
||||
_videoButton.add(!videoEnabled);
|
||||
}
|
||||
|
||||
Function _onSwitchCamera() {
|
||||
Helper.switchCamera(localMediaStream.getVideoTracks()[0]);
|
||||
}
|
||||
|
||||
void _onShowBar() {
|
||||
setState(() {
|
||||
});
|
||||
_onButtonBarVisibleStreamController.add(true);
|
||||
}
|
||||
|
||||
void _onHeightBar(double height) {
|
||||
_onButtonBarHeightStreamController.add(height);
|
||||
}
|
||||
|
||||
void _onHideBar() {
|
||||
setState(() {
|
||||
SystemChrome.setEnabledSystemUIOverlays([SystemUiOverlay.bottom]);
|
||||
});
|
||||
_onButtonBarVisibleStreamController.add(false);
|
||||
}
|
||||
|
||||
Future<void> _onHangup() async {
|
||||
signaling.hangupCall(widget.callerId, widget.receiverId);
|
||||
print('onHangup');
|
||||
Navigator.of(context).pop();
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
// import 'dart:async';
|
||||
//
|
||||
// import 'package:diplomaticquarterapp/pages/conference/web_rtc/widgets/cam_view_widget.dart';
|
||||
// import 'package:diplomaticquarterapp/pages/conference/widgets/noise_box.dart';
|
||||
// import 'package:diplomaticquarterapp/pages/webRTC/signaling.dart';
|
||||
// import 'package:flutter/material.dart';
|
||||
// import 'package:flutter/services.dart';
|
||||
// // import 'package:flutter_webrtc/flutter_webrtc.dart';
|
||||
//
|
||||
// import '../conference_button_bar.dart';
|
||||
//
|
||||
// class CallHomePage extends StatefulWidget {
|
||||
// final String receiverId;
|
||||
// final String callerId;
|
||||
//
|
||||
// const CallHomePage({Key key, this.receiverId, this.callerId}) : super(key: key);
|
||||
//
|
||||
// @override
|
||||
// _CallHomePageState createState() => _CallHomePageState();
|
||||
// }
|
||||
//
|
||||
// class _CallHomePageState extends State<CallHomePage> {
|
||||
// bool showNoise = false;
|
||||
// // RTCVideoRenderer _localRenderer = RTCVideoRenderer();
|
||||
// // RTCVideoRenderer _remoteRenderer = RTCVideoRenderer();
|
||||
//
|
||||
// final StreamController<bool> _audioButton = StreamController<bool>.broadcast();
|
||||
// final StreamController<bool> _videoButton = StreamController<bool>.broadcast();
|
||||
// final StreamController<bool> _onButtonBarVisibleStreamController = StreamController<bool>.broadcast();
|
||||
// final StreamController<double> _onButtonBarHeightStreamController = StreamController<double>.broadcast();
|
||||
//
|
||||
// //Stream to enable video
|
||||
// // MediaStream localMediaStream;
|
||||
// // MediaStream remoteMediaStream;
|
||||
// Signaling signaling = Signaling()..init();
|
||||
//
|
||||
// @override
|
||||
// void initState() {
|
||||
// // TODO: implement initState
|
||||
// super.initState();
|
||||
// startCall();
|
||||
// }
|
||||
//
|
||||
// startCall() async{
|
||||
// // await _localRenderer.initialize();
|
||||
// // await _remoteRenderer.initialize();
|
||||
// }
|
||||
//
|
||||
// Future<void> _disposeStreamsAndSubscriptions() async {
|
||||
// if (_onButtonBarVisibleStreamController != null) await _onButtonBarVisibleStreamController.close();
|
||||
// if (_onButtonBarHeightStreamController != null) await _onButtonBarHeightStreamController.close();
|
||||
// }
|
||||
//
|
||||
// @override
|
||||
// Widget build(BuildContext context) {
|
||||
// return Scaffold(
|
||||
// backgroundColor: Colors.white,
|
||||
// body: Container() //showNoise ? _buildNoiseBox() : buildLayout(),
|
||||
// );
|
||||
// }
|
||||
// }
|
||||
|
||||
@ -0,0 +1,186 @@
|
||||
import 'dart:async';
|
||||
|
||||
import 'package:diplomaticquarterapp/pages/conference/web_rtc/widgets/cam_view_widget.dart';
|
||||
import 'package:diplomaticquarterapp/pages/conference/widgets/noise_box.dart';
|
||||
import 'package:diplomaticquarterapp/pages/webRTC/signaling.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter/services.dart';
|
||||
import 'package:flutter_webrtc/flutter_webrtc.dart';
|
||||
|
||||
import '../conference_button_bar.dart';
|
||||
|
||||
class CallHomePage extends StatefulWidget {
|
||||
final String receiverId;
|
||||
final String callerId;
|
||||
|
||||
const CallHomePage({Key key, this.receiverId, this.callerId}) : super(key: key);
|
||||
|
||||
@override
|
||||
_CallHomePageState createState() => _CallHomePageState();
|
||||
}
|
||||
|
||||
class _CallHomePageState extends State<CallHomePage> {
|
||||
bool showNoise = true;
|
||||
RTCVideoRenderer _localRenderer = RTCVideoRenderer();
|
||||
RTCVideoRenderer _remoteRenderer = RTCVideoRenderer();
|
||||
|
||||
final StreamController<bool> _audioButton = StreamController<bool>.broadcast();
|
||||
final StreamController<bool> _videoButton = StreamController<bool>.broadcast();
|
||||
final StreamController<bool> _onButtonBarVisibleStreamController = StreamController<bool>.broadcast();
|
||||
final StreamController<double> _onButtonBarHeightStreamController = StreamController<double>.broadcast();
|
||||
|
||||
//Stream to enable video
|
||||
MediaStream localMediaStream;
|
||||
MediaStream remoteMediaStream;
|
||||
Signaling signaling = Signaling()..init();
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
// TODO: implement initState
|
||||
super.initState();
|
||||
startCall();
|
||||
}
|
||||
|
||||
startCall() async{
|
||||
await _localRenderer.initialize();
|
||||
await _remoteRenderer.initialize();
|
||||
final connected = await receivedCall();
|
||||
}
|
||||
|
||||
|
||||
Future<bool> receivedCall() async {
|
||||
//Stream local media
|
||||
localMediaStream = await navigator.mediaDevices.getUserMedia({'video': true, 'audio': true});
|
||||
_localRenderer.srcObject = localMediaStream;
|
||||
|
||||
final connected = await signaling.acceptCall(widget.callerId, widget.receiverId, localMediaStream: localMediaStream, onRemoteMediaStream: (remoteMediaStream){
|
||||
setState(() {
|
||||
this.remoteMediaStream = remoteMediaStream;
|
||||
_remoteRenderer.srcObject = remoteMediaStream;
|
||||
});
|
||||
});
|
||||
|
||||
if(connected){
|
||||
signaling.signalR.listen(
|
||||
onAcceptCall: (arg0){
|
||||
print(arg0.toString());
|
||||
},
|
||||
onCandidate: (candidateJson){
|
||||
signaling.addCandidate(candidateJson);
|
||||
},
|
||||
onDeclineCall: (arg0,arg1){
|
||||
// _onHangup();
|
||||
},
|
||||
onHangupCall: (arg0){
|
||||
// _onHangup();
|
||||
},
|
||||
|
||||
onOffer: (offerSdp, callerUser) async{
|
||||
print('${offerSdp.toString()} | ${callerUser.toString()}');
|
||||
await signaling.answerOffer(offerSdp);
|
||||
}
|
||||
);
|
||||
}
|
||||
return connected;
|
||||
}
|
||||
|
||||
@override
|
||||
void dispose() {
|
||||
// TODO: implement dispose
|
||||
super.dispose();
|
||||
_localRenderer?.dispose();
|
||||
_remoteRenderer?.dispose();
|
||||
_audioButton?.close();
|
||||
_videoButton?.close();
|
||||
localMediaStream?.dispose();
|
||||
remoteMediaStream?.dispose();
|
||||
_disposeStreamsAndSubscriptions();
|
||||
}
|
||||
|
||||
Future<void> _disposeStreamsAndSubscriptions() async {
|
||||
if (_onButtonBarVisibleStreamController != null) await _onButtonBarVisibleStreamController.close();
|
||||
if (_onButtonBarHeightStreamController != null) await _onButtonBarHeightStreamController.close();
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Scaffold(
|
||||
backgroundColor: Colors.white,
|
||||
body: buildLayout(),
|
||||
);
|
||||
}
|
||||
|
||||
LayoutBuilder buildLayout() {
|
||||
return LayoutBuilder(
|
||||
builder: (BuildContext context, BoxConstraints constraints) {
|
||||
return Stack(
|
||||
children: [
|
||||
CamViewWidget(
|
||||
localRenderer: _localRenderer,
|
||||
remoteRenderer: _remoteRenderer,
|
||||
constraints: constraints,
|
||||
onButtonBarVisibleStreamController: _onButtonBarVisibleStreamController,
|
||||
onButtonBarHeightStreamController: _onButtonBarHeightStreamController,
|
||||
),
|
||||
ConferenceButtonBar(
|
||||
audioEnabled: _audioButton.stream,
|
||||
videoEnabled: _videoButton.stream,
|
||||
onAudioEnabled: _onAudioEnable,
|
||||
onVideoEnabled: _onVideoEnabled,
|
||||
onSwitchCamera: _onSwitchCamera,
|
||||
onHangup: _onHangup,
|
||||
onPersonAdd: () {},
|
||||
onPersonRemove: () {},
|
||||
onHeight: _onHeightBar,
|
||||
onShow: _onShowBar,
|
||||
onHide: _onHideBar,
|
||||
),
|
||||
],
|
||||
);
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
Function _onAudioEnable() {
|
||||
final audioTrack = localMediaStream.getAudioTracks()[0];
|
||||
final mute = audioTrack.muted;
|
||||
Helper.setMicrophoneMute(!mute, audioTrack);
|
||||
_audioButton.add(mute);
|
||||
}
|
||||
|
||||
Function _onVideoEnabled() {
|
||||
final videoTrack = localMediaStream.getVideoTracks()[0];
|
||||
bool videoEnabled = videoTrack.enabled;
|
||||
localMediaStream.getVideoTracks()[0].enabled = !videoEnabled;
|
||||
_videoButton.add(!videoEnabled);
|
||||
}
|
||||
|
||||
Function _onSwitchCamera() {
|
||||
Helper.switchCamera(localMediaStream.getVideoTracks()[0]);
|
||||
}
|
||||
|
||||
void _onShowBar() {
|
||||
setState(() {
|
||||
});
|
||||
_onButtonBarVisibleStreamController.add(true);
|
||||
}
|
||||
|
||||
void _onHeightBar(double height) {
|
||||
_onButtonBarHeightStreamController.add(height);
|
||||
}
|
||||
|
||||
void _onHideBar() {
|
||||
setState(() {
|
||||
SystemChrome.setEnabledSystemUIOverlays([SystemUiOverlay.bottom]);
|
||||
});
|
||||
_onButtonBarVisibleStreamController.add(false);
|
||||
}
|
||||
|
||||
Future<void> _onHangup() async {
|
||||
signaling.hangupCall(widget.callerId, widget.receiverId);
|
||||
print('onHangup');
|
||||
Navigator.of(context).pop();
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@ -0,0 +1,37 @@
|
||||
import 'dart:io';
|
||||
|
||||
import 'package:diplomaticquarterapp/uitl/translations_delegate_base.dart';
|
||||
import 'package:diplomaticquarterapp/widgets/dialogs/confirm_dialog.dart';
|
||||
import 'package:flutter/cupertino.dart';
|
||||
import 'package:permission_handler/permission_handler.dart';
|
||||
|
||||
import 'PlatformBridge.dart';
|
||||
|
||||
class AppPermission{
|
||||
|
||||
|
||||
static Future<bool> askVideoCallPermission(BuildContext context) async {
|
||||
if (!(await Permission.camera.request().isGranted) || !(await Permission.microphone.request().isGranted)) {
|
||||
return false;
|
||||
}
|
||||
if (Platform.isAndroid && !(await PlatformBridge.shared().isDrawOverAppsPermissionAllowed())) {
|
||||
await _drawOverAppsMessageDialog(context);
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
static Future _drawOverAppsMessageDialog(BuildContext context) async {
|
||||
ConfirmDialog dialog = new ConfirmDialog(
|
||||
context: context,
|
||||
confirmMessage: "Please select 'Dr. Alh'abib' from the list and allow draw over app permission to use live care.",
|
||||
okText: TranslationBase.of(context).confirm,
|
||||
cancelText: TranslationBase.of(context).cancel_nocaps,
|
||||
okFunction: () async {
|
||||
await PlatformBridge.shared().askDrawOverAppsPermission();
|
||||
Navigator.pop(context);
|
||||
},
|
||||
cancelFunction: () => {});
|
||||
dialog.showAlertDialog(context);
|
||||
}
|
||||
}
|
||||
@ -1,12 +1,21 @@
|
||||
import 'package:diplomaticquarterapp/locator.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
class NavigationService {
|
||||
final GlobalKey<NavigatorState> navigatorKey =
|
||||
new GlobalKey<NavigatorState>();
|
||||
|
||||
static NavigationService instance = NavigationService();
|
||||
|
||||
Future<dynamic> navigateTo(String routeName) {
|
||||
return navigatorKey.currentState.pushNamed(routeName);
|
||||
static Future<dynamic> navigateTo(String routeName) {
|
||||
final key = locator<NavigationService>().navigatorKey;
|
||||
return key.currentState.pushNamed(routeName);
|
||||
}
|
||||
|
||||
static Future<dynamic> navigateToPage(Widget page) {
|
||||
final key = locator<NavigationService>().navigatorKey;
|
||||
final pageRoute = MaterialPageRoute(builder: (context) => page);
|
||||
return Navigator.push(key.currentContext, pageRoute);
|
||||
}
|
||||
}
|
||||
|
||||
BuildContext get currentContext => locator<NavigationService>().navigatorKey.currentContext;
|
||||
|
||||
@ -0,0 +1,282 @@
|
||||
|
||||
import 'dart:convert';
|
||||
import 'dart:io';
|
||||
import 'package:diplomaticquarterapp/config/config.dart';
|
||||
import 'package:diplomaticquarterapp/config/shared_pref_kay.dart';
|
||||
import 'package:diplomaticquarterapp/models/LiveCare/IncomingCallData.dart';
|
||||
import 'package:diplomaticquarterapp/pages/landing/landing_page.dart';
|
||||
import 'package:diplomaticquarterapp/pages/livecare/incoming_call.dart';
|
||||
import 'package:diplomaticquarterapp/uitl/app-permissions.dart';
|
||||
import 'package:flutter/cupertino.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:huawei_push/huawei_push.dart' as h_push;
|
||||
import 'package:firebase_messaging/firebase_messaging.dart';
|
||||
import 'package:firebase_messaging/firebase_messaging.dart' as fir;
|
||||
import 'package:flutter_hms_gms_availability/flutter_hms_gms_availability.dart';
|
||||
import 'package:shared_preferences/shared_preferences.dart';
|
||||
|
||||
import 'app_shared_preferences.dart';
|
||||
import 'navigation_service.dart';
|
||||
|
||||
|
||||
// |--> Push Notification Background
|
||||
Future<dynamic> backgroundMessageHandler(dynamic message) async{
|
||||
|
||||
fir.RemoteMessage message_;
|
||||
if(message is h_push.RemoteMessage){ // if huawei remote message convert it to Firebase Remote Message
|
||||
message_ = toFirebaseRemoteMessage(message);
|
||||
}
|
||||
|
||||
if (message_.data != null && message_.data['is_call'] == 'true') {
|
||||
_incomingCall(message_.data);
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
print("Background message is received, sending local notification.");
|
||||
h_push.Push.localNotification({
|
||||
h_push.HMSLocalNotificationAttr.TITLE: 'Background Message',
|
||||
h_push.HMSLocalNotificationAttr.MESSAGE: "By: BackgroundMessageHandler"
|
||||
});
|
||||
|
||||
}
|
||||
// Push Notification Background <--|
|
||||
|
||||
|
||||
|
||||
RemoteMessage toFirebaseRemoteMessage(h_push.RemoteMessage message){
|
||||
final payload_data = jsonDecode(message.data);
|
||||
final fire_message = RemoteMessage(
|
||||
from: message.from,
|
||||
collapseKey: message.collapseKey,
|
||||
data: payload_data['data'],
|
||||
messageId: message.messageId,
|
||||
sentTime: DateTime.fromMillisecondsSinceEpoch(message.sentTime*1000),
|
||||
ttl: message.ttl,
|
||||
category: null,
|
||||
messageType: message.type,
|
||||
notification: RemoteNotification(
|
||||
title: message.notification.title,
|
||||
titleLocArgs: (message.notification.titleLocalizationArgs ?? []).map((e) => e.toString()).toList(),
|
||||
titleLocKey: message.notification.titleLocalizationKey,
|
||||
body: message.notification.body,
|
||||
bodyLocArgs: (message.notification.bodyLocalizationArgs ?? []).map((e) => e.toString()).toList(),
|
||||
bodyLocKey: message.notification.bodyLocalizationKey,
|
||||
android: AndroidNotification(
|
||||
channelId: message.notification.channelId,
|
||||
clickAction: message.notification.clickAction,
|
||||
color: message.notification.color,
|
||||
count: null,
|
||||
imageUrl: message.notification.imageUrl.path,
|
||||
link: message.notification.link.path,
|
||||
smallIcon: message.notification.icon,
|
||||
sound: message.notification.sound,
|
||||
ticker: message.notification.ticker,
|
||||
tag: message.notification.tag,
|
||||
),
|
||||
)
|
||||
);
|
||||
return fire_message;
|
||||
}
|
||||
|
||||
_incomingCall(Map data) async{
|
||||
LandingPage.incomingCallData = IncomingCallData.fromJson(data);
|
||||
if(LandingPage.isOpenCallPage == false){
|
||||
LandingPage.isOpenCallPage = true;
|
||||
final permited = await AppPermission.askVideoCallPermission(currentContext);
|
||||
if(permited)
|
||||
await NavigationService.navigateToPage(IncomingCall(incomingCallData: LandingPage.incomingCallData));
|
||||
LandingPage.isOpenCallPage = false;
|
||||
}
|
||||
await Future.delayed(Duration(milliseconds: 500));
|
||||
await AppSharedPreferences().remove('call_data');
|
||||
}
|
||||
|
||||
class PushNotificationHandler{
|
||||
final BuildContext context;
|
||||
static PushNotificationHandler _instance;
|
||||
|
||||
PushNotificationHandler(this.context){
|
||||
PushNotificationHandler._instance = this;
|
||||
}
|
||||
|
||||
static PushNotificationHandler getInstance() => _instance;
|
||||
|
||||
init() async{
|
||||
if (Platform.isIOS) {
|
||||
final permission = await FirebaseMessaging.instance.requestPermission();
|
||||
if(permission.authorizationStatus == AuthorizationStatus.denied)
|
||||
return;
|
||||
}
|
||||
|
||||
if(Platform.isAndroid && (await FlutterHmsGmsAvailability.isHmsAvailable)) { // 'Android HMS' (Handle Huawei Push_Kit Streams)
|
||||
|
||||
h_push.Push.enableLogger();
|
||||
final result = await h_push.Push.setAutoInitEnabled(true);
|
||||
|
||||
h_push.Push.onNotificationOpenedApp.listen((message){
|
||||
newMessage(toFirebaseRemoteMessage(message));
|
||||
}, onError: (e) => print(e.toString()));
|
||||
|
||||
h_push.Push.onMessageReceivedStream.listen((message){
|
||||
newMessage(toFirebaseRemoteMessage(message));
|
||||
}, onError: (e) => print(e.toString()));
|
||||
|
||||
|
||||
h_push.Push.getTokenStream.listen((token){
|
||||
onToken(token);
|
||||
}, onError: (e) => print(e.toString()));
|
||||
await h_push.Push.getToken('');
|
||||
|
||||
|
||||
h_push.Push.registerBackgroundMessageHandler(backgroundMessageHandler);
|
||||
|
||||
}else{ // 'Android GMS or iOS' (Handle Firebase Messaging Streams)
|
||||
|
||||
FirebaseMessaging.onMessage.listen((RemoteMessage message) async {
|
||||
newMessage(message);
|
||||
});
|
||||
|
||||
FirebaseMessaging.onMessageOpenedApp.listen((RemoteMessage message) {
|
||||
newMessage(message);
|
||||
});
|
||||
|
||||
FirebaseMessaging.instance.onTokenRefresh.listen((fcm_token) {
|
||||
onToken(fcm_token);
|
||||
});
|
||||
|
||||
FirebaseMessaging.onBackgroundMessage(backgroundMessageHandler);
|
||||
|
||||
final fcmToken = await FirebaseMessaging.instance.getToken();
|
||||
if(fcmToken != null)
|
||||
onToken(fcmToken);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
newMessage(RemoteMessage remoteMessage){
|
||||
print('RemoteMessage.data:: ${remoteMessage.data}');
|
||||
if(remoteMessage.data['is_call'] == 'true' || remoteMessage.data['is_call'] == true)
|
||||
_incomingCall(remoteMessage.data);
|
||||
|
||||
}
|
||||
|
||||
onToken(String token) async{
|
||||
print("Push Notification Token: " + token);
|
||||
AppSharedPreferences().setString(PUSH_TOKEN, token);
|
||||
DEVICE_TOKEN = token;
|
||||
}
|
||||
|
||||
onResume() async {
|
||||
var call_data = await AppSharedPreferences().getObject('call_data');
|
||||
if(call_data != null){
|
||||
_incomingCall(call_data);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/* todo verify all functionality */
|
||||
// _firebaseMessaging.configure(
|
||||
// // onMessage: (Map<String, dynamic> message) async {
|
||||
// // // showDialog("onMessage: $message");
|
||||
// // print("onMessage: $message");
|
||||
// // print(message);
|
||||
// // print(message['name']);
|
||||
// // print(message['appointmentdate']);
|
||||
// //
|
||||
// // if (Platform.isIOS) {
|
||||
// // if (message['is_call'] == "true") {
|
||||
// // var route = ModalRoute.of(context);
|
||||
// //
|
||||
// // if (route != null) {
|
||||
// // print(route.settings.name);
|
||||
// // }
|
||||
// //s
|
||||
// // Map<String, dynamic> myMap = new Map<String, dynamic>.from(mesage);
|
||||
// // print(myMap);
|
||||
// // LandingPage.isOpenCallPage = true;
|
||||
// // LandingPage.incomingCallData = IncomingCallData.fromJson(myMap);
|
||||
// // if (!isPageNavigated) {
|
||||
// // isPageNavigated = true;
|
||||
// // Navigator.push(context, MaterialPageRoute(builder: (context) => IncomingCall(incomingCallData: LandingPage.incomingCallData))).then((value) {
|
||||
// // isPageNavigated = false;
|
||||
// // });
|
||||
// // }
|
||||
// // } else {
|
||||
// // print("Is Call Not Found iOS");
|
||||
// // }
|
||||
// // } else {
|
||||
// // print("Is Call Not Found iOS");
|
||||
// // }
|
||||
// //
|
||||
// // if (Platform.isAndroid) {
|
||||
// // if (message['data'].containsKey("is_call")) {
|
||||
// // var route = ModalRoute.of(context);
|
||||
// //
|
||||
// // if (route != null) {
|
||||
// // print(route.settings.name);
|
||||
// // }
|
||||
// //
|
||||
// // Map<String, dynamic> myMap = new Map<String, dynamic>.from(message['data']);
|
||||
// // print(myMap);
|
||||
// // if (LandingPage.isOpenCallPage) {
|
||||
// // return;
|
||||
// // }
|
||||
// // LandingPage.isOpenCallPage = true;
|
||||
// // LandingPage.incomingCallData = IncomingCallData.fromJson(myMap);
|
||||
// // if (!isPageNavigated) {
|
||||
// // isPageNavigated = true;
|
||||
// // Navigator.push(context, MaterialPageRoute(builder: (context) => IncomingCall(incomingCallData: LandingPage.incomingCallData))).then((value) {
|
||||
// // Future.delayed(Duration(seconds: 5), () {
|
||||
// // isPageNavigated = false;
|
||||
// // });
|
||||
// // });
|
||||
// // }
|
||||
// // } else {
|
||||
// // print("Is Call Not Found Android");
|
||||
// // LocalNotification.getInstance().showNow(title: message['notification']['title'], subtitle: message['notification']['body']);
|
||||
// // }
|
||||
// // } else {
|
||||
// // print("Is Call Not Found Android");
|
||||
// // }
|
||||
// // },
|
||||
// onBackgroundMessage: Platform.isIOS ? null : myBackgroundMessageHandler,
|
||||
// onLaunch: (Map<String, dynamic> message) async {
|
||||
// print("onLaunch: $message");
|
||||
// // showDialog("onLaunch: $message");
|
||||
// },
|
||||
// onResume: (Map<String, dynamic> message) async {
|
||||
// print("onResume: $message");
|
||||
// print(message);
|
||||
// print(message['name']);
|
||||
// print(message['appointmentdate']);
|
||||
//
|
||||
// // showDialog("onResume: $message");
|
||||
//
|
||||
// if (Platform.isIOS) {
|
||||
// if (message['is_call'] == "true") {
|
||||
// var route = ModalRoute.of(context);
|
||||
//
|
||||
// if (route != null) {
|
||||
// print(route.settings.name);
|
||||
// }
|
||||
//
|
||||
// Map<String, dynamic> myMap = new Map<String, dynamic>.from(message);
|
||||
// print(myMap);
|
||||
// LandingPage.isOpenCallPage = true;
|
||||
// LandingPage.incomingCallData = IncomingCallData.fromJson(myMap);
|
||||
// if (!isPageNavigated) {
|
||||
// isPageNavigated = true;
|
||||
// Navigator.push(context, MaterialPageRoute(builder: (context) => IncomingCall(incomingCallData: LandingPage.incomingCallData))).then((value) {
|
||||
// isPageNavigated = false;
|
||||
// });
|
||||
// }
|
||||
// } else {
|
||||
// print("Is Call Not Found iOS");
|
||||
// }
|
||||
// } else {
|
||||
// print("Is Call Not Found iOS");
|
||||
// }
|
||||
// },
|
||||
// );
|
||||
Loading…
Reference in New Issue