Home > Enterprise >  Flutter | "runOnUiThread(object : Runnable() {public override fun run() {}})" This class d
Flutter | "runOnUiThread(object : Runnable() {public override fun run() {}})" This class d

Time:10-11

I am working on a Flutter Project where I have to give a call from Flutter to Android(Kotlin) via channel to run some specific task in native android so I used the channel system to achieve this as shown in the below files with the help of https://github.com/liusilong/stack_q/

MainActivity.kt

package com.example.my_flutter_app

import android.os.Build
import android.os.Bundle
import androidx.core.view.WindowCompat
import androidx.annotation.NonNull
import androidx.annotation.Nullable
import io.flutter.embedding.android.FlutterActivity
import io.flutter.embedding.engine.FlutterEngine
import io.flutter.plugin.common.MethodCall;
import io.flutter.plugin.common.MethodChannel
import android.content.Context
import android.content.ContextWrapper
import android.content.Intent
import android.content.IntentFilter
import android.os.Build.VERSION
import android.os.Build.VERSION_CODES
import android.util.Log
import android.app.Activity
import android.app.PendingIntent
import android.content.BroadcastReceiver
import android.telephony.SmsManager

class SmsManager

abstract class MainActivity : FlutterActivity(), MethodChannel.MethodCallHandler {
    private var channel: MethodChannel? = null
    var sendSMS_return: HashMap<String, String?> = HashMap()

    protected override fun onCreate(@Nullable savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        channel = MethodChannel(getFlutterEngine()!!.getDartExecutor(), "MY_FLUTTER_APP_CHANNEL")
        channel!!.setMethodCallHandler(this)
    }

    public override fun onMethodCall(@NonNull call: MethodCall, @NonNull result: MethodChannel.Result) {
        if (call.method.equals("sendSMS")) {
            Log.e("sendSMS", "Function Started Running")
//            Handler handler = new Handler(Application.Context.MainLooper);
//            handler.post(object : Runnable() {
//            Handler(Looper.getMainLooper()).post(object : Runnable() {
              runOnUiThread(object : Runnable() {     // <--- Error Here
                public override fun run() {
                    val paramsList: HashMap<String, String> = call.arguments as HashMap<String, String>
                    val sentinelPhoneNumber = paramsList.get("phoneNo")
                    val message = paramsList.get("msgText")
                    sendSMS_return.clear()
                    var SENT = "SMS_SENT"
                    var DELIVERED = "SMS_DELIVERED"
                    lateinit var sentPI: PendingIntent
                    lateinit var deliveredPI: PendingIntent
                    val delay = 5000 // 1000 milliseconds == 1 second
                    var isSMSSent = false
                    var isSMSDelivered = false
                    sentPI = PendingIntent.getBroadcast(ContextWrapper(applicationContext), 0, Intent(SENT), PendingIntent.FLAG_IMMUTABLE)
                    deliveredPI = PendingIntent.getBroadcast(ContextWrapper(applicationContext), 0, Intent(DELIVERED), PendingIntent.FLAG_IMMUTABLE)
                    // if (requestSmsPermission()){
                    val smsManager = SmsManager.getDefault()
                    smsManager.sendTextMessage(sentinelPhoneNumber, null, message, sentPI, deliveredPI)
                    // }

                    ContextWrapper(applicationContext).registerReceiver(
                        object : BroadcastReceiver() {
                            override fun onReceive(arg0: Context, arg1: Intent) {
                                when (resultCode) {
                                    Activity.RESULT_OK -> isSMSDelivered = true
                                    Activity.RESULT_CANCELED -> { isSMSDelivered = false
                                    }
                                }
                            }
                        }, IntentFilter(DELIVERED)
                    )

                    ContextWrapper(applicationContext).registerReceiver(
                        object : BroadcastReceiver() {
                            override fun onReceive(arg0: Context, arg1: Intent) {
                                Log.e("SMS", "SMS Sender In Native Receiver Running")
                                when (resultCode) {
                                    Activity.RESULT_OK -> {
                                        // Log.e("SMS","SMS sent to book on/off job")
                                        isSMSSent = true
                                        Log.e("SMS", "SMS Sent Successfully.")
                                        //channel.invokeMethod("sendSMS", "SMS Sent Successfully.");
                                        sendSMS_return.put("phone", sentinelPhoneNumber);
                                        sendSMS_return.put("status", "Successful.");

                                    }
                                    SmsManager.RESULT_ERROR_GENERIC_FAILURE -> {
                                        isSMSSent = false
                                        Log.e("SMS", "SMS Not Sent Successfully.")
                                        //channel.invokeMethod("sendSMS", "SMS Not Sent Successfully.");
                                        sendSMS_return.put("phone", sentinelPhoneNumber);
                                        sendSMS_return.put("status", "Not Successful.");
                                    }
                                    SmsManager.RESULT_ERROR_NO_SERVICE -> {
                                        isSMSSent = false
                                        Log.e("SMS", "SMS Not Sent Successfully.")
                                        //channel.invokeMethod("sendSMS", "SMS Not Sent Successfully.");
                                        sendSMS_return.put("phone", sentinelPhoneNumber);
                                        sendSMS_return.put("status", "Not Successful.");
                                    }
                                    SmsManager.RESULT_ERROR_NULL_PDU -> {
                                        isSMSSent = false
                                        Log.e("SMS", "SMS Not Sent Successfully.")
                                        //channel.invokeMethod("sendSMS", "SMS Not Sent Successfully.");
                                        sendSMS_return.put("phone", sentinelPhoneNumber);
                                        sendSMS_return.put("status", "Not Successful.");
                                    }
                                    SmsManager.RESULT_ERROR_RADIO_OFF -> {
                                        isSMSSent = false
                                        Log.e("SMS", "SMS Not Sent Successfully.")
                                        //channel.invokeMethod("sendSMS", "SMS Not Sent Successfully.");
                                        sendSMS_return.put("phone", sentinelPhoneNumber);
                                        sendSMS_return.put("status", "Not Successful.");
                                    }
                                    else -> {
                                        Log.e("SMS", "SMS Not Sent Successfully.")
                                        //_channel.invokeMethod("sendSMS", "SMS Not Sent Successfully.");
                                        sendSMS_return.put("phone", sentinelPhoneNumber);
                                        sendSMS_return.put("status", "Not Successful.");
                                    }
                                }
                                // Send SMS Via Native Code

                                // Send Data To Flutter(Dart) via HashMap
                                channel.invokeMethod("sendSMS", sendSMS_return);
                                Log.e("sendSMS_return", Gson().toJson(sendSMS_return))
                                // Send Data To Flutter(Dart) via HashMap
                            }
                        }, IntentFilter(SENT)
                    )

                    // Invoke Return Dart Method
                    channel!!.invokeMethod("sendSMS", sendSMS_return);
                }
            })

        }
    }
}

And...

andriod_service.dart

import 'package:flutter/services.dart';


class AndroidService {
  AndroidService() {
    _channel.setMethodCallHandler(_methodCallHandler);
  }

  final MethodChannel _channel = const MethodChannel('MY_FLUTTER_APP_CHANNEL');

  Function(String, String)? _loginSuccessCallback;

  Future<void> sendSMS(String phoneNo, String msgText, {Function(String, String)? callback}) async {
    _loginSuccessCallback = callback;
    var params = {'phoneNo': phoneNo, 'msgText': msgText};
    // Call The Native Method 'sendSMS'
    await _channel.invokeMethod('sendSMS', params);
  }

  Future<dynamic> _methodCallHandler(MethodCall call) async {
    String method = call.method;
    // Get Return From The Native Method 'sendSMS'
    if (method == 'sendSMS') {
      if (_loginSuccessCallback != null) {
        final map = call.arguments;
        _loginSuccessCallback?.call(map['key'] as String, map['value'] as String);
      }
    }
  }

}

And I call this in my flutter app as...

final AndroidService androidService = AndroidService();
androidService.sendSMS(phoneNo, msg, callback: (String key, String value) {
  print("MY_FLUTTER_APP_CHANNEL [key: $key, value: $value]");
});

But I am getting error in MainActivity.kt as c: /Users/MY_PC/AndroidStudioProjects/my_flutter_app/android/app/src/main/kotlin/com/example/retrofit_mine/MainActivity.kt: (263, 46): This class does not have a constructor that I commented on MainActivity.kt code shared above.

So how to fix this...???

CodePudding user response:

You just need to remove the parenthesis after Runnable interface:

From this:

runOnUiThread(object : Runnable() <--- remove this {

To this:

runOnUiThread(object : Runnable {

CodePudding user response:

The other answer shows the problem with your code. Just want to mention, you can simplify the syntax in this case, since Runnable is a SAM interface (only has one method).

This

runOnUiThread(object : Runnable {
    public override fun run() {
        //...
    }
})

can be replaced with:

runOnUiThread {
    //...
}

to accomplish exactly the same thing with less nesting and brackets to keep track of.

  • Related