I am trying to implement the wifi change state feature in my Activity but I am getting multiple time calls in Receive.
public class MyReceiver extends BroadcastReceiver {
private IStatusChangeListener listener;
#Override
public void onReceive(final Context context, final Intent intent) {
String status = getConnectivityStatusString(context);
Log.d("network", status);
if (status.isEmpty() || status.equals("Wifi enabled") || status.equals("Wifi enabled")) {
listener.onConnected(true);
} else {
Toast.makeText(context, "NOt Connected", Toast.LENGTH_LONG).show();
listener.onConnected(false);
}
}
public void myBrodCastReceiver(IStatusChangeListener listener) {
this.listener = listener;
}
}
in my Activity :
lateinit var myReceiver: MyReceiver
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
AndroidInjection.inject(this)
setContentView(R.layout.activity_r3_main)
setSupportActionBar(toolbarmain)
val radius = resources.getDimension(R.dimen.roundcorner)
txtRove.text = getString(R.string.txt_live_video)
myReceiver = MyReceiver()
myReceiver.myBrodCastReceiver(this)
}
override fun onStart() {
super.onStart()
this.registerReceiver(myReceiver, IntentFilter(ConnectivityManager.CONNECTIVITY_ACTION))
}
override fun onPause() {
super.onPause()
this.unregisterReceiver(myReceiver);
}
in my Android manifest file :
<receiver android:name = "com.rovedashcam.newmodeule.base.wifirecciver.MyReceiver" android:exported="true">
<intent-filter>
<action android:name = "android.net.conn.CONNECTIVITY_CHANGE"
tools:ignore="BatteryLife" />
<action android:name = "android.net.wifi.WIFI_STATE_CHANGED" />
</intent-filter>
</receiver>
when I try to get the run code then I get multiple time calls back in MyReceiver class onReceive method I have to register the broadcast Receiver from one place and unregister from onpause method but I don't know why it's calling two times please help me in this.
You have registered the BroadcastReceiver twice. Once in the manifest and again in code. You only need to do the one or the other. If you want to register your BroadcastReceiver dynamically (in code), then remove the <receiver> declaration from the manifest.
Related
How do you detect a user pressing the call button on a connected Bluetooth Headset?
While multiple posts address the topic I think I have tried most (if not all) and still have not found a solution which works
The following simplified code connects to the Bluetooth headset in onResume()
It then logs a message if ANY intent is received (which it never does)
class MainActivity : AppCompatActivity() {
private lateinit var audioManager : AudioManager
private var headsetDevice: AudioDeviceInfo? = null // device used for audio input
private lateinit var mediaSession: MediaSession
private lateinit var headsetButtonIntentReceiver: HeadsetButtonIntentReceiver
private lateinit var headsetButtonIntentFilter: IntentFilter
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
window.addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON)
audioManager = getSystemService(Context.AUDIO_SERVICE) as AudioManager
mediaSession = MediaSession(this, packageName)
headsetButtonIntentFilter = IntentFilter(Intent.ACTION_CALL_BUTTON)
headsetButtonIntentReceiver = HeadsetButtonIntentReceiver()
}
class HeadsetButtonIntentReceiver : BroadcastReceiver() {
override fun onReceive(context: Context?, intent: Intent) {
Log.d(TAG, "HeadsetButtonIntentReceiver() !!!!")
abortBroadcast()
}
}
override fun onResume() {
super.onResume()
val devices = audioManager.availableCommunicationDevices
Log.d(TAG, "audioManager.availableCommunicationDevices found ${devices.size} devices")
headsetDevice = devices.firstOrNull { it.type == AudioDeviceInfo.TYPE_BLUETOOTH_SCO }
if (headsetDevice != null) {
Log.d(TAG, "setCommunicationsDevice ${headsetDevice!!.productName}")
if (!audioManager.setCommunicationDevice(headsetDevice!!)) Log.d(TAG, "Failed to connect to headset")
}
mediaSession.isActive = true
this.registerReceiver(headsetButtonIntentReceiver, headsetButtonIntentFilter)
}
override fun onStop() {
super.onStop()
if (headsetDevice != null)
audioManager.clearCommunicationDevice() // disconnect from the headset
mediaSession.release()
mediaSession.isActive = false
this.unregisterReceiver(headsetButtonIntentReceiver)
}
companion object {
const val TAG = "MediaButton"
}
}
I have tried adding different Button actions to the intent filter - also without success
headsetButtonIntentFilter = IntentFilter()
headsetButtonIntentFilter.addAction(Intent.ACTION_MEDIA_BUTTON)
headsetButtonIntentFilter.addAction(Intent.ACTION_CALL_BUTTON)
I have tried adding the intent into the Manifest (although several posts suggest this is not required)
<intent-filter>
<action android:name="android.intent.action.CALL_BUTTON" />
</intent-filter>
I have tried specifying the receiver in the Manifest - but also nothing
<receiver android:name=".MainActivity$HeadsetButtonIntentReceiver" android:exported="false">
<intent-filter>
<action android:name="android.intent.action.CALL_BUTTON"/>
</intent-filter>
</receiver>
For completeness I even tried overriding the onKeyDown() and dispatchKeyEvent() but these are also not being triggered
override fun onKeyDown(keyCode: Int, event: KeyEvent?): Boolean {
Log.d(TAG, "onKeyDown() KEYCODE $keyCode Event ${event?.action}")
return super.onKeyDown(keyCode, event)
}
override fun dispatchKeyEvent(event: KeyEvent?): Boolean {
Log.d(TAG, "dispatchKeyEvent() KEYCODE ${event?.keyCode} Event ${event?.action}")
return super.dispatchKeyEvent(event)
}
Frustratingly there are indications the code is close to working. Specifically a double press of the headset call button dials the previous number but when the above code is running that no longer occurs indicating the App is consuming the call button press. Unfortunately the App is not being notified of this action!
Happy to try solutions posted in previous questions I may have missed!
I am developing a sample app where my goal is to display a notification but initially, just for testing purposes I'm playing an alarm sound when Screen goes ON twice via 4 pressed in the power button. I also intend to run a Service even if the app is totally closed that's why I put the broadcast receiver inside the service.
Before when I implemented this using Service, the app seems to be working fine except for Oreo and above. I found out regarding the execution limit for background, so I updated my code by using Job Intent Service. I just noticed that my broadcast receiver is not being called though it gets registered in the JobIntentService class. I tried playing the alarm sound just on the service (broadcast receiver excluded), and the alarm goes playing, meaning that my Service is functioning properly. I was just wandering why the broadcast receiver is not getting triggered?
This is my code for this:
MainActivity :
class MainActivity : AppCompatActivity() {
private lateinit var receiver: SampleReceiver
private val actionCheck = "action_check"
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
receiver = SampleReceiver()
btnStart.setOnClickListener {
SampleJobIntentService.enqueueWork(
applicationContext,
Intent().setAction(actionCheck)
)
}
}
}
JobIntentService Class:
class SampleJobIntentService : JobIntentService() {
private lateinit var receiver: SampleReceiver
private val actionCheck = "action_check"
companion object {
fun enqueueWork(context: Context, intent: Intent) {
enqueueWork(context, SampleJobIntentService::class.java, 123, intent)
}
}
override fun onHandleWork(intent: Intent) {
Log.v("Service", "Service is running")
receiver = SampleReceiver()
when (intent.action) {
actionCheck -> {
IntentFilter(Intent.ACTION_SCREEN_ON).also { filter ->
this.registerReceiver(receiver, filter)
}
}
}
}
override fun onDestroy() {
unregisterReceiver(receiver)
super.onDestroy()
Log.v("Receiver", "Receiver is now unregistered...")
}
}
Receiver class:
class SampleReceiver : BroadcastReceiver() {
private lateinit var player: MediaPlayer
private var pressedCounts = 0
override fun onReceive(context: Context?, intent: Intent?) {
when (intent?.action) {
Intent.ACTION_SCREEN_ON -> {
pressedCounts =+ 1
if (pressedCounts == 2) {
player.start()
}
}
}
}
}
AndroidManifest.xml
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.samplereceiver">
<uses-permission android:name="android.permission.VIBRATE" />
<uses-permission android:name="android.permission.WAKE_LOCK" />
<application
android:allowBackup="true"
android:icon="#mipmap/ic_launcher"
android:label="#string/app_name"
android:roundIcon="#mipmap/ic_launcher_round"
android:supportsRtl="true"
android:theme="#style/AppTheme">
<service
android:name=".SampleJobIntentService"
android:exported="false"
android:permission="android.permission.BIND_JOB_SERVICE">
<intent-filter>
<action android:name="android.intent.action.SCREEN_OFF" />
<action android:name="android.intent.action.SCREEN_ON" />
</intent-filter>
</service>
<activity android:name=".MainActivity">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
</application>
I am trying to developing JobScheduler, and I want the App to do something every 1 minute when App has been killed by system.
AndroidManifest.xml
<service
android:name=".BaiduPush.BaiduJobService"
android:enabled="true"
android:permission="android.permission.BIND_JOB_SERVICE"/>
MainActivity
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
binding = DataBindingUtil.setContentView(this, R.layout.activity_main2)
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
startJobService()
}
}
private fun startJobService() {
Log.d(TAG,"startBaiduJobService")
val JOB = 10
val jobScheler = getSystemService((Context.JOB_SCHEDULER_SERVICE)) as JobScheduler
val jobinfo = JobInfo.Builder(JOB, ComponentName(packageName,BaiduJobService::class.java.name))
//.setPeriodic(AlarmManager.INTERVAL_FIFTEEN_MINUTES)
.setOverrideDeadline(60000)
.setPersisted(true)
.build()
jobScheler.schedule(jobinfo)
}
BaiduJobService
class BaiduJobService : JobService() {
val TAG = "BaiduJobService"
override fun onStartJob(params: JobParameters?): Boolean {
Log.d(TAG,"BaiduJobService onStartJob")
return true
}
override fun onStopJob(params: JobParameters?): Boolean {
return false
}
}
When I use the setPeriodic(AlarmManager.INTERVAL_FIFTEEN_MINUTES). The onStartJob has not been called.
When I use the setOverrideDeadline(60000). The onStartJob only show once times at the first.
But the BaiduJobService seems not called when time is up.
Did I missing something? Thanks in advance.
I am Using Alarm Manager For Keep my service alive it is better than a job scheduler. I implement this code in service oncreate() method.
public class CallService extends Service {
#Override
public void onCreate() {
super.onCreate();
Intent intent = new Intent(this, RestartServiceBroadcast.class);
mKeepAlivePendingIntent = PendingIntent.getBroadcast(this, 0, intent, PendingIntent.FLAG_UPDATE_CURRENT);
((AlarmManager) this.getSystemService(Context.ALARM_SERVICE)).setRepeating(AlarmManager.ELAPSED_REALTIME_WAKEUP, SystemClock.elapsedRealtime() + 60000, 60000, mKeepAlivePendingIntent);
}
}
Create BroadcastReceiver to call service again in onRecieve
public class RestartServiceBroadcast extends BroadcastReceiver {
#Override
public void onReceive(Context context, Intent intent) {
if (intent.getAction().equals("service.RestartService")) {
// Here Call a Service
}
}
}
Manifest Like this
<receiver
android:name=".service.receiver.RestartServiceBroadcast"
android:enabled="true"
android:exported="true"
android:process=":sipStack">
<intent-filter>
<action android:name="service.RestartService" />
</intent-filter>
</receiver>
<service
android:name=".service.CallService"
android:enabled="true"
android:exported="false"
android:stopWithTask="false">
</service>
This is my broadcast receiver class and the implementation of it in main.
Problem is that onReceive method never gets called.
class MyBroadcastReceiver : BroadcastReceiver() {
override fun onReceive(p0: Context?, p1: Intent?) {
Toast.makeText(p0, "It works", Toast.LENGTH_LONG).show()
}
}
class MainActivity : AppCompatActivity() {
......
private var broadcastReceiver: MyBroadcastReceiver = MyBroadcastReceiver()
override fun onCreate(savedInstanceState: Bundle?) {
......
registerReceiver(broadcastReceiver, IntentFilter().apply {
addAction(Intent.ACTION_PACKAGE_ADDED)
addAction(Intent.ACTION_PACKAGE_REMOVED)
})
}
override fun onDestroy() {
super.onDestroy()
unregisterReceiver(broadcastReceiver)
}
}
Please help. Thanks in advance.
I could make it work with the following code
class KotlinBroadcastReceiver(action: (context: Context, intent: Intent) -> Unit) : BroadcastReceiver() {
override fun onReceive(context: Context, intent: Intent) = action(context, intent)
}
class MainActivity : AppCompatActivity() {
private val broadcastReceiver = KotlinBroadcastReceiver { context, _ ->
Toast.makeText(context, "It works", Toast.LENGTH_LONG).show()
}
override fun onCreate(savedInstanceState: Bundle?) {
registerReceiver(broadcastReceiver, IntentFilter().apply {
addAction(Intent.ACTION_PACKAGE_ADDED)
addAction(Intent.ACTION_PACKAGE_REMOVED)
addDataScheme("package") // I could not find a constant for that :(
})
}
override fun onDestroy() {
super.onDestroy()
unregisterReceiver(broadcastReceiver)
}
}
Usually the BroadcastReceiver needs a number of steps to be set up.
First of all did yout pass to the manifest the receiver?
<receiver android:name=".MyBroadcastReceiver" android:exported="true">
<intent-filter>
<action android:name="android.intent.action.BOOT_COMPLETED"/>
<action android:name="android.intent.action.INPUT_METHOD_CHANGED" />
</intent-filter>
</receiver>
Edit: Please see this post, where is suggested ACTION_PACKAGE_FULLY_REMOVED or JobScheduler
try also to reinstall the app on the emulator
I am building an app using the NotificationListenerService. But always when I run the app in debug mode the Service is not started. I reduced my code to the following:
My Acticity:
class MainActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
val intent = Intent("android.settings.ACTION_NOTIFICATION_LISTENER_SETTINGS")
startActivity(intent)
}
override fun onResume() {
super.onResume()
val isServiceRunning = isMyServiceRunning(NLService::class.java)
Log.i("MainActivity", "service running: " + isServiceRunning)
}
private fun isMyServiceRunning(serviceClass: Class<*>): Boolean {
val manager = getSystemService(Context.ACTIVITY_SERVICE) as ActivityManager
for (service in manager.getRunningServices(Integer.MAX_VALUE)) {
if (serviceClass.name == service.service.className) {
return true
}
}
return false
}
}
The Service:
class NLService : NotificationListenerService() {
private val TAG: String? = "NLService"
override fun onBind(intent: Intent): IBinder? {
Log.i(TAG, "onBind()")
return super.onBind(intent)
}
override fun onCreate() {
super.onCreate()
Log.i(TAG, "onCreate()")
}
override fun onDestroy() {
super.onDestroy()
}
override fun onNotificationPosted(sbn: StatusBarNotification?) {
Log.i(TAG, "onNotificationPosted() sbn: $sbn")
super.onNotificationPosted(sbn)
}
}
Of course I added this in manifest:
<service
android:name=".NLService"
android:label="MyNLService"
android:permission="android.permission.BIND_NOTIFICATION_LISTENER_SERVICE">
<intent-filter>
<action android:name="android.service.notification.NotificationListenerService" />
</intent-filter>
</service>
When starting the app in debug mode then I always get the log output service running: false in onResume. The value is true when starting normally, without debug. What is going wrong and how to fix that?
Okay, finally I don't have a complete solution but a kind of improvement which is close to a working solution.
So what are actually the technical problems in my original app code? And how did I solve them?
I made some initialization in NLService class' onConnect() method. I moved all this initialization to onListenerConnected(), adding a handler.postDelayed(runnable, 500);.
I created an object of a class (Let's call it MyHandlerClass) within the NLService class and passed a reference to the Service into it. This is not a good solution because Android documentation says something about many methods within the NotificationListenerService:
The service should wait for the onListenerConnected() event before performing this operation.
So in MyHandlerClass I called a nlService.getActiveNotifications(). This call was made maybe before Android called NLServices' onListenerConnected. So I made wrappers for methods inside NLService, like e.g.:
fun getActiveNotifications(): Array<StatusBarNotification>?
{
return if (isConnected)
{
super.getActiveNotifications()
}
else
{
null
}
}
And I toggled my boolean variable isConnected within onListenerConnected()and onListenerDisconnected()
Now the service still crashes when running app in debug mode. But running in normal mode the amount of crashes could be reduced by the described improvements.