Permission Issue

development_mirza
Aamir Muhammad 2 years ago
parent ed220b80a0
commit c8f9826266

@ -7,11 +7,13 @@
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
<uses-permission android:name="android.permission.NFC" />
<uses-permission android:name="android.permission.CAMERA" />
<!-- Foreground Service For Background Notifications-->
<uses-permission android:name="android.permission.FOREGROUND_SERVICE" />
<application
android:allowBackup="false"
android:icon="@mipmap/ic_launcher"
android:label="Mohemm"
android:allowBackup="false"
android:networkSecurityConfig="@xml/network_security_config"
android:roundIcon="@mipmap/ic_launcher_round">
<activity
@ -37,15 +39,21 @@
<meta-data
android:name="io.flutter.embedding.android.SplashScreenDrawable"
android:resource="@drawable/launch_background" />
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
<intent-filter>
<action android:name="FLUTTER_NOTIFICATION_CLICK" />
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
</activity>
<!-- Don't delete the meta-data below.
This is used by the Flutter tool to generate GeneratedPluginRegistrant.java -->
<meta-data
android:name="flutterEmbedding"
android:value="2" />
</application>
</manifest>

@ -1,5 +1,7 @@
import UIKit
import Flutter
import flutter_local_notifications
@UIApplicationMain
@objc class AppDelegate: FlutterAppDelegate {
@ -7,6 +9,13 @@ import Flutter
_ application: UIApplication,
didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?
) -> Bool {
FlutterLocalNotificationsPlugin.setPluginRegistrantCallback { (registry) in
GeneratedPluginRegistrant.register(with: registry)
}
if #available(iOS 10.0, *) {
UNUserNotificationCenter.current().delegate = self as UNUserNotificationCenterDelegate
}
GeneratedPluginRegistrant.register(with: self)
return super.application(application, didFinishLaunchingWithOptions: launchOptions)
}

@ -30,10 +30,19 @@ class ChatApiClient {
{
"employeeNumber": AppState().memberInformationList!.eMPLOYEENUMBER.toString(),
"password": "FxIu26rWIKoF8n6mpbOmAjDLphzFGmpG",
"isMobile": true,
"deviceToken": AppState().deviceNotificationToken
},
);
print({
"employeeNumber": AppState().memberInformationList!.eMPLOYEENUMBER.toString(),
"password": "FxIu26rWIKoF8n6mpbOmAjDLphzFGmpG",
"isMobile": true,
"deviceToken": AppState().deviceNotificationToken
});
if (!kReleaseMode) {
logger.i("res: " + response.body);
logger.i("login-res: " + response.body);
}
if (response.statusCode == 200) {
userLoginResponse = user.userAutoLoginModelFromJson(response.body);

@ -173,4 +173,13 @@ class AppState {
}
bool cancelRequestTrancsection = true;
String? _deviceNotificationToken;
String? get deviceNotificationToken => _deviceNotificationToken;
set deviceNotificationToken(String? deviceNotificationToken) {
_deviceNotificationToken = deviceNotificationToken;
}
}

@ -0,0 +1,61 @@
import 'dart:convert';
import 'dart:io';
import 'package:firebase_messaging/firebase_messaging.dart';
import 'package:flutter_local_notifications/flutter_local_notifications.dart';
import 'package:mohem_flutter_app/app_state/app_state.dart';
import 'package:mohem_flutter_app/main.dart';
import 'package:permission_handler/permission_handler.dart';
final FlutterLocalNotificationsPlugin flutterLocalNotificationsPlugin = FlutterLocalNotificationsPlugin();
class AppNotifications {
static final AppNotifications _instance = AppNotifications._internal();
AppNotifications._internal();
factory AppNotifications() => _instance;
Future<void> requestPermissions() async {
if (Platform.isIOS) {
await flutterLocalNotificationsPlugin.resolvePlatformSpecificImplementation<IOSFlutterLocalNotificationsPlugin>()?.requestPermissions(alert: true, badge: true, sound: true);
} else if (Platform.isAndroid) {
AndroidFlutterLocalNotificationsPlugin? androidImplementation = flutterLocalNotificationsPlugin.resolvePlatformSpecificImplementation<AndroidFlutterLocalNotificationsPlugin>();
bool? granted = await androidImplementation?.requestPermission();
if (granted == false) {
print("-------------------- Permission Granted ------------------------");
print(granted);
await Permission.notification.request();
}
}
}
Future<void> isAndroidPermGranted() async {
if (Platform.isAndroid) {
bool granted = await flutterLocalNotificationsPlugin.resolvePlatformSpecificImplementation<AndroidFlutterLocalNotificationsPlugin>()?.areNotificationsEnabled() ?? false;
}
}
void initNotification(String? firebaseToken) async {
// await requestPermissions();
AppState().deviceNotificationToken = firebaseToken;
// await Permission.notification.isDenied.then((value) {
// if (value) {
// Permission.notification.request();
// }
// });
RemoteMessage? initialMessage = await FirebaseMessaging.instance.getInitialMessage();
if (initialMessage != null) _handleMessage(initialMessage);
FirebaseMessaging.onMessage.listen((RemoteMessage message) {
if (message.notification != null) _handleMessage(message);
});
FirebaseMessaging.onMessageOpenedApp.listen(_handleMessage);
}
void _handleMessage(RemoteMessage message) {
print("Handle Message");
logger.w(json.encode(message));
}
}

@ -2,7 +2,6 @@ import 'dart:async';
import 'dart:convert';
import 'dart:io';
import 'dart:typed_data';
import 'package:audio_waveforms/audio_waveforms.dart';
import 'package:easy_localization/easy_localization.dart';
import 'package:flutter/cupertino.dart';
@ -32,6 +31,7 @@ import 'package:permission_handler/permission_handler.dart';
import 'package:signalr_netcore/hub_connection.dart';
import 'package:signalr_netcore/signalr_client.dart';
import 'package:uuid/uuid.dart';
import 'package:flutter/material.dart' as Material;
class ChatProviderModel with ChangeNotifier, DiagnosticableTreeMixin {
ScrollController scrollController = ScrollController();
@ -66,6 +66,8 @@ class ChatProviderModel with ChangeNotifier, DiagnosticableTreeMixin {
List<GetEmployeeSubordinatesList> getEmployeeSubordinatesList = [];
List<ChatUser> teamMembersList = [];
Material.TextDirection textDirection = Material.TextDirection.ltr;
//Chat Home Page Counter
int chatUConvCounter = 0;
@ -99,7 +101,7 @@ class ChatProviderModel with ChangeNotifier, DiagnosticableTreeMixin {
HubConnection hub;
HttpConnectionOptions httpOp = HttpConnectionOptions(skipNegotiation: false, logMessageContent: true);
hub = HubConnectionBuilder()
.withUrl(ApiConsts.chatHubConnectionUrl + "?UserId=${AppState().chatDetails!.response!.id}&source=Web&access_token=${AppState().chatDetails!.response!.token}", options: httpOp)
.withUrl(ApiConsts.chatHubConnectionUrl + "?UserId=${AppState().chatDetails!.response!.id}&source=Desktop&access_token=${AppState().chatDetails!.response!.token}", options: httpOp)
.withAutomaticReconnect(retryDelays: <int>[2000, 5000, 10000, 20000]).build();
return hub;
}
@ -1409,4 +1411,50 @@ class ChatProviderModel with ChangeNotifier, DiagnosticableTreeMixin {
isLoading = false;
notifyListeners();
}
void inputBoxDirection(String val) {
if (val.isNotEmpty) {
isTextMsg = true;
} else {
isTextMsg = false;
}
RegExp exp = RegExp("[a-zA-Z]");
if (exp.hasMatch(val.substring(val.length - 1)) && val.substring(val.length - 1) != " ") {
textDirection = Material.TextDirection.ltr;
notifyListeners();
} else if (val.substring(val.length - 1) != " " && !exp.hasMatch(val.substring(val.length - 1))) {
textDirection = Material.TextDirection.rtl;
notifyListeners();
}
}
Material.TextDirection getTextDirection(String v) {
String str = v.trim();
if (str.isEmpty) return Material.TextDirection.ltr;
int firstUnit = str.codeUnitAt(0);
if (firstUnit > 0x0600 && firstUnit < 0x06FF ||
firstUnit > 0x0750 && firstUnit < 0x077F ||
firstUnit > 0x07C0 && firstUnit < 0x07EA ||
firstUnit > 0x0840 && firstUnit < 0x085B ||
firstUnit > 0x08A0 && firstUnit < 0x08B4 ||
firstUnit > 0x08E3 && firstUnit < 0x08FF ||
firstUnit > 0xFB50 && firstUnit < 0xFBB1 ||
firstUnit > 0xFBD3 && firstUnit < 0xFD3D ||
firstUnit > 0xFD50 && firstUnit < 0xFD8F ||
firstUnit > 0xFD92 && firstUnit < 0xFDC7 ||
firstUnit > 0xFDF0 && firstUnit < 0xFDFC ||
firstUnit > 0xFE70 && firstUnit < 0xFE74 ||
firstUnit > 0xFE76 && firstUnit < 0xFEFC ||
firstUnit > 0x10800 && firstUnit < 0x10805 ||
firstUnit > 0x1B000 && firstUnit < 0x1B0FF ||
firstUnit > 0x1D165 && firstUnit < 0x1D169 ||
firstUnit > 0x1D16D && firstUnit < 0x1D172 ||
firstUnit > 0x1D17B && firstUnit < 0x1D182 ||
firstUnit > 0x1D185 && firstUnit < 0x1D18B ||
firstUnit > 0x1D1AA && firstUnit < 0x1D1AD ||
firstUnit > 0x1D242 && firstUnit < 0x1D244) {
return Material.TextDirection.rtl;
}
return Material.TextDirection.ltr;
}
}

@ -32,6 +32,8 @@ class ChatBubble extends StatelessWidget {
bool isReplied = false;
bool isVoice = false;
int? fileTypeID;
String? fileTypeName;
@ -50,6 +52,7 @@ class ChatBubble extends StatelessWidget {
isCurrentUser = cItem.currentUserId == AppState().chatDetails!.response!.id ? true : false;
isSeen = cItem.isSeen == true ? true : false;
isReplied = cItem.userChatReplyResponse != null ? true : false;
// isVoice = cItem.fileTypeId == 13 && cItem.voiceController != null ? true : false;
fileTypeID = cItem.fileTypeId;
fileTypeName = cItem.fileTypeResponse != null ? cItem.fileTypeResponse!.fileTypeName : "";
fileTypeDescription = cItem.fileTypeResponse != null ? cItem.fileTypeResponse!.fileTypeDescription : "";
@ -57,18 +60,6 @@ class ChatBubble extends StatelessWidget {
userName = AppState().chatDetails!.response!.userName == cItem.currentUserName.toString() ? "You" : cItem.currentUserName.toString();
}
Future<String> getCurrentUrl(String url)async{
if(Platform.isIOS){
String a = url.substring(url.indexOf("Documents/") + 10, url.length) ;
Directory dir = await getApplicationDocumentsDirectory();
a = "${dir.path}/$a";
return a;
}
else{
return url;
}
}
void playVoice(
BuildContext context, {
required SingleUserChatModel data,
@ -91,36 +82,30 @@ class ChatBubble extends StatelessWidget {
} else {
Utils.showLoading(context);
Uint8List encodedString = await ChatApiClient().downloadURL(fileName: data.contant!, fileTypeDescription: provider.getFileTypeDescription(data.fileTypeResponse!.fileTypeName ?? ""));
// try {
File sFile = await provider.downChatVoice(encodedString, data.fileTypeResponse!.fileTypeName ?? "", data);
if(sFile.path.isEmpty){
logger.d("Path Is Emptyyyyyyy");
}else{
logger.d("Path Exsists");
}
data.voice = sFile;
if (Platform.isIOS) {
logger.d("isIOS");
Duration? duration = await data.voiceController!.setAudioSource(MyCustomStream(data.voice!.readAsBytesSync()));
await data.voiceController!.seek(duration);
await data.voiceController!.setLoopMode(LoopMode.off);
await data.voiceController!.setVolume(1.0);
// try {
File sFile = await provider.downChatVoice(encodedString, data.fileTypeResponse!.fileTypeName ?? "", data);
if (sFile.path.isEmpty) {
logger.d("Path Is Emptyyyyyyy");
} else {
logger.d("Path Exsists");
}
data.voice = sFile;
if (Platform.isIOS) {
logger.d("isIOS");
Duration? duration = await data.voiceController!.setAudioSource(MyCustomStream(data.voice!.readAsBytesSync()));
await data.voiceController!.seek(duration);
await data.voiceController!.setLoopMode(LoopMode.off);
await data.voiceController!.setVolume(1.0);
await data.voiceController!.load();
Utils.hideLoading(context);
data.voiceController!.play();
} else {
Duration? duration = await data.voiceController!.setFilePath(sFile.path);
await data.voiceController!.setLoopMode(LoopMode.off);
await data.voiceController!.seek(duration);
Utils.hideLoading(context);
await data.voiceController!.play();
}
// } catch (e) {
// Utils.hideLoading(context);
// Utils.showToast(e.toString());
// }
Utils.hideLoading(context);
data.voiceController!.play();
} else {
Duration? duration = await data.voiceController!.setFilePath(sFile.path);
await data.voiceController!.setLoopMode(LoopMode.off);
await data.voiceController!.seek(duration);
Utils.hideLoading(context);
await data.voiceController!.play();
}
}
}
@ -168,9 +153,12 @@ class ChatBubble extends StatelessWidget {
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
(userName).toText12(color: MyColors.gradiantStartColor, isBold: false).paddingOnly(right: 5, top: 5, bottom: 0, left: 5),
(cItem.userChatReplyResponse != null ? cItem.userChatReplyResponse!.contant.toString() : "")
.toText10(color: isCurrentUser ? MyColors.grey71Color : MyColors.white.withOpacity(0.5), isBold: false, maxlines: 4)
.paddingOnly(right: 5, top: 5, bottom: 8, left: 5),
Directionality(
textDirection: provider.getTextDirection(cItem.userChatReplyResponse != null ? cItem.userChatReplyResponse!.contant.toString() : ""),
child: (cItem.userChatReplyResponse != null ? cItem.userChatReplyResponse!.contant.toString() : "")
.toText10(color: isCurrentUser ? MyColors.grey71Color : MyColors.white.withOpacity(0.5), isBold: false, maxlines: 4)
.paddingOnly(right: 5, top: 5, bottom: 8, left: 5),
),
],
).expanded,
if (cItem.userChatReplyResponse != null)
@ -215,7 +203,7 @@ class ChatBubble extends StatelessWidget {
// || fileTypeID == 2
)
SvgPicture.asset(provider.getType(fileTypeName ?? ""), height: 30, width: 22, alignment: Alignment.center, fit: BoxFit.cover).paddingOnly(left: 0, right: 10),
(cItem.contant ?? "").toText12().expanded,
Directionality(textDirection: provider.getTextDirection(cItem.contant ?? ""), child: (cItem.contant ?? "").toText12().expanded),
if (fileTypeID == 1 || fileTypeID == 5 || fileTypeID == 7 || fileTypeID == 6 || fileTypeID == 8
//|| fileTypeID == 2
)
@ -269,9 +257,12 @@ class ChatBubble extends StatelessWidget {
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
(userName).toText12(color: MyColors.gradiantStartColor, isBold: false).paddingOnly(right: 5, top: 5, bottom: 0, left: 5),
(cItem.userChatReplyResponse != null ? cItem.userChatReplyResponse!.contant.toString() : "")
.toText10(color: isCurrentUser ? MyColors.grey71Color : MyColors.white.withOpacity(0.5), isBold: false, maxlines: 4)
.paddingOnly(right: 5, top: 5, bottom: 8, left: 5),
Directionality(
textDirection: provider.getTextDirection(cItem.userChatReplyResponse != null ? cItem.userChatReplyResponse!.contant.toString() : ""),
child: (cItem.userChatReplyResponse != null ? cItem.userChatReplyResponse!.contant.toString() : "")
.toText10(color: isCurrentUser ? MyColors.grey71Color : MyColors.white.withOpacity(0.5), isBold: false, maxlines: 4)
.paddingOnly(right: 5, top: 5, bottom: 8, left: 5),
),
],
).expanded,
if (cItem.userChatReplyResponse != null)
@ -317,7 +308,7 @@ class ChatBubble extends StatelessWidget {
// || fileTypeID == 2
)
SvgPicture.asset(provider.getType(fileTypeName ?? ""), height: 30, width: 22, alignment: Alignment.center, fit: BoxFit.cover).paddingOnly(left: 0, right: 10),
(cItem.contant ?? "").toText12(color: Colors.white).expanded,
Directionality(textDirection: provider.getTextDirection(cItem.contant ?? ""), child: (cItem.contant ?? "").toText12(color: Colors.white).expanded),
if (fileTypeID == 1 || fileTypeID == 5 || fileTypeID == 7 || fileTypeID == 6 || fileTypeID == 8
//|| fileTypeID == 2
)
@ -335,6 +326,10 @@ class ChatBubble extends StatelessWidget {
).paddingOnly(right: MediaQuery.of(context).size.width * 0.3);
}
Widget voiceMsg(BuildContext context) {
return Container();
}
Widget showImage({required bool isReplyPreview, required String fileName, required String fileTypeDescription}) {
if (cItem.isImageLoaded! && cItem.image != null) {
return Image.memory(
@ -455,7 +450,7 @@ class ChatBubble extends StatelessWidget {
playVoice(context, data: modelData);
});
} else if (processingState != ProcessingState.completed) {
return Icon(
return const Icon(
Icons.pause,
size: 30,
color: MyColors.lightGreenColor,
@ -463,7 +458,7 @@ class ChatBubble extends StatelessWidget {
pausePlaying(context, data: modelData);
});
} else {
return Icon(
return const Icon(
Icons.replay,
size: 30,
color: MyColors.lightGreenColor,
@ -476,7 +471,6 @@ class ChatBubble extends StatelessWidget {
}
}
// Feed your own stream of bytes into the player
class MyCustomStream extends StreamAudioSource {
final Uint8List bytes;

@ -42,6 +42,7 @@ class _ChatDetailScreenState extends State<ChatDetailScreen> {
final RefreshController _rc = RefreshController(initialRefresh: false);
late ChatProviderModel data;
ChatDetailedScreenParams? params;
var textDirection = TextDirection.RTL;
void getMoreChat() async {
if (params != null) {
@ -202,8 +203,7 @@ class _ChatDetailScreenState extends State<ChatDetailScreen> {
WaveBubble(
playerController: m.playerController,
isPlaying: m.playerController.playerState == PlayerState.playing,
onTap: () {
},
onTap: () {},
).expanded
else
AudioWaveforms(
@ -253,6 +253,7 @@ class _ChatDetailScreenState extends State<ChatDetailScreen> {
Row(
children: [
TextField(
textDirection: m.textDirection,
controller: m.message,
decoration: InputDecoration(
hintText: m.isAttachmentMsg ? m.selectedFile.path.split("/").last : LocaleKeys.typeheretoreply.tr(),
@ -275,11 +276,8 @@ class _ChatDetailScreenState extends State<ChatDetailScreen> {
: null,
),
onChanged: (String val) {
if (val.isNotEmpty) {
m.isTextMsg = true;
} else {
m.isTextMsg = false;
}
m.inputBoxDirection(val);
m.userTypingInvoke(currentUser: AppState().chatDetails!.response!.id!, reciptUser: params!.chatUser!.id!);
},
).expanded,

@ -58,7 +58,7 @@ class _DashboardScreenState extends State<DashboardScreen> {
data = Provider.of<DashboardProviderModel>(context, listen: false);
marathonProvider = Provider.of<MarathonProvider>(context, listen: false);
cProvider = Provider.of<ChatProviderModel>(context, listen: false);
_bHubCon();
_onRefresh();
});
}
@ -80,7 +80,6 @@ class _DashboardScreenState extends State<DashboardScreen> {
void _onRefresh() async {
data.initProvider();
_bHubCon();
// data.getITGNotification().then((value) {
// print("--------------------detail_1-----------------");
// print(value!.result!.data!.notificationMasterId);

@ -1,3 +1,4 @@
import 'dart:convert';
import 'dart:io';
import 'package:easy_localization/easy_localization.dart';
@ -12,12 +13,14 @@ import 'package:mohem_flutter_app/api/login_api_client.dart';
import 'package:mohem_flutter_app/app_state/app_state.dart';
import 'package:mohem_flutter_app/classes/colors.dart';
import 'package:mohem_flutter_app/classes/consts.dart';
import 'package:mohem_flutter_app/classes/notifications.dart';
import 'package:mohem_flutter_app/classes/utils.dart';
import 'package:mohem_flutter_app/config/routes.dart';
import 'package:mohem_flutter_app/extensions/int_extensions.dart';
import 'package:mohem_flutter_app/extensions/string_extensions.dart';
import 'package:mohem_flutter_app/extensions/widget_extensions.dart';
import 'package:mohem_flutter_app/generated/locale_keys.g.dart';
import 'package:mohem_flutter_app/main.dart';
import 'package:mohem_flutter_app/models/check_mobile_app_version_model.dart';
import 'package:mohem_flutter_app/models/get_mobile_login_info_list_model.dart';
import 'package:mohem_flutter_app/models/member_information_list_model.dart';
@ -25,6 +28,7 @@ import 'package:mohem_flutter_app/models/member_login_list_model.dart';
import 'package:mohem_flutter_app/models/privilege_list_model.dart';
import 'package:mohem_flutter_app/widgets/button/default_button.dart';
import 'package:mohem_flutter_app/widgets/input_widget.dart';
import 'package:permission_handler/permission_handler.dart';
import 'package:safe_device/safe_device.dart';
class LoginScreen extends StatefulWidget {
@ -93,6 +97,7 @@ class _LoginScreenState extends State<LoginScreen> {
await Firebase.initializeApp();
_firebaseMessaging = FirebaseMessaging.instance;
firebaseToken = await _firebaseMessaging.getToken();
AppNotifications().initNotification(firebaseToken);
loginInfo = await LoginApiClient().getMobileLoginInfoNEW(firebaseToken ?? "", Platform.isAndroid ? "android" : "ios");
if (loginInfo == null) {
await checkPrefs();
@ -154,6 +159,7 @@ class _LoginScreenState extends State<LoginScreen> {
}
}
@override
Widget build(BuildContext context) {
if (isAppOpenBySystem == null) {

@ -92,6 +92,7 @@ dependencies:
swipe_to: ^1.0.2
flutter_webrtc: ^0.9.16
camera: ^0.10.0+4
flutter_local_notifications: any
#Chat Voice Message Recoding & Play
audio_waveforms: ^0.1.5+1
@ -106,6 +107,10 @@ dependencies:
flutter_layout_grid: ^2.0.1
dependency_overrides:
firebase_core_platform_interface: 4.5.1
dev_dependencies:
flutter_test:
sdk: flutter

Loading…
Cancel
Save