could not find any reference on using kotlin to detect incoming call using BroadcastReceiver created dynamically. most java program add intent in the manifest. I wanted to use Broadcastreciever in the specific activity. I used below code but not working. Can anyone help?
Problem:
1. How to set up the Intent Filter for the Phone_State
class MainActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
val broadCastReceiver = object : BroadcastReceiver() {
override fun onReceive(contxt: Context?, intent: Intent?) {
try {
println("Receiver start")
val state = intent!!.getStringExtra(TelephonyManager.EXTRA_STATE)
val incomingNumber =
intent.getStringExtra(TelephonyManager.EXTRA_INCOMING_NUMBER)
if (state == TelephonyManager.EXTRA_STATE_RINGING) {
Toast.makeText(applicationContext, "Incoming Call State", Toast.LENGTH_SHORT).show()
Toast.makeText(applicationContext,
"Ringing State Number is -$incomingNumber",
Toast.LENGTH_SHORT
).show()
}
if (state == TelephonyManager.EXTRA_STATE_OFFHOOK) {
Toast.makeText(applicationContext, "Call Received State", Toast.LENGTH_SHORT).show()
}
if (state == TelephonyManager.EXTRA_STATE_IDLE) {
Toast.makeText(applicationContext, "Call Idle State", Toast.LENGTH_SHORT).show()
}
} catch (e: Exception) {
e.printStackTrace()
}
}
}
// Set When broadcast event will fire.
val filter = IntentFilter(Intent.ACTION_CONFIGURATION_CHANGED)
LocalBroadcastManager.getInstance(this).registerReceiver(broadCastReceiver, filter)
}
}
Related
I have a RecyclerView with a list of customLayout alarms. Each alarm has a switch for on and off.
in my adapter I have a setOnCheckedChangeListener that checks if the switch has been manually turned on or off through the HomeFragment and then calls the AlarmManager to cancel or schedule an alarm.
But when an alarm is called after the broadcast is received, I then need the switch to be turned off automatically ( assuming the alarm isn't repeating)
How can I go about this?
Adapter:
val switch = holder.itemView.findViewById<Switch>(R.id.switch_alarm)
switch.setOnCheckedChangeListener { _, isChecked ->
if (onItemClickListener != null) {
if (isChecked) {
onItemClickListener?.setSwitchOn(currentItem)
} else {
onItemClickListener?.setSwitchOff(currentItem)
}
}
}
Home Fragment:
override fun setSwitchOn(alarm: Alarm) {
val toastTime = if (alarm.minute > 9) {
"${alarm.hour}:${alarm.minute}"
} else {
"${alarm.hour}:0${alarm.minute}"
}
val alarmManager = AlarmManager(
alarm.id,
alarm.hour,
alarm.minute,
true,
alarm.repeat,
)
alarmManager.cancel(requireContext())
Toast.makeText(context, "Alarm set for $toastTime", Toast.LENGTH_SHORT).show()
}
override fun setSwitchOff(alarm: Alarm) {
val alarmManager = AlarmManager(
alarm.id,
alarm.hour,
alarm.minute,
true,
alarm.repeat,
)
alarmManager.cancel(requireContext())
Toast.makeText(context, "Alarm cancelled", Toast.LENGTH_SHORT).show()
}
Receiver:
override fun onReceive(context: Context?, intent: Intent?) {
val intent = Intent(context, AlarmRingActivity::class.java)
intent.flags = Intent.FLAG_ACTIVITY_NEW_TASK
context!!.startActivity(intent)
}
}
i need a method to continuously get location updates in my application even when my application is in background. i have tried using Service and BroadcastReceiver but when application goes into background, location updates are stopped.
here is my Code with boradcast Receiver:-
MainActivity:
class MainActivity : AppCompatActivity() {
companion object {
private var instance: MainActivity? = null
fun getMainInstance(): MainActivity? {
return instance
}
}
private lateinit var client: FusedLocationProviderClient
private lateinit var request: LocationRequest
#RequiresApi(Build.VERSION_CODES.M)
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
instance = this
client = LocationServices.getFusedLocationProviderClient(applicationContext)
request = LocationRequest.create()
request.priority = LocationRequest.PRIORITY_HIGH_ACCURACY
request.interval = 1000
request.fastestInterval = 1000
if (ActivityCompat.checkSelfPermission(
this,
Manifest.permission.ACCESS_FINE_LOCATION
) != PackageManager.PERMISSION_GRANTED && ActivityCompat.checkSelfPermission(
this,
Manifest.permission.ACCESS_COARSE_LOCATION
) != PackageManager.PERMISSION_GRANTED
) {
requestPermissions(
arrayOf(
android.Manifest.permission.ACCESS_FINE_LOCATION,
android.Manifest.permission.ACCESS_COARSE_LOCATION
), 2201
)
} else {
client.requestLocationUpdates(request, getPendingIntent()!!)
}
}
override fun onPause() {
super.onPause()
Toast.makeText(applicationContext, "paused", Toast.LENGTH_SHORT).show()
}
override fun onStop() {
super.onStop()
Toast.makeText(applicationContext, "stopped", Toast.LENGTH_SHORT).show()
}
override fun onDestroy() {
super.onDestroy()
client.removeLocationUpdates(getPendingIntent()!!)
Toast.makeText(applicationContext, "destroyed", Toast.LENGTH_SHORT).show()
}
fun toastMessage(location: String) {
this.runOnUiThread {
Toast.makeText(
this,
location,
Toast.LENGTH_SHORT
).show()
}
}
private fun getPendingIntent(): PendingIntent? {
val intent = Intent(this,MyLocationReceiver::class.java)
intent.setAction(MyLocationReceiver.ACTION_PROCESS_UPDATE)
return PendingIntent.getBroadcast(this,0,intent,PendingIntent.FLAG_UPDATE_CURRENT)
}
}
BroadcastReceiver:
class MyLocationReceiver : BroadcastReceiver() {
companion object{
val ACTION_PROCESS_UPDATE = "com.example.backgroundlocation.UPDATE_LOCATION"
}
override fun onReceive(context: Context?, intent: Intent?) {
if(intent != null) {
val action = intent.action
if (action.equals(ACTION_PROCESS_UPDATE) && LocationResult.hasResult(intent)){
val locationResult = LocationResult.extractResult(intent)
try {
Log.d("onLocationReceived", locationResult.toString())
//MainActivity.getMainInstance()?.toastMessage(locationResult.toString())
} catch (e: Exception) {
Toast.makeText(context, e.toString(), Toast.LENGTH_SHORT).show()
}
} else {
//MainActivity.getMainInstance()?.toastMessage("no result")
}
}
}
}
to me, the solution to this seems impossible.
Is there any way to update location when application is in background ? Kindly help me out!
To access the location while in the background you need to get this permission as well from the user in the Manifest
<uses-permission android:name="android.permission.ACCESS_BACKGROUND_LOCATION" />
While giving the permission user needs to select allow all the time for location.
Im implementing a simple blutooth classic scan from the official docs on my Redmi Note 4 (Bluetooth 4.1).
However I am not seeing a toast that should appear when the onReceive function on the broadcast receiver is called.
What could be wrong here?
class MainActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
defaultAdapter = BluetoothAdapter.getDefaultAdapter()
if (defaultAdapter == null) {
toast("no adapter")
return
}
if (!defaultAdapter!!.isEnabled) {
val enableBluetoothIntent = Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE)
startActivityForResult(enableBluetoothIntent, REQUEST_ENABLE_BLUETOOTH)
}
searchButton.setOnClickListener { newDevicesList() }
val filter = IntentFilter(BluetoothDevice.ACTION_FOUND)
Log.i("receiver", "registering receiver")
registerReceiver(receiver, filter)
}
private val receiver = object : BroadcastReceiver() {
override fun onReceive(context: Context, intent: Intent) {
toast("maybe i find new device who know")
when (intent.action) {
BluetoothDevice.ACTION_FOUND -> {
// Discovery has found a device. Get the BluetoothDevice
// object and its info from the Intent.
val device: BluetoothDevice? =
intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE)
val deviceName = device?.name
val deviceHardwareAddress = device?.address // MAC address
toast("device $deviceName was found")
}
BluetoothAdapter.ACTION_DISCOVERY_FINISHED -> {
context.unregisterReceiver(this)
}
}
if (defaultAdapter!!.isDiscovering) {
toast("scan already in progress")
} else {
toast("starting discovery")
defaultAdapter!!.startDiscovery();
}
}
How do i know that the onReceive function never gets called? cause this toast toast("maybe i find new device who know") never appears.
I want to use my BroadcastReceiver as sender of data into my activity. For this reason I'm using LocalBroadcastManager. This manager is used to register and unregister my receiver. Problem is that Context in onReceive method is different than Context in onStart and onStop method.
I need to pass activity context into my BroadcastReceiver or instance of LocalBroadcastManager initialized inside Activity. Because my receiver is not receiving any data.
Maybe it is not fault of this manager context but I don't know why it doesnt work since I implemented this manager.
class GPSReceiver: BroadcastReceiver(){
companion object{
const val GPS_PAYLOAD = "gps_payload"
}
override fun onReceive(context: Context, intent: Intent) {
try {
val locationManager = context.getSystemService(Context.LOCATION_SERVICE) as LocationManager
val int = Intent(GPS_PAYLOAD)
if (locationManager.isProviderEnabled(LocationManager.GPS_PROVIDER)) {
int.putExtra(GPS_PAYLOAD, true)
} else {
int.putExtra(GPS_PAYLOAD, false)
}
LocalBroadcastManager.getInstance(context).sendBroadcast(int)
} catch (ex: Exception) {
}
}
}
Registering receiver inside Activity:
private val gpsStatusReceiver = object: BroadcastReceiver() {
override fun onReceive(context: Context?, intent: Intent?) {
App.log("isGpsEnabled: onReceive")
val gpsStatus = intent?.extras?.getBoolean(GPS_PAYLOAD)
if (gpsStatus != null) {
if (gpsStatus){
App.log("isGpsEnabled: true")
hideGpsSnackbar()
} else {
App.log("isGpsEnabled: false")
showGpsSnackbar()
}
} else {
App.log("isGpsEnabled: null")
}
}
}
override fun onStart() {
super.onStart()
LocalBroadcastManager.getInstance(this).apply {
val filter = IntentFilter()
filter.apply {
addAction("android.location.PROVIDERS_CHANGED")
addAction(GPS_PAYLOAD)
}
registerReceiver(gpsStatusReceiver, filter)
}
}
I have seen your code. So there is not issue with context, but in the approach.
Your are registering your reciever with the same strings in which you are getting you data inside the Reciever.
So Send Your broadcast from Fragment/Activity
Send BroadCast Like
private fun sendSuccessfulCheckoutEvent() {
val intent = Intent("successful_checkout_event")
intent.putExtra("cartID", cartId)
LocalBroadcastManager.getInstance(this).sendBroadcast(intent)
}
And Listen it in Activity/Fragment like this
1) Create broadcast Reciever
private val checkoutDoneReciever : BroadcastReceiver = object : BroadcastReceiver(){
override fun onReceive(context: Context?, intent: Intent?) {
val cartNumbers = intent.getIntExtra("cartID", 0)
Log.d("receiver", "Got message: $cartNumbers.toString()")
}
}
2) Register it in onCreate()/onStart()
LocalBroadcastManager.getInstance(this).registerReceiver(cartUpdatedReceiver,IntentFilter("successful_checkout_event"))
3) Unregister it in onDestroy()
LocalBroadcastManager.getInstance(this).unregisterReceiver(cartUpdatedReceiver)
Im working on an android app which uses notifications frequently.
I chose to set the alarms via setting activity rather then Main Activity but I couldn't manage to find out how to cancel the Alarm Manager via the settingActivity immediately after pressing the switch.
I only found out how to cancel the notifications on the MainActivity, which stops them only after closing and opening the app.
what is the preferred way to do it?
from SettingActivity.kt:
class NotificationPreferenceFragment : PreferenceFragment() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
addPreferencesFromResource(R.xml.pref_notification)
setHasOptionsMenu(false)
var switchPref: Preference = findPreference(getString(R.string.pref_notifications_switch_key))
switchPref.onPreferenceChangeListener = OnPreferenceChangeListener { preference, isChecked ->
var toast: Toast = if (isChecked as Boolean) {
Toast.makeText(activity, "switch is ON", Toast.LENGTH_SHORT)
} else {
Toast.makeText(activity, "notifications is OFF", Toast.LENGTH_SHORT)
}
toast.show()
true
}
}
cancel method from MainActivity:
fun cancelAlarm() {
alarmMgr = applicationContext.getSystemService(Context.ALARM_SERVICE) as AlarmManager
val intent1 = Intent(applicationContext, AlarmReceiver::class.java)
alarmIntent = PendingIntent.getBroadcast(applicationContext, 0, intent1, PendingIntent.FLAG_UPDATE_CURRENT)
alarmMgr!!.cancel(alarmIntent)
}
As said by a commenter, just use BroadcastReceiver
NotificationPreferenceFragment.java
class NotificationPreferenceFragment : PreferenceFragment() {
val broadcaster: LocalBroadcastManager? = null;
override fun onCreate(savedInstanceState: Bundle?) {
broadcaster = LocalBroadcastManager.getInstance(this);
}
// Inside your onPreferenceChangeListener, depends on when you want to call it, either ON or OFF
Intent intent = new Intent("YOUR_DATA_STRING");
intent.putExtra(ANY_EXTRAS_STRING, DATA_ITSELF);
broadcaster.sendBroadcast(intent);
}
MainActivity.java
import android.support.v4.content.LocalBroadcastManager;
override fun onStart() {
super.onStart()
LocalBroadcastManager.getInstance(this).registerReceiver(MYReceiver,
IntentFilter("YOUR_DATA_STRING")
)
}
private val MYReceiver = object : BroadcastReceiver() {
fun onReceive(context: Context, intent: Intent) {
if (intent.extras != null) {
// get any extras if neccessary
// intent.extras!!.getString("ANY_EXTRAS_STRING")
cancelAlarm()
}
}
}
override fun onStop() {
super.onStop()
LocalBroadcastManager.getInstance(this).unregisterReceiver(MYReceiver)
}