skip to Main Content

I am developing a flutter application that let users video call each other using Agora Rtc Engine. I am pushing notification using firebase messaging with cloud function when a user schedules a call and that is working fine even after releasing to playstore. I want a phone to ring when a user is receiving a call from another and for that I used [flutter_callkit_incoming][1]. this works well when I am locally testing my app in debug mode using Android 11 and 10 but the callkit is not showing after uploading my app to playstore.

I added necessary permission in AndroidManifest.xml. I am using Flutter 3

Any Help is much appreciated

Here is how I am triggering CallKit on main.dart after receiving a FCM – which is only working in debug mode but not after adding app to Playstore using appbundle.

import 'package:flutter/services.dart';
import 'package:flutter/material.dart';
import 'package:firebase_core/firebase_core.dart';
import 'dart:async';
import 'package:firebase_messaging/firebase_messaging.dart';
import 'package:flutter_callkit_incoming/entities/android_params.dart';
import 'package:flutter_callkit_incoming/entities/call_kit_params.dart';
import 'package:flutter_callkit_incoming/entities/ios_params.dart';
import 'package:flutter_easyloading/flutter_easyloading.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:get/get.dart';
import 'controllers/notifications_controller.dart';
import 'firebase_options.dart';
import 'package:myidol/constants/constants.dart';
import 'notifications/call_schedule_notifications.dart';
import 'package:flutter_callkit_incoming/flutter_callkit_incoming.dart';
import 'package:uuid/uuid.dart';


Future<void> _onBackgroundMessage(RemoteMessage message) async {
  await Firebase.initializeApp(
    options: DefaultFirebaseOptions.currentPlatform,
  );
  String? title = message.notification!.title;
  String? body = message.notification!.body;
  showCallkitIncoming(Uuid().v4(), title!, body!);
  if (body == "Incoming Video Call") {
    showCallkitIncoming(Uuid().v4(), title, body);
  } else {
    print("Messaging notification");
  }
}

Future<void> showCallkitIncoming(String uuid, String title, String body) async {
  final params = CallKitParams(
    id: uuid,
    nameCaller: "CallerName",
    appName: 'My idol',
    avatar: 'avatar',
    handle: body,
    type: 0,
    duration: 60000,
    textAccept: 'Accept',
    textDecline: 'Decline',
    textMissedCall: 'Missed call',
    textCallback: 'Call back',
    extra: <String, dynamic>{'userId': '1a2b3c4d'},
    headers: <String, dynamic>{'apiKey': 'Abc@123!', 'platform': 'flutter'},
    android: AndroidParams(
      isCustomNotification: true,
      isShowLogo: false,
      isShowCallback: true,
      isShowMissedCallNotification: true,
      ringtonePath: 'system_ringtone_default',
      backgroundColor: '#027DC3',
      backgroundUrl: 'assets/test.png',
      actionColor: '#EE1D52',
    ),
    ios: IOSParams(
      iconName: 'CallKitLogo',
      handleType: '',
      supportsVideo: true,
      maximumCallGroups: 2,
      maximumCallsPerCallGroup: 1,
      audioSessionMode: 'default',
      audioSessionActive: true,
      audioSessionPreferredSampleRate: 44100.0,
      audioSessionPreferredIOBufferDuration: 0.005,
      supportsDTMF: true,
      supportsHolding: true,
      supportsGrouping: false,
      supportsUngrouping: false,
      ringtonePath: 'system_ringtone_default',
    ),
  );
  await FlutterCallkitIncoming.showCallkitIncoming(params);
}


void main() async {
  WidgetsFlutterBinding.ensureInitialized();
  SystemChrome.setPreferredOrientations([DeviceOrientation.portraitUp]);
  await Firebase.initializeApp(
    options: DefaultFirebaseOptions.currentPlatform,
  ).then((value) => Get.put(AuthController()));
  await NotificationController.initializeLocalNotifications();
  //Awesone Notification
  FirebaseMessaging.onBackgroundMessage(_onBackgroundMessage);
  await FirebaseMessaging.instance.setForegroundNotificationPresentationOptions(
    alert: true,
    badge: true,
    sound: true,
  );
  await NotificationService.initializeNotification();

  runApp(const ProviderScope(child: MyApp()));
  easyLoadingConfig();
}

class MyApp extends StatefulWidget {
  const MyApp({super.key});

  @override
  State<MyApp> createState() => _MyAppState();
}

class _MyAppState extends State<MyApp> with WidgetsBindingObserver {
  @override
  void initState() {
    super.initState();
  }
  // This widget is the root of your application.
  @override
  Widget build(BuildContext context) {
    return GetMaterialApp(
      debugShowCheckedModeBanner: false,
      title: 'My App',
      theme: ThemeData.dark().copyWith(
        scaffoldBackgroundColor: backgroundColor,
      ),
      home: LoginOptions(),
      builder: EasyLoading.init(),
    );
  }
}

AndroidManifest Permissions

<uses-permission android:name="android.permission.INTERNET"/>
<uses-permission  android:name="android.permission.READ_PHONE_STATE"/>
<uses-permission  android:name="android.permission.RECORD_AUDIO"  />
<uses-permission  android:name="android.permission.CAMERA"  />
<uses-permission  android:name="android.permission.MODIFY_AUDIO_SETTINGS"  />
<uses-permission  android:name="android.permission.ACCESS_NETWORK_STATE"  />
<!-- The Agora SDK requires Bluetooth permissions in case users are using Bluetooth devices.-->
<uses-permission  android:name="android.permission.BLUETOOTH"  />
<uses-permission android:name="android.permission.WAKE_LOCK" />
<uses-permission android:name="android.permission.FOREGROUND_SERVICE"/>
<uses-permission android:name="android.permission.REQUEST_IGNORE_BATTERY_OPTIMIZATIONS" />

<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" android:maxSdkVersion="28" tools:ignore="ScopedStorage" />
<uses-permission android:name="android.permission.WRITE_INTERNAL_STORAGE" />
<uses-permission android:name="android.permission.VIBRATE" />
<uses-permission android:name="android.permission.FOREGROUND_SERVICE" />

2

Answers


  1. play store will generate new SHA code, you must get it and paste to firebase console.

    Login or Signup to reply.
  2. i don’t know it’s still actual or not , but i have same problem. But in logcat i catched an error

    NoSuchMethodError: No top-level getter

    After searching , i understood that flutter can run native code only in debug mode. I haven’t published my app yet. But i think this is your case. So, in release mode you must declare @pragma annotation , it means that it will be used from native code.

    In my case resolved this like:

        @pragma("vm:entry-point")
    Future<void> _messageHandler(RemoteMessage message) async {
    
      print('I received background message ${message}'); 
     // paste your implementation
     //e.g await showCallkitIncoming(message);
     }
    

    more information about pragma
    I hope it hepls. Good Luck.

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search