Why my job is not starting? - android

I try using JobSchedulers for my chat app (for async send message):
val job = dispatcher.newJobBuilder()
.setService(BackgroundJobService::class.java)
.setTag(BackgroundJobService.TASKTAG_SEND_MESSAGE)
.setReplaceCurrent(false)
.setConstraints(Constraint.ON_ANY_NETWORK)
.setExtras(bundle)
.setTrigger(Trigger.executionWindow(0, 1))
.build()
dispatcher.mustSchedule(job)
And add my service in manifest:
<service
android:exported="false"
android:name=".data.background.service.BackgroundJobService">
<intent-filter>
<action android:name="com.firebase.jobdispatcher.ACTION_EXECUTE"/>
</intent-filter>
</service>
I write this JobService and it not called onCreate() and not called onDestroy()
class BackgroundJobService : JobService() {
companion object {
val TASKTAG_SEND_MESSAGE = "send_message"
}
#Inject
lateinit var webSocket: IRxWebSocket
var subscribe: Disposable? = null
override fun onCreate() {
super.onCreate()
App.appComponent.inject(this)
subscribe = webSocket.connect().subscribe({}, {})
}
override fun onStartJob(job: JobParameters?): Boolean {
return true // Debug point here
}
override fun onStopJob(job: JobParameters?): Boolean {
return true
}
override fun onDestroy() {
super.onDestroy()
subscribe?.dispose()
}
}
But my onStartJob not calling! Where is my mistake?
Something i see message "Google Play services has stopped".

Your manifest declaration is wrong: you need to declare job services as requiring a specific permission that only the OS itself can use. From the JobService documentation:
Job services must be protected with this permission:
<service android:name="MyJobService"
android:permission="android.permission.BIND_JOB_SERVICE" >
If a job service is declared in the manifest but not protected with this permission, that service will be ignored by the OS.

I must put in bundle with
bundle.putString("TAG", gson.toJson(object))
but not
bundle.putParcelable("TAG", object)

Related

How to launch a service app from another app in Android?

I have a service app with no activity. I want to connect it with my main app, because I will send data from main app to service, then get response from it. Service should be launched programmatically.
If they was in same project, i could tag it in manifest like <service android:name.../> . I tried to intent but packageManager.getLaunchIntentForPackage also didn't work. Other apps with activity works with this way but service app is different.
Main App - Try to intent
val i = packageManager.getLaunchIntentForPackage("com.myexample.serviceapp")
if (i!=null) {
Log.d("MyService","Success")
startService(i)
} else {
Toast.makeText(this,"Fail",Toast.LENGTH_SHORT).show()
}
Main App - Manifest
<queries>
<package android:name="com.myexample.serviceapp"/>
</queries>
Service App
class RegistryService : Service() {
override fun onBind(p0: Intent?): IBinder? = null
override fun onStartCommand(intent: Intent?, flags: Int, startId: Int): Int {
Log.d("MyService","working")
Thread {
while (true) {
Log.d("MyService","working 2")
}
}.start()
return START_STICKY
}
}
Service Manifest
<service android:name=".RegistryService" />
It solve the problem.
val i = Intent().apply {
this.setClassName("com.myexample.serviceapp", "com.myexample.serviceapp.RegistryService")
}
startForegroundService(i)

Android background service not starting

I have read multiple threads on this issue but none of them solved my problem, so I gave up and decided to write this.
I have a service (right now it's a background service but I am going to turn it into a foreground service) which monitors the battery level so it can notify the user when it reaches a certain percentage.
abstract class MonitoringService : Service() {
private var maxPercentage: Int = -1
private var thread: Thread? = null
private lateinit var batteryManager: BatteryManager
override fun onBind(intent: Intent?): IBinder? {
return null
}
override fun onCreate() {
batteryManager = getSystemService(BATTERY_SERVICE) as BatteryManager
Log.d(null, "created service")
}
override fun onDestroy() {
thread?.interrupt()
updateServiceState(false)
Log.d(null, "destroyed service")
}
override fun onStartCommand(intent: Intent?, flags: Int, startId: Int): Int {
println("started service")
if (intent == null) {
stopSelf(startId)
updateServiceState(false)
report(applicationContext, "service started with intent null")
return START_NOT_STICKY
}
when (intent.action) {
ACTION_START_SERVICE -> {
// if a thread is already active interrupt it
thread?.interrupt()
if (updateMaxPercentage(intent, startId) == 1) return START_NOT_STICKY
thread = Thread(Runnable {
while (true) {
if (batteryManager.isCharging && batteryManager.getIntProperty(
BatteryManager.BATTERY_PROPERTY_CAPACITY
) == maxPercentage
) {
Log.d(null, "time to do it")
}
Log.d(null, "time to not do it")
try {
// sleep for 1 minute
Thread.sleep(60000)
} catch (exception: InterruptedException) {
stopSelf(startId)
updateServiceState(false)
return#Runnable
}
}
})
thread?.start()
updateServiceState(true)
}
ACTION_STOP_SERVICE -> {
thread?.interrupt()
stopSelf(startId)
updateServiceState(false)
return START_NOT_STICKY
}
ACTION_UPDATE_SERVICE -> if (updateMaxPercentage(intent, startId) == 1) return START_NOT_STICKY
else -> {
stopSelf(startId)
updateServiceState(false)
report(applicationContext, "service started with action null")
return START_NOT_STICKY
}
}
return START_REDELIVER_INTENT
}
}
I start the service like so from my activity
private fun start() {
val serviceIntent = Intent(applicationContext, MonitoringService::class.java)
serviceIntent.action = ACTION_START_SERVICE
serviceIntent.putExtra("maxPercentage", maxPercentage)
println(startService(intent))
Log.d(null, "startService")
}
This is my 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="com.segv.batconv">
<application
android:icon="#mipmap/ic_launcher"
android:label="#string/app_name"
android:roundIcon="#mipmap/ic_launcher_round"
android:theme="#style/Theme.Batconv"
tools:targetApi="31">
<service
android:name=".MonitoringService"
android:enabled="true"/>
<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>
I am testing this on an Android 11 device. The logs show no errors but the service doesn't start.
Thanks.
Remove the abstract keyword from your MonitoringService declaration:
class MonitoringService : Service()
By declaring it abstract, you are saying that nothing can create an instance of that class.

Intent Service running properly on android 9 when app is in background

I have an Intent service & a BroadcastReceiver.
As per background limitation on Android Oreo & above, the background applications(when an application is not foreground ) cannot use the started service. When you call startService() method from the background applications simply through the IllegalStateException.
But In my case, My intent service is running properly even when the app is in the background.
I am using ADB cmd to trigger broadcast.
Please correct where I am missing.
adb shell am broadcast -a android.intent.action.TEST --es maxCountValue 10 -n com.example.servicedemo/.MyReceiver
enter code here
BroadcastReceiver class
class MyReceiver : BroadcastReceiver() {
override fun onReceive(context: Context?, intent: Intent?) {
Toast.makeText(context, "CompleteReceiver", Toast.LENGTH_LONG).show()
if (intent!!.action.equals("android.intent.action.TEST")) {
val mIntent = Intent(context, MyIntentService::class.java).apply {
Log.v("MyIntentService", intent.data.toString())
this.putExtra("maxCountValue", 100)
}
context?.startService(mIntent)
}
}
}
Intent Service
private const val SERVICE_NAME = "MyIntentService"
class MyIntentService : IntentService(SERVICE_NAME) {
private val handler = Handler()
override fun onCreate() {
super.onCreate()
showToast("Job Execution Started")
}
override fun onStartCommand(intent: Intent?, flags: Int, startId: Int): Int {
showToast("Job Execution onStartCommand")
return super.onStartCommand(intent, flags, startId)
}
override fun onDestroy() {
super.onDestroy()
showToast("Job Execution onDestroy")
}
override fun onHandleIntent(intent: Intent?) {
val maxCount = intent!!.getIntExtra("maxCountValue", -1)
for (i in 0 until maxCount) {
Log.d(SERVICE_NAME, "onHandleWork: The number is: $i")
try {
Thread.sleep(100)
} catch (e: InterruptedException) {
Log.d(SERVICE_NAME, "Exception: ")
e.printStackTrace()
}
}
}
private fun showToast(msg: String) {
handler.post {
Toast.makeText(this#MyIntentService, msg, Toast.LENGTH_LONG).show()
}
}
}
Manifest :
<service android:name=".MyIntentService"/>
<receiver android:name=".MyReceiver">
<intent-filter>
<action android:name="android.intent.action.TEST" />
</intent-filter>
</receiver>
"The definition of background for purposes of service limitations is distinct from the definition used by memory management; an app might be in the background as pertains to memory management, but in the foreground as pertains to its ability to launch services."
-
https://developer.android.com/about/versions/oreo/background
PS that's the whole purpose of services

Why the JobService did not repeat?

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>

Notification Listener Service not started when running in debug mode

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.

Categories

Resources