Can't change text in textview from broadcast receiver - android

I have the following code of activity:
import android.content.BroadcastReceiver
import android.content.Context
import android.content.Intent
import android.content.IntentFilter
import android.os.Bundle
import android.os.Handler
import android.support.v7.app.AppCompatActivity
import com.mikhailovskii.androidacademytask8.R
import com.mikhailovskii.androidacademytask8.data.service.ProgressIntentService
import kotlinx.android.synthetic.main.activity_main.*
class ProgressActivity : AppCompatActivity() {
private val receiver = ActivityBroadcastReceiver(Handler())
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
tv_progress.text="0"
val intentFilter = IntentFilter(ProgressIntentService.INTENT_ACTION)
registerReceiver(receiver, intentFilter)
btn_intent_service.setOnClickListener {
val intent = Intent(this, ProgressIntentService::class.java)
startService(intent)
}
btn_service.setOnClickListener {
}
}
override fun onDestroy() {
super.onDestroy()
unregisterReceiver(receiver)
}
//FIXME handler1 seems strange, but passing to constructor doesn't work
class ActivityBroadcastReceiver (handler1: Handler) : BroadcastReceiver() {
private val handler = handler1
override fun onReceive(context: Context?, intent: Intent?) {
val progress = intent?.getIntExtra(ProgressIntentService.EXTRA_KEY_OUT, 0)
handler.post { tv_progress.text = progress }
}
}
}
I need to change the text in tv_progress from BroadcastReceiver. For this purpose I added Handler here. But name of tv is highlighted in red and studio writes that
Unresolved reference. None of the following candidates is applicable because of receiver type mismatch
So, what's the reason of this problem and how can I solve it? Thanks in advance!

Please check the name on broadcast in below line :
val intentFilter = IntentFilter(ProgressIntentService.INTENT_ACTION)

Related

I am not able to validate my new activity

I created a new empty activity for my project but I am getting an error. The activity file as well as the layout file is shown in red color. I tried creating an intent object from MainActivity, in order to start this activity but received the following error
Classifier 'Details' does not have a companion object, and thus must
be initialized here
I've attached a screenshot of my android studio.
Code for new activity
package com.example.safetyapp
import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
class Details : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_details)
}
}
package com.example.safetyapp
import android.content.Intent
import android.os.Bundle
import android.widget.Button
import androidx.appcompat.app.AppCompatActivity
import com.firebase.ui.auth.AuthUI
import com.google.firebase.auth.FirebaseAuth
class MainActivity : AppCompatActivity() {
final val AUTH_REQUEST_CODE = 7192
lateinit var firebaseAuth:FirebaseAuth
lateinit var listener: FirebaseAuth.AuthStateListener
lateinit var providers: List<AuthUI.IdpConfig>
override fun onStart(){
super.onStart()
firebaseAuth.addAuthStateListener(listener)
}
override fun onStop(){
super.onStop()
if(listener!=null){
firebaseAuth.removeAuthStateListener(listener)
}
}
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
val button2 = findViewById<Button>(R.id.button2)
val defence = findViewById<Button>(R.id.Defence)
button2.setOnClickListener{
val myintent = Intent(this, Details::class.java)
}
init()
}
private fun init() {
providers = arrayListOf(AuthUI.IdpConfig.PhoneBuilder().build(),
AuthUI.IdpConfig.EmailBuilder().build())
firebaseAuth = FirebaseAuth.getInstance()
listener = object:FirebaseAuth.AuthStateListener{
override fun onAuthStateChanged(p0: FirebaseAuth) {
val user = p0.currentUser
if(user!= null){
// Do something
}
else{
startActivityForResult(AuthUI.getInstance()
.createSignInIntentBuilder()
.setAvailableProviders(providers)
.setLogo(R.drawable.logo)
.build(),AUTH_REQUEST_CODE)
}
}
}
}
}
You didn't import the Details class, add this line between your MainActivity class imports
import com.example.safetyapp.Details

How to invoke flutter method from broadcastReceiver class?

I am trying to awake flutter method on a received call. I already done the receiving part, but I can't awake flutter method yet.
I tried calling method channel in onReceive() method in MainActivity.kt class, but it gives me error. method channel only seems to work in onCreate() method.
The question is how can I invoke flutter method in onReceive() or is there another way to do it?
MainActivity.kt
import android.Manifest
import android.content.BroadcastReceiver
import android.content.Context
import android.content.Intent
import android.content.IntentFilter
import android.content.pm.PackageManager
import android.os.Build
import android.os.Bundle
import android.widget.Toast
import androidx.annotation.RequiresApi
import androidx.core.app.ActivityCompat
import androidx.core.content.ContextCompat
import io.flutter.app.FlutterActivity
import io.flutter.plugin.common.MethodCall
import io.flutter.plugin.common.MethodChannel
import io.flutter.plugins.GeneratedPluginRegistrant
class MainActivity: FlutterActivity(){
var updateUIReciver: BroadcastReceiver? = null
#RequiresApi(Build.VERSION_CODES.O)
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
GeneratedPluginRegistrant.registerWith(this)
registerReceiver(broadcastReceiver, IntentFilter("Service.to.activity"));
val channel = "my.data"
val methodChannel = MethodChannel(flutterView, channel)
val map: HashMap<String, String> = HashMap()
val permissionCheck: Int = ContextCompat.checkSelfPermission(this, Manifest.permission.READ_PHONE_STATE)
if (permissionCheck == PackageManager.PERMISSION_GRANTED) {
Toast.makeText(this, "Permission granted ", Toast.LENGTH_LONG).show();
} else {
//TODO
ActivityCompat.requestPermissions(this, arrayOf(Manifest.permission.READ_PHONE_STATE), 4);
Toast.makeText(this, "Permission not granted ", Toast.LENGTH_LONG).show();
}
methodChannel.setMethodCallHandler { call: MethodCall, result: MethodChannel.Result? ->
if (call.method == "callMyFunction") {
methodChannel.invokeMethod("callMyFunction", map)
} else {
}
}
}
var broadcastReceiver: BroadcastReceiver = object : BroadcastReceiver() {
override fun onReceive(context: Context, intent: Intent) {
Toast.makeText(context, "Incoming call received", Toast.LENGTH_LONG).show()
// I can't call "methodChannel.invokeMethod("callMyFunction", map)" here cause of error.
}
}
}
MyBroadcastReceiver.kt
import android.app.Service
import android.content.BroadcastReceiver
import android.content.Context
import android.content.Intent
import android.telephony.PhoneStateListener
import android.telephony.TelephonyManager
import androidx.core.app.NotificationCompat
import android.app.NotificationManager;
import android.os.Build;
import android.os.IBinder;
import android.widget.Toast
class MyBroadcastReceiver : BroadcastReceiver() {
override fun onReceive(context: Context, intent: Intent) {
val telephony = context.getSystemService(Service.TELEPHONY_SERVICE) as TelephonyManager
telephony.listen(object : PhoneStateListener() {
override fun onCallStateChanged(state: Int, incomingNumber: String) {
super.onCallStateChanged(state, incomingNumber)
context.sendBroadcast(Intent("Service.to.activity"))
}
}, PhoneStateListener.LISTEN_CALL_STATE)
}
}
Flutter code
const platform = const MethodChannel('my.data');
Future<void> _receiveFromNative(MethodCall call) async {
try {
if (call.method == "callMyFunction") {
print("Received in flutter");
}
} on PlatformException catch (e) {}
}
platform.setMethodCallHandler(_receiveFromNative);
Basically you can't access methodChannel in BroadcastReceiver directly so you have to make methodChannel in compaion object So,
Add these lines to your MainActivity
companion object {
lateinit var methodChannel: MethodChannel
}
And in onCreate method of MainActivity replace
val methodChannel = MethodChannel(flutterView, channel)
To :
methodChannel = MethodChannel(flutterView, channel)
now you can use MainActivity.methodChannel anywhere in your app.

Kotlin: Set variable in secondary activity conditional on OnClick in main activity

I have a main activity with four card views. I want each card view, when clicked, to go to a multiple choice quiz specific to that card. In my questions activity, I need to identify which of the card views was clicked in order to determine which set of questions should be called. I tried using boolean values in my main activity but am not able to reference them in my questions activity.
Main Activity
import android.content.Intent
import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import kotlinx.android.synthetic.main.activity_main.*
class MainActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
c1.setOnClickListener {
val intent = Intent(this, QuestionsActivity::class.java)
intent.putExtra("boolean_a", true);
startActivity(intent)
finish()
}
c2.setOnClickListener {
val intent = Intent(this, QuestionsActivity::class.java)
intent.putExtra("boolean_b", true);
startActivity(intent)
finish()
}
c3.setOnClickListener {
val intent = Intent(this, QuestionsActivity::class.java)
intent.putExtra("boolean_c", true);
startActivity(intent)
finish()
}
c4.setOnClickListener {
val intent = Intent(this, QuestionsActivity::class.java)
intent.putExtra("boolean_d", true);
startActivity(intent)
finish()
}
}
}
The intent.putExtra("booleanA", true) in my main activity and if boolean statement and var booleanA = getIntent().getExtras()!!.getBoolean("booleanA") declaration in my secondary activity crash the app. If I remove intent.putExtra("booleanA", true) and var booleanA = getIntent().getExtras()!!.getBoolean("booleanA")and remove the if statement, leaving just mQuestionsList = Constants.getQuestions(), the app no longer crashes
import android.content.Intent
import android.graphics.Color
import android.graphics.Typeface
import android.os.Bundle
import android.view.View
import android.widget.TextView
import android.widget.Toast
import androidx.appcompat.app.AppCompatActivity
import androidx.core.content.ContextCompat
import kotlinx.android.synthetic.main.activity_questions.*
class QuestionsActivity : AppCompatActivity(), View.OnClickListener {
private var mCurrentPosition:Int = 1
private var mQuestionsList:ArrayList<Questions>? = null
private var mSelectedOptionPosition:Int = 0
private var mCorrectAnswers: Int = 0
var booleanA = getIntent().getExtras()!!.getBoolean("booleanA")
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_questions)
if (booleanA){
mQuestionsList = Constants.getQuestions()
}
setQuestion()
radio_button1.setOnClickListener(this)
radio_button2.setOnClickListener(this)
radio_button3.setOnClickListener(this)
radio_button4.setOnClickListener(this)
}
You Should do like this
class QuestionsActivity : AppCompatActivity(), View.OnClickListener {
private var mCurrentPosition:Int = 1
private var mQuestionsList:ArrayList<Questions>? = null
private var mSelectedOptionPosition:Int = 0
private var mCorrectAnswers: Int = 0
//don't get the intent data here
var booleanA: Boolean = false
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_questions)
//get the intent data here
booleanA = getIntent().getExtras()!!.getBoolean("booleanA")
if (booleanA){
mQuestionsList = Constants.getQuestions()
}
setQuestion()
radio_button1.setOnClickListener(this)
radio_button2.setOnClickListener(this)
radio_button3.setOnClickListener(this)
radio_button4.setOnClickListener(this)
}

MissingPluginException on try of use custom EventChannel in flutter

Recently I decided to create flutter application I have only problem with one thing.
I wanted to create custom stream to detect unplug of headset to stop music playing.
This is my MainActivity.
package com.example.radio24
import android.content.BroadcastReceiver
import android.content.IntentFilter
import android.content.Context
import android.content.Intent
import android.media.AudioManager
import android.os.Bundle
import android.os.PersistableBundle
import io.flutter.embedding.android.FlutterActivity
import io.flutter.plugin.common.EventChannel
class MainActivity: FlutterActivity() {
private val HEADPHONES_LISTENER_CHANNEL = "com.radioanime24.dev/headphones"
lateinit var broadCastReceiver: BroadcastReceiver;
override fun onCreate(savedInstanceState: Bundle?, persistentState: PersistableBundle?) {
super.onCreate(savedInstanceState, persistentState)
EventChannel(flutterEngine?.dartExecutor?.binaryMessenger, HEADPHONES_LISTENER_CHANNEL).setStreamHandler(
object: EventChannel.StreamHandler {
override fun onListen(arguments: Any?, events: EventChannel.EventSink?) {
broadCastReceiver = object : BroadcastReceiver() {
override fun onReceive(contxt: Context?, intent: Intent?) {
when (intent?.action) {
AudioManager.ACTION_AUDIO_BECOMING_NOISY -> {
events?.success("HEADPHONES_UNPLUGGED")
}
}
}
}
val filter = IntentFilter(AudioManager.ACTION_AUDIO_BECOMING_NOISY)
registerReceiver(broadCastReceiver, filter);
}
override fun onCancel(arguments: Any?) {
unregisterReceiver(broadCastReceiver)
}
}
)
}
}
In dart I am trying to consume this stream with:
Stream headPhonesStateStream = EventChannel('com.radioanime24.dev/headphones').receiveBroadcastStream();
headPhonesStateStream.listen((event) {
if (event == 'HEADPHONES_UNPLUGGED') {
if (AudioService.playbackState.playing) {
AudioService.pause();
}
}
});
But I am receiving error:
MissingPluginException(No implementation found for method listen on channel com.radioanime24.dev/headphones)
How should I register eventchannel to omit this error?
I believe you should override the onCreate(savedInstanceState: Bundle?) method instead of onCreate(savedInstanceState: Bundle?, persistentState: PersistableBundle?) of the Activity.

get phoneNumber and messagetext I get from broadcast receiver to textviews in main activity and calling phoneNumber

I cant quite seem to get the values from Broadcast Receiver to textviews in Main Activity.
In Android (KOTLIN) I managed to create a broadcast receiver that gets the phoneNumber and text Message in a Toast Event When an SMS message is received.
In main activity, I also have a button that when clicked calls #133# to check my Airtime Balance.
smsReceive Class code;
package com.example.demmo
import android.content.BroadcastReceiver
import android.content.Context
import android.content.Intent
import android.os.Build
import android.telephony.SmsMessage
import android.widget.Toast
import android.app.Activity
class SmsReceiver : BroadcastReceiver(){
var activity : Activity? = null
override fun onReceive(context: Context, intent: Intent) {
val extras = intent.extras
if(extras != null){
val sms = extras.get("pdus") as Array<Any>
for(i in sms.indices) {
val format = extras.getString("format")
var smsMessage = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
SmsMessage.createFromPdu(sms[i] as ByteArray, format)
} else {
SmsMessage.createFromPdu(sms[i] as ByteArray)
}
val phoneNumber = smsMessage.originatingAddress
val messageText = smsMessage.messageBody.toString()
Toast.makeText(context, "From: $phoneNumber Message: $messageText", Toast.LENGTH_LONG).show()
}
}
}
}
MainActivity.kt code
package com.example.demmo
import android.content.pm.PackageManager
import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import androidx.core.app.ActivityCompat
import android.Manifest
import android.annotation.SuppressLint
import android.content.Intent
import android.net.Uri
import kotlinx.android.synthetic.main.activity_main.*
class MainActivity : AppCompatActivity() {
private val requestReceiveSms = 2
val balance = "*144%23"
val REQUEST_PHONE_CALL = 1
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
if (ActivityCompat.checkSelfPermission(this, Manifest.permission.RECEIVE_SMS)
!= PackageManager.PERMISSION_GRANTED
) {
ActivityCompat.requestPermissions(this, arrayOf(Manifest.permission.RECEIVE_SMS), requestReceiveSms)
}
btnBalance.setOnClickListener {
if (ActivityCompat.checkSelfPermission(this, Manifest.permission.CALL_PHONE) != PackageManager.PERMISSION_GRANTED){
ActivityCompat.requestPermissions(this, arrayOf(Manifest.permission.CALL_PHONE), REQUEST_PHONE_CALL)
} else{
balance()
}
}
}
#SuppressLint("MissingPermission")
private fun balance() {
val callIntent = Intent(Intent.ACTION_CALL)
callIntent.data = (Uri.parse("tel:" + balance))
startActivity(callIntent)
}
override fun onRequestPermissionsResult(requestCode: Int, permissions: Array<out String>, grantResults: IntArray) {
if(requestCode == REQUEST_PHONE_CALL)balance
}
}
I would like some code after ' Toast.makeText(context, "From: $phoneNumber Message: $messageText", Toast.LENGTH_LONG).show()' to put the values phoneNumber and textmessage to TextViews txtPhone and txtSMS respectively and 'Click' or call phoneNumber programtically.
I can not provide working code as I neither have Android nor Kotlin installed right now.
Basically you should follow this approach. The observer pattern is a widely used concept. And maybe the cleanest way to achieve what you're looking for:
Communication between BroadcastReceiver and Activity - android
With some dirty code, you would be able to call "fun balance" from the SmsReceiver class. But that's something you really don't want to do. You can try getting it done as an exercise, but I don't recommend using it. Not if there are better ways ;)
If, for some reason the observer pattern does not work, I can elaborate on other possiblities.
-------------- EDIT -------------
Ok, if you're having trouble with the observer pattern, I will think of something else.
You want to call "fun balance" from the other activity. The Broadcast-Receiver has no reference to the Main class. So add to your MainActivity
static MainActivity reference
public static MainActivity getInstance() {
return reference;
}
Add this to the constructor of the MainActivity
reference = this
In the SmsReceiver right after the toast, add:
MainActivity ma = MainActivity.getInstance()
ma.balance()
Don't forget to declare balance as public, else it won't work.
I said I can't test it ... There might be a problem as I think that the BroadcastReceiver is executed inside of another thread, so you might have to invoke this on the other Thread. Not sure if you really have to do that though.
If that does not work as well, check these link:
Calling activity class method from Service class
The first 2 answers look promising

Categories

Resources