I have tried every possible answer on SO but nothing has helped.
I want to reset alarms using AlarmManager on device reboot and the code to do exactly that works, but it doesn't when I put it inside the receiver.
I had tried creating a service but that didn't seem to work at all which that was probably incompetence of my part, however I just can't see why this code isn't working.
AndroidManifest:
<manifest
(...)
<uses-permission android:name = "android.permission.RECEIVE_BOOT_COMPLETED" />
(...)
<application
(...)
<receiver
android:name = ".utils.DeviceRebootReceiver">
<intent-filter>
<action android:name = "android.intent.action.BOOT_COMPLETED" />
</intent-filter>
<intent-filter>
<action android:name="android.intent.action.QUICKBOOT_POWERON" />
</intent-filter>
</receiver>
DeviceRebootReceiver:
class DeviceRebootReceiver : BroadcastReceiver() {
override fun onReceive(context : Context?, intent : Intent?) {
resetAlarms(context)
}
}
fun resetAlarms(context:Context):
fun resetAlarms(context : Context?) {
suspend fun resetAlarmsCoroutine(context : Context) {
val reminders = NotesDatabase.getInstance(context).notesDatabaseDAO.getAllActiveReminders()
reminders.forEach {
if (it.reminderTime > System.currentTimeMillis()) {
createAlarm(it.reminderTime, it.reminderMessage,null,context)
}
}
}
CoroutineScope(Dispatchers.IO).launch {
if (context != null) {
resetAlarmsCoroutine(context)
}
}
}
No need to show the createAlarm() function cause it works fine, BUT since I had seen that AlarmManager could cause problems on reboot I do instantiate it there like so:
val alarmManager = context.getSystemService(Context.ALARM_SERVICE) as AlarmManager
Related
AppWidget.kt:
override fun onEnabled(context: Context) {
// register price and widget button update receivers
val filters = IntentFilter()
filters.addAction(BROADCAST_PRICE_UPDATED)
filters.addAction(BROADCAST_WIDGET_UPDATE_BUTTON_CLICK)
LocalBroadcastManager.getInstance(context.applicationContext).registerReceiver(br, filters)
}
override fun onDisabled(context: Context) {
// unregister price and widget button update receivers
LocalBroadcastManager.getInstance(context.applicationContext).unregisterReceiver(br)
}
private val br = object : BroadcastReceiver() {
override fun onReceive(context: Context?, intent: Intent?) { ... }
Notes: local broadcast receiver receives all other registered broadcasts, except from piWidgetUpdateButtonClicked. Using LocalBroadcastManager is the only way I've been able to send/receive broadcasts, as apparently using global broadcast system filters out broadcasts from my app's package?
internal fun updateAppWidget(context: Context, appWidgetManager: AppWidgetManager, appWidgetId: Int) {
// Construct the RemoteViews object
val views = RemoteViews(context.packageName, R.layout.app_widget)
// Create an Intent to launch MainActivity when widget background touched
val piLaunchMainActiv: PendingIntent = PendingIntent.getActivity(context,0,
Intent(context.applicationContext, MainActivity::class.java),
PendingIntent.FLAG_UPDATE_CURRENT or PendingIntent.FLAG_IMMUTABLE
)
views.setOnClickPendingIntent(R.id.widget_background_layout, piLaunchMainActiv)
// create intent to update widget when button clicked TODO this not working
val piWidgetUpdateButtonClicked =
PendingIntent.getBroadcast(context, appWidgetId,
Intent(BROADCAST_WIDGET_UPDATE_BUTTON_CLICK), PendingIntent.FLAG_UPDATE_CURRENT
or PendingIntent.FLAG_IMMUTABLE
)
views.setOnClickPendingIntent(R.id.widget_update_button, piWidgetUpdateButtonClicked)
Notes: *piLauchMainActiv *pending intent works fine, but piWidgetUpdateButtonClicked does nothing. I've tried using context.applicationContext, also does nothing. Also I've tried explicitly setting receiving class: Intent.setClass(context, AppWidget::class.java), nothing.
Apparently, latest Google Android releases want you to register broadcast receivers programmatically, as I've done above, rather than in the manifest, which I've tried too, but also doesn't work:
AndroidManifest.xml:
<receiver
android:name=".AppWidget"
android:exported="false">
<intent-filter>
<action android:name="android.appwidget.action.APPWIDGET_UPDATE" />
</intent-filter>
<intent-filter>
<action android:name="org.bitanon.bitcointicker.BROADCAST_PRICE_UPDATED" />
</intent-filter>
<intent-filter>
<action android:name="org.bitanon.bitcointicker.BROADCAST_WIDGET_UPDATE_BUTTON_CLICK" />
</intent-filter>
<meta-data
android:name="android.appwidget.provider"
android:resource="#xml/app_widget_info" />
</receiver>
After days and days of reading through other related posts on stackoverflow, nothing has helped. I'm completely stumped, please send help!
New to Android & Kotlin, and I need help with Intents and Intent Filters.
I'm using a Zebra MC2700 with Android Studio 2021 & Kotlin.
My Main Activity sets up the DataWedge profile and then starts another activity. The second activity should have an intent filter, so that I can make use of onNewIntent. The process is nicely demonstrated in this tutorial https://github.com/darryncampbell/DataWedge-GettingStarted-Samples I was able to duplicate & modify that app. But I cannot get my OnIntent routine to be called in anything other than the main activity.
I have also read the topic "Using DataWedge for Multiple Activities on Zebra Barcode Scanner doesn't work in Kotlin" But I'm still missing something. Surely it has to do with the Android manifest and the Intent Filter / Listener setup.
The DWUtilities.kt file is the same as the example except for the filter action:
intentProps.putString(
"intent_action",
"com.example.simplescan.ACTION")
My Main Activity has a button that launches the second activity.
val intent = Intent(this, SubActivityConsume::class.java)
startActivity(intent)
This is the second activity where the scan should be handled:
class SubActivityConsume : AppCompatActivity(), View.OnTouchListener{
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_sub_consume)
val btnScan = findViewById<Button>(R.id.btnScan)
btnScan.setOnTouchListener(this)
}
// Zebra DataWedge Stuff
override fun onNewIntent(intent: Intent) {
super.onNewIntent(intent)
displayScanResult(intent)
}
and here is my latest Android Manifest
(Edited to have the whole .xml file in case there are other issues I'm missing)
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.simplescan">
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>
<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/Theme.SimpleScan">
<activity
android:name=".ViewLists"
android:exported="false"
android:label="View Lists" />
<activity
android:name=".SubActivityConsume"
android:exported="false"
android:label="Scan Consumed Material"
android:launchMode="singleTop">
<intent-filter>
<action android:name="com.example.simplescan.ACTION" />
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
</activity>
<activity
android:name=".SubActivityReceive"
android:exported="false"
android:label="Scan Received Material" />
<activity
android:name=".MainActivity"
android:exported="true">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
</application>
</manifest>
Both the soft trigger and the device trigger fire the scanner, and it reads the barcode, and a beep is heard. But, onNewIntent() is never called.
I also had problems with this; the way I got it working was to set the profile to Broadcast Intent, and set a BroadcastReceiver in the activity that needs it.
In DWUtilities.kt, change
intentProps.putString("intent_delivery", "0") // StartActivity
to
intentProps.putString("intent_delivery", "2") // Broadcast Intent
Then in SubActivityConsume.kt set up your broadcast receiver...
class SubActivityConsume : AppCompatActivity(), View.OnTouchListener{
lateinit var broadcastReceiver: BroadcastRecevier
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_sub_consume)
val btnScan = findViewById<Button>(R.id.btnScan)
btnScan.setOnTouchListener(this)
broadcastReceiver = object : BroadcastReceiver() {
override fun onReceive(context: Context, scanIntent: Intent?) {
Log.v("SCAN","broadcast received: ${scanIntent?.action}")
when (scanIntent?.action) {
"com.example.simplescan.ACTION" -> {
displayScanResult(scanIntent)
}
}
}
}
DWUtilities.CreateDWProfile(this)
}
override fun onResume() {
super.onResume()
this.registerReceiver(broadcastReceiver,
IntentFilter("com.example.simplescan.ACTION"))
Log.v("SCAN","Broadcast receiver registered")
}
override fun onPause() {
super.onPause()
this.unregisterReceiver(broadcastReceiver)
Log.v("SCAN","Broadcast receiver unregistered")
}
I have the following Broadcast Receiver
class ShutdownReceiver(): BroadcastReceiver() {
override fun onReceive(context: Context?, intent: Intent?) {
if (Intent.ACTION_SHUTDOWN == intent?.action) {
HiddenFileUtility.appendLogs("ACTION_SHUTDOWN: true")
ApplicationGlobalContext.setShutDownState(true)
}
}
}
I register the ShutdownReceiver through the AndroidManifext.xml like this:
<receiver android:name=".BroadcastReceivers.ShutdownReceiver">
<intent-filter android:priority="1">
<action android:name="android.intent.action.BOOT_COMPLETED" android:priority="999"/>
</intent-filter>
</receiver>
And i never receive the ACTION_SHUTDOWN intent.
In the Android official documentation states that As of Build.VERSION_CODES#P this broadcast is only sent to receivers registered through Context.registerReceiver link here
The solution is to delete the ShutdownReceiver from the AndroidManifest.xml and register it using Context.registerReceiver like this:
val shutdownReceiver = ShutdownReceiver();
val bootIntentFilter = IntentFilter(Intent.ACTION_SHUTDOWN);
context.registerReceiver(shutdownReceiver, bootIntentFilter);
I want to do some work when user unlock their phone
I define a receiver in AndroidManifest.xml
<receiver
android:enabled="true"
android:name=".service.ScreenReceiver">
<intent-filter>
<action android:name="android.intent.action.USER_PRESENT" />
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
</receiver>
and Receiver
class ScreenReceiver : BroadcastReceiver() {
override fun onReceive(context: Context, intent: Intent) {
}
private fun checkClearSavedNote(context: Context) {
AppPref.getInstance(context).putString(AppPref.KEY_ID_CURRENT_NOTE, "")
Log.e("Quang", "clear note")
}
}
But it was not called when fired
I've tried using Service and registerBroadcastReceiver inside
and start it when application start
class MyApplication : MultiDexApplication() {
override fun onCreate() {
super.onCreate()
instance = this
MultiDex.install(applicationContext)
try {
startService(Intent(this, NoteService::class.java))
} catch (e: IllegalStateException) {
e.printStackTrace()
}
}
}
but it work only with Android API < 8.0 because background execution limit
You can set your targetSdk < 26 to leverage implicit broadcasts. Otherwise you have to change your design according to latest list of exempted broadcasts.
I am trying to put together just a basic IntentService/BroadcastReceiver combo.
Yes, I know that what is currently there isn't really useful, but I just wanted to get the broadcast running.
The Service receives my initial intent, but the Receiver doesn't get the return Broadcast (debugger). Other answers didn't help me, and I feel like I've tried everything. It has to be something trivial, but I just can't put my finger on it.
Displaying Activity:
class MainActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
val filter = IntentFilter()
filter.addAction(Constants.BROADCAST_ACTION)
filter.addDataScheme("http")
val dsl = DownloadStateReceiver()
LocalBroadcastManager.getInstance(this).registerReceiver(dsl,filter)
buttonLogin.setOnClickListener({
var loginIntent = Intent(this,RawRestJsonPull::class.java)
loginIntent.putExtra("userName",editLogin.text.toString())
loginIntent.putExtra("password",editPassword.text.toString())
this.startService(loginIntent)
})
}
class DownloadStateReceiver : BroadcastReceiver()
{
override fun onReceive(currentContext: Context, incomingIntent: Intent) {
Log.d("?????","d")
}
}
}
Service and the action constants:
class RawRestJsonPull : IntentService("rest" ) {
override fun onHandleIntent(incomingIntent: Intent) {
var outgoingIntent = Intent(Constants.BROADCAST_ACTION)
var status = 0
var userName : String? = incomingIntent.getStringExtra("userName")
var password : String? = incomingIntent.getStringExtra("password")
outgoingIntent.putExtra(Constants.EXTENDED_DATA_STATUS,status).putExtra("userName",userName).
putExtra("password",password)
outgoingIntent.flags = Intent.FLAG_INCLUDE_STOPPED_PACKAGES
LocalBroadcastManager.getInstance(this).sendBroadcast(outgoingIntent)
}
}
class Constants
{
companion object {
val BROADCAST_ACTION = "com.example.hubert1224.xxx.BROADCAST"
val EXTENDED_DATA_STATUS = "com.example.hubert1224.xxx.STATUS"
}
}
Manifest:
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.hubert1224.xxx">
<uses-permission android:name="android.permission.INTERNET" />
<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">
<activity
android:name=".MainActivity"
android:windowSoftInputMode="stateVisible">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<service android:name=".RawRestJsonPull" />
<receiver android:name=".MainActivity$DownloadStateReceiver" />
</application>
</manifest>
Try that
First make your BroadcastReceiver static or it's own class, I am not sure Android can work with non static inner classes.
Second, I am not sure why your receiver intent filter has a
filter.addDataScheme("http")
But you are missing that from the Intent you are firing from your service, if you don't need it, remove it.
Try removing the data scheme http from the filter. 2. Try adding the category default to the filter.