jiusanzhou / flutter_notification_listener

Flutter plugin to listen for and interact with all incoming notifications for Android. 一个监听手机通知的插件。
https://pub.dev/packages/flutter_notification_listener
Other
39 stars 47 forks source link

Problem updating interface when permissions are approved #28

Open manarbajafar opened 1 year ago

manarbajafar commented 1 year ago

I'm having a problem updating the interface, I want when I press the button and then agree to the permissions, and go back to the screen That button disappears But what happens is that it requires me to press the button again for the button to disappear

I don't know what the problem is And when I use the loading and started values, it hides the button before I approve the permissions only once I open the settings Where in the code can I tell that the user has approved the permissions?

I recorded the screen when I run https://drive.google.com/file/d/1ftcUdR_voBZOYE0gMOoEhj9FP37e6ULr/view?usp=sharing

this is the screen code:

class ChildUncombletePSc extends StatelessWidget {
  ChildUncompleteController controller = Get.put(ChildUncompleteController());

  String iconUrl(Gender gender, bool isActive) { }

  calculateAge(DateTime birthDate) { }

  bool back = true;
  @override
  Widget build(BuildContext context) {
    return WillPopScope(
      onWillPop: () async => false,
      child: Scaffold(
        appBar: AppBar(
          leading: GetBuilder<ChildUncompleteController>(builder: (controller) {
            return controller.backbutton
                ? IconButton(
                    alignment: Alignment(-1.0.w, -0.7.w),
                    icon: Icon(Icons.arrow_back, color: Colors.white),
                    onPressed: () => Navigator.of(context).pop(),
                  )
                : Text("");
          }),
          shape: RoundedRectangleBorder(
            borderRadius: BorderRadius.only(
              bottomLeft: Radius.circular(400.r),
            ),
          ),
          flexibleSpace: ClipRRect(
            borderRadius: BorderRadius.only(
              bottomLeft: Radius.circular(400.r),
            ),
            child: Container(
              decoration: BoxDecoration(
                gradient: LinearGradient(
                  begin: Alignment.topCenter,
                  end: Alignment.bottomCenter,
                  colors: [
                    Theme.of(context).accentColor,
                    Theme.of(context).primaryColor,
                  ],
                ),
              ),
            ),
          ),
          bottom: PreferredSize(
            preferredSize: Size.fromHeight(250.h),
            child: Column(
              children: [
                Image.asset(
                  'images/whiteLogo.png',
                  height: 150.h,
                ),
                Padding(
                  padding:
                      EdgeInsets.only(top: 28.h, bottom: 30.h, right: 20.w),
                  child: GetBuilder<ChildUncompleteController>(
                    builder: (controller) => Row(
                      children: [
                        Image.asset(
                          // iconUrl(gender, isActivated),

                          ChildAccount.iconUrl(
                              controller.gender.toString() == 'أنثى'
                                  ? Gender.Girl
                                  : Gender.Boy,
                              controller.isActive == 0 ? false : true),
                          height: 70.h,
                        ),
                        SizedBox(
                          width: 10.w,
                        ),
                        Text(controller.name ?? "",
                            style: Theme.of(context).textTheme.headline5),
                      ],
                    ),
                  ),
                ),
              ],
            ),
          ),
        ),
        body: SingleChildScrollView(
          child: GetBuilder<ChildUncompleteController>(
            init: ChildUncompleteController(),
            builder: (value) => Column(
              children: [
                Padding(
                  padding: EdgeInsets.only(bottom: 10.h),
                  child: Text(
                    'العمر: ${calculateAge(DateTime.parse(controller.age ?? ""))}',
                    textAlign: TextAlign.right,
                    style: Theme.of(context).textTheme.headline5,
                  ),
                ),
                Center(
                  child: Padding(
                    padding:
                        EdgeInsets.symmetric(vertical: 3.h, horizontal: 3.w),
                    child: !value.flag
                        ? Text(
                            'لم يتم إنهاء اجراءات هذا الطفل',
                            textAlign: TextAlign.center,
                            style: Theme.of(context).textTheme.headline3,
                          )
                        : Text(
                            'تم انهاء إجراءات هذا الطفل ',
                            textAlign: TextAlign.center,
                            style: Theme.of(context).textTheme.headline3,
                          ),
                  ),
                ),
                SizedBox(
                  height: 20.h,
                ),
                Center(
                  child: !value.flag
                      ? SizedBox(
                          height: 40.h,
                          width: 200.w,
                          child: ElevatedButton(
                            style: ElevatedButton.styleFrom(
                              backgroundColor: Theme.of(context).buttonColor,
                            ),
                            onPressed: () {
                              print("message 1 ${value.started}");
                              value.started
                                  ? value.stopListening()
                                  : value.startListening();
                            },
                            child: Text(
                              ' إنهاء الاجراءات ',
                              style: Theme.of(context).textTheme.headline4,
                            ),
                          ),
                        )
                      : null,
                ),
              ],
            ),
          ),
        ),
      ),
    );
  }
}

and this is it's controller:

class ChildUncompleteController extends GetxController {
  List<NotificationEvent> _log = [];
  bool started = false;
  bool _loading = false;
  bool flag = false;
  ReceivePort port = ReceivePort();

  Crud crud = Crud();
  bool isLoading = false;
  bool backbutton = true;

  String? name;
  String? age;
  int? isActive;
  String? gender;

  final myServerUrl = 'http://192.168.8.102:5000/';

  @override
  void onInit() {
    initPlatformState();
    super.onInit();
  }

  // we must use static method, to handle in background
  static void _callback(NotificationEvent evt) {
    // HANDLING BACKGROUND NOTIFICATIONS :
    // print('GETTING INFO ');
    // print(evt.packageName); // PACKAGE USE TO SEND MESSAGE :
    // print(evt.text); // MESSAGE CONTENT  :
    // print(evt.title); //SENDER NUMBER: OR HEADER

    final SendPort? send = IsolateNameServer.lookupPortByName("_listener_");
    if (send == null) print("can't find the sender");
    send?.send(evt);
  }

  // Platform messages are asynchronous, so we initialize in an async method.
  Future<void> initPlatformState() async {
    NotificationsListener.initialize(callbackHandle: _callback);

    // this can fix restart<debug> can't handle error
    IsolateNameServer.removePortNameMapping("_listener_");
    IsolateNameServer.registerPortWithName(port.sendPort, "_listener_");
    port.listen((message) => onData(message));

    // don't use the default receivePort
    // NotificationsListener.receivePort.listen((evt) => onData(evt));

    bool? isR = await NotificationsListener.isRunning;
    print("""Service is ${isR == false ? "not " : ""}aleary running""");

    started = isR!;
    update();
  }

  Future<void> onData(NotificationEvent event) async {
    _log.add(event);
    update();

    if (!event.packageName!.contains("example")) {
      // TODO: fix bug
      // NotificationsListener.promoteToForeground("");
    }
    // print('GETTING INFO FRONT APP ');
    // print(event.packageName); // PACKAGE USE TO SEND MESSAGE :
    // print(event.text); // MESSAGE CONTENT  :
    // print(event.title); //SENDER NUMBER: OR HEADER

    if (event.packageName == 'com.whatsapp' && event.id != 0) {
      await processMsg(event);
    }
  }

  void startListening() async {
    print("start listening");

    _loading = true;
    update();

    bool? hasPermission = await NotificationsListener.hasPermission;
    if (hasPermission == false) {
      print("no permission, so open settings");
      NotificationsListener.openPermissionSettings();
      return;
    }

    bool? isR = await NotificationsListener.isRunning;

    if (isR == false) {
      await NotificationsListener.startService(
          title: "we still with you ", description: "payai from feelsafe");
    }
    //if he agree
    flag = true;
    activateC();
    started = true;
    _loading = false;
    update();
  }

  void stopListening() async {
    print("stop listening");

    _loading = true;
    update();

    await NotificationsListener.stopService();

    started = false;
    _loading = false;
    update();
  }

  Future<void> processMsg(NotificationEvent msg) async {
    //url to send the post request to
    final url = myServerUrl;
    // print(text);
    //sending a post request to the url
    final response = await http.post(Uri.parse(url),
        body: json.encode({
          'content': msg.text,
          "sender": msg.title.toString(),
          "date_time": msg.createAt.toString().substring(0, 19).toString(),
          "parent_id": sharedPref.getString('parent_id'),
          "child_name": name,
        }));

    //converting the fetched data from json to key value pair that can be displayed on the screen
    final decoded = json.decode(response.body) as Map<String, dynamic>;

    //this for tharaa :)
    String label = decoded['label'];
    if (label == 'NOT_APROP') {
      //Here take the same msg information (line 134 - 138) and deal with it
      print("label is $label");
    }
  }

  void storeMsg(NotificationEvent msg) async {
    print(
        "child_name: $name , parent_id: ${sharedPref.getString('parent_id')}");

    var response = await crud.postRequest2(linkStoreMsg, {
      "child_name": name,
      "sender": msg.title.toString(),
      "date_time": msg.createAt.toString().substring(0, 19).toString(),
      "content": msg.text,
      "parent_id": sharedPref.getString('parent_id'),
    });
    print("response ${response}");
  }

  activateC() async {
    isLoading = true;
    var response = await crud.postRequest(linkactivateChild, {
      "child_name": name,
      "parent_id": sharedPref.getString("parent_id"),
    });
    isLoading = false;
    if (response != null && response["status"] != "fail") {
      backbutton = false;
      isActive = 1;
      update();
    } else {
      print("activate fail");
    }
  }
}
jiusanzhou commented 1 year ago

Hi @manarbajafar Thank you for your attention. Do you want the button to disappear automatically after you click Authorize?

manarbajafar commented 1 year ago

Hi @manarbajafar Thank you for your attention. Do you want the button to disappear automatically after you click Authorize?

Hello @jiusanzhou thanks for your reply. Yes, I want the button to disappear after the user clicks on Allow access to notifications

jiusanzhou commented 1 year ago

@manarbajafar Sorry for the late reply. I think this requires adding a listener to listen for permission changing events, but I don't currently have it implemented, if I remember correctly. You can still add a timed task to get the latest permission status at regular intervals, this is of course a silly solution