Dial USSD service dial from a flutter app

  Kiến thức lập trình

I have a flutter app that needs to dial a ussd service with one sequence like :

*150*1*{secret}*1*{amount}*{gsmNumber}*{gsmNumber}#

I already tried all the packages from flutter none of them working in a proper way so I tried the telephony manger in android since it’s only android but none seem to be working
this is my mainActivity.kt

package com.example.topup

import android.Manifest
import android.content.Context
import android.content.pm.PackageManager
import android.os.Bundle
import android.os.Handler
import android.os.Looper
import android.telephony.SubscriptionManager
import android.telephony.TelephonyManager
import android.telephony.TelephonyManager.UssdResponseCallback
import android.util.Log
import androidx.core.app.ActivityCompat
import androidx.core.content.ContextCompat
import io.flutter.embedding.android.FlutterActivity
import io.flutter.embedding.engine.FlutterEngine
import io.flutter.plugin.common.MethodChannel

class MainActivity : FlutterActivity() {
    private val CHANNEL = "com.example.ussd"
    private val REQUEST_CALL_PHONE = 1

    override fun configureFlutterEngine(flutterEngine: FlutterEngine) {
        super.configureFlutterEngine(flutterEngine)
        MethodChannel(flutterEngine.dartExecutor.binaryMessenger, CHANNEL).setMethodCallHandler { call, result ->
            if (call.method == "callUssd") {
                val ussdCode = call.argument<String>("ussdCode") ?: ""
                if (ContextCompat.checkSelfPermission(this, Manifest.permission.CALL_PHONE) != PackageManager.PERMISSION_GRANTED) {
                    ActivityCompat.requestPermissions(this, arrayOf(Manifest.permission.CALL_PHONE), REQUEST_CALL_PHONE)
                    result.error("PERMISSION_DENIED", "CALL_PHONE permission denied", null)
                } else {
                    if (isSimPresent()) {
                        sendUssdRequest(ussdCode, result)
                    } else {
                        result.error("NO_SIM", "No SIM card present", null)
                    }
                }
            } else {
                result.notImplemented()
            }
        }
    }

    private fun isSimPresent(): Boolean {
        val subscriptionManager = getSystemService(Context.TELEPHONY_SUBSCRIPTION_SERVICE) as SubscriptionManager
        val activeSubscriptionInfoList = subscriptionManager.activeSubscriptionInfoList
        val simPresent = activeSubscriptionInfoList != null && activeSubscriptionInfoList.isNotEmpty()
        Log.d("USSD", "SIM present: $simPresent")
        return simPresent
    }

    private fun sendUssdRequest(ussdCode: String, result: MethodChannel.Result) {
        val telephonyManager = getSystemService(Context.TELEPHONY_SERVICE) as TelephonyManager

        try {
            Log.d("USSD", "Sending USSD request: $ussdCode")
            telephonyManager.sendUssdRequest(ussdCode, object : UssdResponseCallback() {
                override fun onReceiveUssdResponse(
                    telephonyManager: TelephonyManager,
                    request: String,
                    response: CharSequence
                ) {
                    Log.d("USSD", "USSD request: $request")
                    Log.d("USSD", "USSD response received: $response")
                    result.success(response.toString())
                }

                override fun onReceiveUssdResponseFailed(
                    telephonyManager: TelephonyManager,
                    request: String,
                    failureCode: Int
                ) {
                    Log.e("USSD", "USSD request: $request")
                    Log.e("USSD", "USSD request failed with code: $failureCode")
                    when (failureCode) {
                        TelephonyManager.USSD_RETURN_FAILURE -> Log.e("USSD", "USSD_RETURN_FAILURE")
                        TelephonyManager.USSD_ERROR_SERVICE_UNAVAIL -> Log.e("USSD", "USSD_ERROR_SERVICE_UNAVAIL")
                        else -> Log.e("USSD", "Unknown failure code: $failureCode")
                    }
                    result.error("USSD_FAILED", "USSD request failed with code: $failureCode", null)
                }
            }, Handler(Looper.getMainLooper()))
        } catch (e: SecurityException) {
            Log.e("USSD", "SecurityException: ${e.message}")
            result.error("USSD_FAILED", "SecurityException: ${e.message}", null)
        } catch (e: Exception) {
            Log.e("USSD", "Exception: ${e.message}")
            result.error("USSD_FAILED", "Exception: ${e.message}", null)
        }
    }

    override fun onRequestPermissionsResult(requestCode: Int, permissions: Array<out String>, grantResults: IntArray) {
        super.onRequestPermissionsResult(requestCode, permissions, grantResults)
        if (requestCode == REQUEST_CALL_PHONE) {
            if ((grantResults.isNotEmpty() && grantResults[0] == PackageManager.PERMISSION_GRANTED)) {
                Log.d("USSD", "CALL_PHONE permission granted")
            } else {
                Log.e("USSD", "CALL_PHONE permission denied")
            }
        }
    }
}

and this is android.manifest:

<manifest xmlns:android="http://schemas.android.com/apk/res/android">
      <uses-permission android:name="android.permission.INTERNET"/>
    <uses-permission android:name="android.permission.CALL_PHONE"/>
    <uses-permission android:name="android.permission.READ_PHONE_STATE"/>


    <application
        android:label="topup"
        android:name="${applicationName}"
        android:icon="@mipmap/ic_launcher">
        <activity
            android:name=".MainActivity"
            android:exported="true"
            android:launchMode="singleTop"
            android:theme="@style/LaunchTheme"
            android:configChanges="orientation|keyboardHidden|keyboard|screenSize|smallestScreenSize|locale|layoutDirection|fontScale|screenLayout|density|uiMode"
            android:hardwareAccelerated="true"
            android:windowSoftInputMode="adjustResize">
            <!-- Specifies an Android theme to apply to this Activity as soon as
                 the Android process has started. This theme is visible to the user
                 while the Flutter UI initializes. After that, this theme continues
                 to determine the Window background behind the Flutter UI. -->
            <meta-data
              android:name="io.flutter.embedding.android.NormalTheme"
              android:resource="@style/NormalTheme"
              />
            <intent-filter>
                <action android:name="android.intent.action.MAIN"/>
                <category android:name="android.intent.category.LAUNCHER"/>
            </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>

and this is the implementation in flutter :

import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:permission_handler/permission_handler.dart';

class UssdService extends StatelessWidget {
  static const platform = MethodChannel('com.example.ussd');

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text('USSD Service'),
      ),
      body: Center(
        child: ElevatedButton(
          onPressed: _callUssd,
          child: Text('Dial USSD Code'),
        ),
      ),
    );
  }

  Future<void> _callUssd() async {
    if (await _requestPhonePermission()) {
      try {
        final String result = await platform.invokeMethod('callUssd', {"ussdCode": "*123#"});
        print('USSD Response: $result');
      } on PlatformException catch (e) {
        print('Failed to call USSD: ${e.message}');
      }
    } else {
      print('Phone call permission not granted');
    }
  }

  Future<bool> _requestPhonePermission() async {
    PermissionStatus status = await Permission.phone.status;
    if (!status.isGranted) {
      status = await Permission.phone.request();
    }
    return status.isGranted;
  }
}

when I try I get something like
`D/USSD ( 3110): Sending USSD request: *123#
E/USSD ( 3110): USSD request: *123#
E/USSD ( 3110): USSD request failed with code: -1
E/USSD ( 3110): USSD_RETURN_FAILURE
I/flutter ( 3110): Failed to dial USSD code. Error: PlatformException(USSD_FAILED, USSD request failed with code: -1, null, null)

`
Any one got any experience or can guide me through how to do the implementation for calling a USSD services in android flutter app

New contributor

Majd Maihoub is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
Check out our Code of Conduct.

Theme wordpress giá rẻ Theme wordpress giá rẻ Thiết kế website

LEAVE A COMMENT