I'm working on an android application and i need alarm manager to fire events at certain times , the code works fine and the notification fires in time but only in one scenario is not working when the screen is off , the device is not waking up and wait for notification to fire up , actually this works in emulators ( i guess because there is no such power saving mode like in some physical devices ) , I've looked up most topics and could not find any solution , any help would be appreciated Thank you .
Firing Alarm Manager
fun fireAlarmManager(context: Context , time : MutableList<Long>){
val intent = Intent(context, AlarmReceiver::class.java)
for (i in 0 until time.size){
if(time[i] > deviceTimeInMillis()){
list.add(time[i])
val pendingIntent = PendingIntent.getBroadcast(context,time[i].toInt(),intent,PendingIntent.FLAG_IMMUTABLE)
if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.M){
alarmManager.setExactAndAllowWhileIdle(AlarmManager.RTC_WAKEUP,time[i],pendingIntent)
} else {
alarmManager.set(AlarmManager.RTC_WAKEUP,time[i],pendingIntent)
}
}
}
setDataFromSharedPreferences(list)
}
Broadcast receiver
class AlarmReceiver : BroadcastReceiver() {
override fun onReceive(context : Context?, intent : Intent?) {
wakeUp(context)
val serviceIntent = Intent(context,OnClearFromRecentServices::class.java)
if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.O){
context!!.startForegroundService(serviceIntent)
} else {
context!!.startService(serviceIntent)
}
}
private fun wakeUp(context: Context?) {
val pm = context!!.getSystemService(Context.POWER_SERVICE) as PowerManager
val wakeLock = pm.newWakeLock(PowerManager.SCREEN_BRIGHT_WAKE_LOCK or PowerManager.FULL_WAKE_LOCK or PowerManager.ACQUIRE_CAUSES_WAKEUP, "app::tag")
wakeLock.acquire(60000)
val keyguardManager = context.getSystemService(Context.KEYGUARD_SERVICE) as KeyguardManager
val keyguardLock = keyguardManager.newKeyguardLock("TAG")
keyguardLock.disableKeyguard()
}
}
Alarm Service
override fun onStartCommand(intent: Intent?, flags: Int, startId: Int): Int {
fireNotification(this)
return START_STICKY
}
Manifest File
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
package="com.kotlin.quranapp">
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.DISABLE_KEYGUARD" />
<uses-permission android:name="android.permission.SCHEDULE_EXACT_ALARM" />
<uses-permission android:name="com.google.android.gms.permission.AD_ID"/>
<uses-permission android:name="android.permission.REQUEST_IGNORE_BATTERY_OPTIMIZATIONS" />
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
<uses-permission android:name="android.permission.WAKE_LOCK" />
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />
<application
android:name=".koin.BaseApplication"
android:allowBackup="true"
android:dataExtractionRules="#xml/data_extraction_rules"
android:fullBackupContent="#xml/backup_rules"
android:icon="#mipmap/ic_launcher"
android:label="#string/app_name"
android:largeHeap="true"
android:roundIcon="#mipmap/ic_launcher_round"
android:supportsRtl="true"
android:theme="#style/Theme.QuranApp"
android:usesCleartextTraffic="true"
tools:targetApi="31">
<activity
android:name=".MainActivity"
android:exported="false"
android:launchMode="singleInstance"
android:screenOrientation="portrait" />
<activity
android:name=".views.SplashActivity"
android:exported="true"
android:screenOrientation="portrait">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<receiver
android:name=".alarm.AlarmReceiver"
android:enabled="true"
android:exported="true">
<intent-filter>
<action android:name="android.intent.action.BOOT_COMPLETED" />
<action android:name="android.intent.action.QUICKBOOT_POWERON" />
</intent-filter>
</receiver>
<receiver
android:name=".alarm.PlayerReceiver"
android:exported="false" />
<service android:name=".alarm.services.OnClearFromRecentServices" />
</application>
</manifest>
Related
I'm sending a push notification from Firebase console to my Android App. But sometimes, after receiving the notification and waiting for a couple of hours, and clicking the notification thereafter, it is not opening the app.
PS: In Samsung devices app is opening after a delay of 30+ seconds but in other devices like Mi or Oneplus, it is not opening at all.
Bug video:
In Samsung device
In Mi device
App manifest file
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
package="com.baja.app">
<uses-feature
android:name="android.hardware.camera"
android:required="false" />
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.RECORD_AUDIO" />
<uses-permission android:name="android.permission.FOREGROUND_SERVICE" />
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />
<application
android:requestLegacyExternalStorage="true"
android:name=".BajaApplication"
android:allowBackup="false"
android:icon="#mipmap/ic_launcher"
android:label="#string/app_name"
android:roundIcon="#mipmap/ic_launcher_round"
android:supportsRtl="false"
android:theme="#style/AppTheme.Default"
tools:ignore="GoogleAppIndexingWarning">
<activity
android:name=".ui.home.HomeActivity"
android:launchMode="singleTask"
android:screenOrientation="portrait"
android:windowSoftInputMode="adjustPan">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
<intent-filter
android:label="#string/app_name"
android:autoVerify="true"
tools:targetApi="m">
<action android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.DEFAULT" />
<category android:name="android.intent.category.BROWSABLE" />
<!-- Accepts URIs that begin with "example://gizmosā -->
<data
android:host="#string/share_host"
android:scheme="https" />
</intent-filter>
</activity>
<activity
android:name=".ui.welcome.WelcomeActivity"
android:screenOrientation="portrait" />
<activity
android:name=".ui.home.alarms.ringer.AlarmRingingActivity"
android:screenOrientation="portrait"
android:launchMode="singleInstance" />
<service
android:name=".media.MediaService"
android:enabled="true"
android:exported="false">
<intent-filter>
<action android:name="android.media.browse.MediaBrowserService" />
</intent-filter>
</service>
<service
android:name=".messaging.BajaFirebaseMessagingService"
android:exported="false">
<intent-filter>
<action android:name="com.google.firebase.MESSAGING_EVENT" />
</intent-filter>
</service>
<service
android:name=".ui.welcome.AddressIntentService"
android:exported="false" />
<service
android:name=".media.download.InternalMediaDownloadService"
android:exported="false" />
<service
android:name=".media.download.ExternalMediaDownloadService"
android:exported="false" />
<service android:name=".ui.home.alarms.ringer.AlarmMediaService" />
<receiver android:name=".media.download.DownloadCancelReceiver" />
<receiver
android:name=".ui.home.alarms.AlarmsBroadcastReceiver"
android:enabled="true"
android:exported="true">
<intent-filter>
<action android:name="android.intent.action.BOOT_COMPLETED" />
</intent-filter>
</receiver>
<service
android:name=".ui.home.alarms.RescheduleAlarmsService"
android:exported="false" />
<!--
MediaSession, prior to API 21, uses a broadcast receiver to communicate with a
media session. It does not have to be this broadcast receiver, but it must
handle the action "android.intent.action.MEDIA_BUTTON".
Additionally, this is used to resume the service from an inactive state upon
receiving a media button event (such as "play").
-->
<receiver android:name="androidx.media.session.MediaButtonReceiver">
<intent-filter>
<action android:name="android.intent.action.MEDIA_BUTTON" />
</intent-filter>
</receiver> <!-- Disable crash and analytics reporting for debug builds -->
<meta-data
android:name="firebase_crashlytics_collection_enabled"
android:value="${enableCrashReporting}" />
<meta-data
android:name="firebase_analytics_collection_deactivated"
android:value="${disableAnalyticsReporting}" /> <!-- Set custom default icon and color for request notification -->
<meta-data
android:name="com.google.firebase.messaging.default_notification_channel_id"
android:value="#string/default_notification_channel" />
<meta-data
android:name="com.google.firebase.messaging.default_notification_icon"
android:resource="#drawable/ic_favicon" />
<meta-data
android:name="com.google.firebase.messaging.default_notification_color"
android:resource="#color/black" />
<provider
android:name="androidx.core.content.FileProvider"
android:authorities="#string/app_fileprovider_authority"
android:exported="false"
android:grantUriPermissions="true">
<meta-data
android:name="android.support.FILE_PROVIDER_PATHS"
android:resource="#xml/file_paths" />
</provider>
</application>
onMessageReceived method
override fun onMessageReceived(remoteMessage: RemoteMessage) {
val notification: RemoteMessage.Notification = remoteMessage.notification ?: return
val channelId: String = notification.channelId ?: getString(R.string.default_notification_channel)
val (channelCode: Int, #StringRes channelNameRes: Int, #StringRes channelDescRes: Int) =
getNotificationChannelRelatedParams(channelId)
buildAndShowNotification(
notification.title!!,
notification.body!!,
channelId,
notification.imageUrl,
remoteMessage.data,
channelCode,
channelNameRes,
channelDescRes
)
}
Notification builder method
private fun buildAndShowNotification(
title: String,
message: String,
channelId: String,
imageUri: Uri?,
extras: Map<String, String>,
requestCode: Int,
#StringRes channelName: Int,
#StringRes channelDescRes: Int
) {
val defaultSoundUri: Uri = RingtoneManager.getDefaultUri(RingtoneManager.TYPE_NOTIFICATION)
val intent: Intent = Intent(this, HomeActivity::class.java).apply {
addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP)
extras.keys.forEach { key ->
putExtra(key, extras[key])
}
}
val pendingIntent: PendingIntent = PendingIntent.getActivity(this, requestCode, intent, PendingIntent.FLAG_UPDATE_CURRENT)
val builder: NotificationCompat.Builder = NotificationCompat.Builder(this, channelId)
.setSmallIcon(R.drawable.ic_favicon)
.setColor(Color.BLACK)
.setContentTitle(title)
.setContentText(message)
.setAutoCancel(true)
.setSound(defaultSoundUri)
.setContentIntent(pendingIntent)
.setStyle(NotificationCompat.BigTextStyle().bigText(message))
applyImageUrl(builder, imageUri)
val manager: NotificationManager = getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
val channel = NotificationChannel(
channelId,
getString(channelName),
NotificationManager.IMPORTANCE_DEFAULT
).apply { description = getString(channelDescRes) }
manager.createNotificationChannel(channel)
}
manager.notify(requestCode, builder.build())
}
Checking notification intent in HomeActivity, if notification handled by system tray
onCreate(..){
//statements
// Check if opened with notification
val intentData: Triple<String, String?, Boolean> = if (savedInstanceState == null) {
playFromIntent(intent, appLaunch = true)
} else {
Triple("", null, false)
}
//statements
}
I'm trying to show a full-screen activity on the lock screen when the app recieves a firebase cloud message.
Currently the code looks like this:
private void showFullScreenIntent(RemoteMessage remoteMessage, String ticketNumber) {
try {
int acceptCallRequestCode = 0;
String channelId = getString(R.string.channel_id);
NotificationCompat.Builder builder = new NotificationCompat.Builder(this, channelId)
.setSmallIcon(R.drawable.ic_action_name)
.setContentTitle("Incoming Video Conference Call")
.setContentText("From Demo Doctor")
.setPriority(NotificationCompat.PRIORITY_HIGH)
.setCategory(NotificationCompat.CATEGORY_CALL)
.setAutoCancel(true)
.setDefaults(Notification.DEFAULT_ALL)
.setFullScreenIntent(createAcceptCallIntent(remoteMessage, acceptCallRequestCode), true);
// notificationId is a unique int for each notification that you must define
int notificationId = GlobalState.getInstance().getNewNotificationId();
Log.d(TAG, "showFullScreenIntent NotificationId: " + notificationId);
//https://developer.android.com/training/notify-user/time-sensitive
// Provide a unique integer for the "notificationId" of each notification.
startForeground(notificationId, builder.build());
Log.d(TAG, "Finished showFullScreenIntent");
} catch (Exception e) {
Log.d(TAG, e.getMessage());
}
}
private PendingIntent createAcceptCallIntent(RemoteMessage remoteMessage, int requestCode) {
// Create an explicit intent for an Activity in your app
Intent i = new Intent(getBaseContext(), MainActivity.class);
i.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK);
i.putExtra(EXTRA_MESSAGE, remoteMessage);
//Create hashmap of extra stuff
HashMap<String, String> map = new HashMap<String, String>();
map.put(LAUNCH_METHOD, "notification");
i.putExtra(EXTRA_MAP, map);
PendingIntent pendingIntent = PendingIntent.getActivity(this, requestCode, i, PendingIntent.FLAG_CANCEL_CURRENT);
return pendingIntent;
}
The logs show that there are no errors and I can see that Finished showFullScreenIntent gets output to the log. Also the notification id is greater than zero.
My manifest looks like this:
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.augustinus.fcmtest">
<application
android:name=".MainApplication"
android:allowBackup="false"
android:icon="#mipmap/ic_launcher"
android:label="#string/app_name"
android:roundIcon="#mipmap/ic_launcher_round"
android:theme="#style/AppTheme"
android:networkSecurityConfig="#xml/network_security_config">
<!-- Add this SplashActivity -->
<activity
android:name=".SplashActivity"
android:theme="#style/SplashTheme"
android:label="#string/app_name">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<!-- Remove the intent-filter of the MainActivity and add a param android:exported="true" -->
<activity
android:name=".MainActivity"
android:configChanges="keyboard|keyboardHidden|orientation|screenSize|uiMode"
android:label="#string/app_name"
android:launchMode="singleTask"
android:windowSoftInputMode="adjustResize"
android:exported="true">
</activity>
<activity android:name="com.facebook.react.devsupport.DevSettingsActivity" />
<service
android:name=".CustomFirebaseMessagingService"
android:exported="false">
<intent-filter>
<action android:name="com.google.firebase.MESSAGING_EVENT" />
</intent-filter>
</service>
</application>
<uses-permission android:name="android.permission.USE_FULL_SCREEN_INTENT" />
<uses-permission android:name="android.permission.FOREGROUND_SERVICE" />
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.CAMERA" />
<uses-permission android:name="android.permission.MODIFY_AUDIO_SETTINGS" />
<uses-permission android:name="android.permission.RECORD_AUDIO" />
<uses-feature android:name="android.hardware.camera" android:required="true" />
<uses-feature android:name="android.hardware.camera.autofocus" android:required="false" />
<uses-feature android:name="android.hardware.microphone" android:required="true" />
<uses-permission android:name="android.permission.BLUETOOTH"/>
<uses-permission android:name="android.permission.BLUETOOTH_ADMIN"/>
<uses-permission-sdk-23 android:name="android.permission.ACCESS_FINE_LOCATION"/>
</manifest>
This is yet another question about why a BroadcastReceiver doesn't see the messages being sent to it. I've looked at a dozen examples and other questions their solutions seem the same as mine but mine doesn't work.
My receiver is in a service. Here's the manifest fragment:
<service android:name="com.madurasoftware.vmnotifications.services.BLEService"
android:label="BluetoothService"
android:process="com.madurasoftware.vmnotifications.services.VMServices">
</service>
The service registers the receiver like this:
private val messageReceiver = object : BroadcastReceiver() {
override fun onReceive(context: Context, intent: Intent) {
Log.d(TAG, "onReceive() called")
val message = intent.getStringExtra(BluetoothService.MESSAGE)
NotificationQueue.add(message)
}
}
override fun onCreate() {
super.onCreate()
Log.d(TAG, "onCreate() called")
val filter = IntentFilter()
filter.addAction(BluetoothService.MESSAGE_ACTION)
baseContext.registerReceiver(this.messageReceiver, filter )
}
override fun onDestroy() {
baseContext.unregisterReceiver(this.messageReceiver)
}
Because I am dynamically registering the receiver I don't add anything about it to the manifest.
I send from a button in my MainActivity like this:
Intent().also { intent ->
intent.setAction(BluetoothService.MESSAGE_ACTION)
intent.putExtra(BluetoothService.MESSAGE, "xyz")
sendBroadcast(intent)
}
Log.d(TAG, "sendBroadcast() called")
When I press the button I see that the logged sendBroadcast() message shows up, but the onReceive() log message does not. So it isn't being delivered.
Can anyone see why?
I'm using API 29 and this is my full manifest:
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.madurasoftware.vmnotifications">
<uses-permission android:name="android.permission.BLUETOOTH" />
<uses-permission android:name="android.permission.BLUETOOTH_ADMIN" />
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
<uses-feature
android:name="android.hardware.bluetooth_le"
android:required="true" />
<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"
android:fullBackupContent="#xml/my_backup_rules">
<activity android:name=".ui.MainActivity">
<intent-filter>
<action android:name="android.intent.action.MAIN"/>
<action android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.LAUNCHER"/>
</intent-filter>
</activity>
<service android:name="com.madurasoftware.vmnotifications.services.NotificationService"
android:label="#string/app_name"
android:permission="android.permission.BIND_NOTIFICATION_LISTENER_SERVICE">
<intent-filter>
<action android:name="android.service.notification.NotificationListenerService" />
</intent-filter>
</service>
<service android:name="com.madurasoftware.vmnotifications.services.BLEService"
android:label="BluetoothService"
android:process="com.madurasoftware.vmnotifications.services.VMServices">
</service>
<service android:name="com.madurasoftware.vmnotifications.services.BluetoothService"
android:label="BluetoothService"
android:process="com.madurasoftware.vmnotifications.services.VMServices">
</service>
</application>
</manifest>
Thanks for any help
I'm trying to start a service in my app when the phone on which the app is running, boots. I've added a broadcastreceiver, added an intent-filter in the manifest, created a service and added that to the manifest as well. But whenever I boot my phone, after a while it displays that my app has crashed.
An important thing to note is that the service works if it started from MainActivity.
I've seen more questions about this on Stackoverflow, but none of these solve my problem because most of them were of people who forgot to add the receiver to the manifest or something else.
But I don't know how to read logcat-output as well, from when a phone starts, so I can't determine what's crashing the app.
AndroidManifest.xml
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
package="nl.arnovanliere.nuntia">
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />
<uses-feature android:name="android.hardware.location.gps" />
<application
android:allowBackup="true"
android:fullBackupContent="true"
android:icon="#mipmap/ic_launcher"
android:label="#string/app_name"
android:resizeableActivity="false"
android:roundIcon="#mipmap/ic_launcher_round"
android:supportsPictureInPicture="false"
android:supportsRtl="true"
android:theme="#style/AppTheme"
tools:ignore="GoogleAppIndexingWarning">
<receiver
android:name=".receivers.BroadcastReceiver"
android:enabled="true"
android:exported="true"
android:permission="android.permission.RECEIVE_BOOT_COMPLETED">
<intent-filter>
<action android:name="android.intent.action.BOOT_COMPLETED" />
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
</receiver>
<service
android:name=".services.CheckMessagesService"
android:enabled="true"
android:exported="true"
android:permission="false" />
<activity
android:label="#string/app_name"
android:name=".MainActivity"
android:theme="#style/AppTheme">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<meta-data
android:name="com.google.android.geo.API_KEY"
android:value="AIzaSyBhlLDqLSihI41pIs-ELuomRWUv6513CeE" />
</application>
</manifest>
BroadcastReceiver.kt
class BroadcastReceiver : BroadcastReceiver() {
#SuppressLint("UnsafeProtectedBroadcastReceiver")
override fun onReceive(context: Context?, intent: Intent?) {
context?.startService(Intent(context, CheckMessagesService::class.java))
Log.d(LOG_TAG, "onReceive BroadcastReceiver called")
}
}
CheckMessagesService
class CheckMessagesService : Service() {
override fun onBind(intent: Intent): IBinder? {
return null
}
override fun onCreate() {
Log.d(LOG_TAG, "onCreate of service called")
super.onCreate()
}
override fun onStartCommand(intent: Intent?, flags: Int, startId: Int): Int {
Log.d(LOG_TAG, "onStartCommand of service called")
val runnable = Runnable {
checkMessages()
// Only need to check for messages every minute
Thread.sleep(60000)
}
// New thread for checking messages, otherwise the UI-thread would be blocked
val thread = Thread(runnable)
thread.start()
return super.onStartCommand(intent, flags, startId)
}
override fun onDestroy() {
Log.d(LOG_TAG, "onDestroy of service called")
super.onDestroy()
}
checkMessages() is just a function that calls an API and deserializes it to check if a notification has to be send.
I hope one of you can help me.
For any future viewers: The problem was that I had to use startForegroundService() instead of startService() because I was running it on Android Oreo.
Thanks #Pawel
I have a Jobservice that runs periodically every time.My activity only is to job start for running on the app.i can stop or destroy the app manually using UI and the JobService not running ,the jobservice why stop i don't know.i attached the my manifistfile and Jobdispatcher what i do something else?
dispatcher = new FirebaseJobDispatcher(new GooglePlayDriver(getActivity()));
Bundle myExtrasBundle = new Bundle();
myExtrasBundle.putString("some_key", "some_value");
if (myJob == null) {
myJob = dispatcher.newJobBuilder()
// the JobService that will be called
.setService(ReminderService.class)
// uniquely identifies the job
.setTag("my-unique-tag")
// one-off job
.setRecurring(true)
// don't persist past a device reboot
.setLifetime(Lifetime.FOREVER)
// start between 0 and 60 seconds from now
.setTrigger(Trigger.executionWindow(0, 60))
// don't overwrite an existing job with the same tag
.setReplaceCurrent(true)
// retry with exponential backoff
.setRetryStrategy(RetryStrategy.DEFAULT_LINEAR)
// constraints that need to be satisfied for the job to run
.setConstraints(
// only run on an unmetered network
Constraint.ON_ANY_NETWORK
)
.setExtras(myExtrasBundle)
.build();
dispatcher.mustSchedule(myJob);
}
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
package="com.vvsugar">
<uses-permission android:name="${applicationId}.permission.C2D_MESSAGE" />
<permission
android:name="${applicationId}.permission.C2D_MESSAGE"
android:protectionLevel="signature" />
<uses-feature android:name="android.hardware.camera" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.CAMERA" />
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
<uses-permission android:name="com.google.android.providers.gsf.permission.READ_GSERVICES" />
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
<uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW" />
<application
android:name=".AppController"
android:hardwareAccelerated="true"
android:icon="#mipmap/ic_launcher"
android:installLocation="internalOnly"
android:label="#string/app_name"
android:largeHeap="true"
android:roundIcon="#mipmap/ic_launcher_round"
android:supportsRtl="true"
android:theme="#style/AppTheme"
tools:replace="android:icon,android:theme">
<meta-data
android:name="DATABASE"
android:value="vvsugae.db" />
<meta-data
android:name="VERSION"
android:value="1.45" />
<meta-data
android:name="QUERY_LOG"
android:value="true" />
<meta-data
android:name="DOMAIN_PACKAGE_NAME"
android:value="com.vvsugar.dbview" />
<provider
android:name="android.support.v4.content.FileProvider"
android:authorities="${applicationId}.provider"
android:exported="false"
android:grantUriPermissions="true">
<meta-data
android:name="android.support.FILE_PROVIDER_PATHS"
android:resource="#xml/provider_paths" />
</provider>
<activity
android:name=".activity.LoginActivity"
android:screenOrientation="portrait">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<service
android:name="com.vvsugar.activity.ReminderService"
android:enabled="true"
android:exported="false"
android:permission="android.permission.RECEIVE_BOOT_COMPLETED">
<intent-filter>
<action android:name="com.firebase.jobdispatcher.ACTION_EXECUTE" />
<action android:name="android.intent.action.BOOT_COMPLETED" />
<action android:name="android.intent.action.QUICKBOOT_POWERON" />
<action android:name="android.intent.action.REBOOT"/>
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
</service>
<activity android:name=".activity.DashBoardActivity" />
<activity android:name=".base.BaseActivity" />
<activity
android:name=".activity.MainActivity"
android:configChanges="keyboard|keyboardHidden|screenLayout|screenSize|orientation"
android:windowSoftInputMode="stateAlwaysHidden|adjustResize" />
<activity android:name=".uicomponent.imagepicker.activities.AlbumSelectActivity" />
<activity android:name=".uicomponent.imagepicker.activities.HelperActivity" />
<activity android:name=".uicomponent.imagepicker.activities.ImageSelectActivity" />
<activity
android:name=".adapters.PaymentsAdapter"
android:label="#string/title_activity_payments_adapter"
android:theme="#style/AppTheme.NoActionBar" />
<meta-data
android:name="com.google.android.maps.v2.API_KEY"
android:value="AIzaSyBwdtoapVVM-Yg4VIKNuFaH8f3GqN7pd98" />
<!--
<meta-data android:name="com.google.android.gms.version"
android:value="#integer/google_play_services_version"/>
-->
<meta-data
android:name="io.fabric.ApiKey"
android:value="eab11ffa174990145b21fef7ed3fd2ddcf6ca4c8" />
<activity android:name=".activity.ActiveWindow"></activity>
</application>
</manifest>
On your Job service return true on onStartJob
override fun onStartJob(jobParameters: JobParameters): Boolean {
return true
}
also override onStartCommand like this
override fun onStartCommand(intent: Intent, flags: Int, startId: Int): Int {
return Service.START_STICKY
}
and for menifest write code like this
<service
android:name=".JobServiceEx"
android:permission="android.permission.BIND_JOB_SERVICE"/>
Your service will look like this for Kolin code
class JobServiceEx : JobService() {
var startTime: Long = 0
val workHandler = Handler()
var workRunnable: Runnable? = null
// Called by the Android system when it's time to run the job
override fun onStartJob(jobParameters: JobParameters): Boolean {
Log.d(TAG, "Job started!")
workRunnable = object : Runnable {
override fun run() {
val millis = System.currentTimeMillis() - startTime
var seconds = (millis / 1000).toInt()
val minutes = seconds / 60
seconds %= 60
var curTime = "$seconds"
Toast.makeText(baseContext, "Current Sec : $curTime", Toast.LENGTH_SHORT).show()
Log.e("TAG", "Current Time : $curTime")
workHandler.postDelayed(this, 1000)
}
}
workHandler.post(workRunnable)
return true
}
override fun onStartCommand(intent: Intent, flags: Int, startId: Int): Int {
return Service.START_STICKY
}
// Called if the job was cancelled before being finished
override fun onStopJob(jobParameters: JobParameters): Boolean {
workHandler.removeCallbacks(workRunnable);
return false
}
companion object {
private val TAG = JobServiceEx::class.java.simpleName
}
}
and start and stop service like this
R.id.buttonStart -> {
/**
* start job service to test
*/
var componentName = ComponentName(this, JobServiceEx::class.java)
var jobInfo: JobInfo? = null
jobInfo = JobInfo.Builder(JOB_ID, componentName)
.setRequiresCharging(true)
.setMinimumLatency(1)
.setOverrideDeadline(1)
.build()
var jobScheduler = getSystemService(JOB_SCHEDULER_SERVICE) as JobScheduler
var resultCode = jobScheduler.schedule(jobInfo);
if (resultCode == JobScheduler.RESULT_SUCCESS) {
Log.e("TAG", "Job scheduled!");
} else {
Log.e("TAG", "Job not scheduled");
}
}
R.id.buttonStop -> {
/**
* stop job service to test
*/
val jobScheduler = getSystemService(Context.JOB_SCHEDULER_SERVICE) as JobScheduler
jobScheduler.cancel(JOB_ID)
}