I am trying to call startForegroundService(intent) but my app crashes after few seconds but I am able to call startForegroundService(intent) in my other activity it works fine and both the activities have the same code. I am not able to figure out what is causing this problem. I am trying to upload some photos in activity one it's working without any issues and in this activity it's crashing the app after few seconds I click on the button
Stack Trace
2021-07-18 22:48:16.233 8352-8352/com.android.testproject1 E/AndroidRuntime: FATAL EXCEPTION: main
Process: com.android.testproject1, PID: 8352
android.app.RemoteServiceException: Context.startForegroundService() did not then call Service.startForeground(): ServiceRecord{dac122 u0 com.android.testproject1/.services.UploadServiceOffers}
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:2005)
at android.os.Handler.dispatchMessage(Handler.java:106)
at android.os.Looper.loop(Looper.java:223)
at android.app.ActivityThread.main(ActivityThread.java:7656)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:592)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:947)
My Code
Activity
override fun onOptionsItemSelected(item: MenuItem): Boolean {
if (item.itemId==R.id.Post){
if (descriptionTextTitle.text.isEmpty()) {
// AnimationUtil.shakeView(mEditText, activity)
} else {
sharedPreferences.edit().putInt("count", ++serviceCount).apply()
Log.d(myTag, "On click sp $serviceCount")
val intent = Intent(this, UploadServiceOffers::class.java)
intent.putExtra("count", serviceCount)
intent.putExtra("notification_id", System.currentTimeMillis().toInt())
intent.action = UploadServiceOffers.ACTION_START_FOREGROUND_SERVICE_UPLOAD_OFFERS
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
startForegroundService(intent)
Log.d(myTag, "Build Version OP")
// startForegroundService(activity!!,intent)
} else {
Log.d(myTag, "Build Version NP")
// activity!!.startService(intent)
startService(intent)
}
Toasty.info(this, "Uploading images..", Toasty.LENGTH_SHORT, true).show()
finish()
}
}
return super.onOptionsItemSelected(item)
}
Service
class UploadServiceOffers : Service() {
companion object{
val ACTION_START_FOREGROUND_SERVICE_UPLOAD_OFFERS = "ACTION_START_FOREGROUND_SERVICE"
}
private var count = 0
private var bitmap: Bitmap? = null
private var resized: Bitmap? = null
val myTag:String = "MyTag"
override fun onCreate() {
Log.d(myTag, "Service Created ")
super.onCreate()
}
override fun onStartCommand(intent: Intent?, flags: Int, startId: Int): Int {
Log.d(myTag, "onStart $intent $flags $startId")
if (intent!=null) {
val action = intent.action
if (action == ACTION_START_FOREGROUND_SERVICE_UPLOAD_OFFERS) {
val imagesList: ArrayList<Image>? = intent.getParcelableArrayListExtra<Image>("imagesList")
val notificationId = intent.getIntExtra("notification_id", 3)
val postID = intent.getStringExtra("offerID")
val title=intent.getStringExtra("title")
val originalPrice=intent.getStringExtra("originalPrice")
val discountedPrice=intent.getStringExtra("discountedPrice")
val city=intent.getStringExtra("city")
val currentId = intent.getStringExtra("current_id")
val description = intent.getStringExtra("description")
val uploadedImagesUrl = intent.getStringArrayListExtra("uploadedImagesUrl")
count = intent.getIntExtra("count", 0)
if (imagesList != null) {
if (postID != null) {
if (title != null) {
if (city != null) {
if (originalPrice != null) {
if (discountedPrice != null) {
uploadImages(notificationId, 0, imagesList, currentId, description,
uploadedImagesUrl, postID,title,originalPrice,discountedPrice,city)
}
}
}
}
}
}
}
}
return super.onStartCommand(intent, flags, startId)
}
override fun onDestroy() {
super.onDestroy()
}
override fun onBind(intent: Intent?): IBinder? {
return null
}
private fun stopForegroundService(removeNotification: Boolean) {
Log.d(myTag,"Stop foreground service.")
// Stop foreground service and remove the notification.
stopForeground(removeNotification)
// Stop the foreground service.
stopSelf()
}
private fun notifyProgress(
id: Int,
icon: Int,
title: String,
message: String,
context: Context,
max_progress: Int,
progress: Int,
indeterminate: Boolean
) {
val builder = NotificationCompat.Builder(context, App.CHANNEL_ID2)
// Create notification default intent.
val intent = Intent()
val pendingIntent = PendingIntent.getActivity(this, 0, intent, 0)
builder.setSmallIcon(icon)
.setContentTitle(title)
.setContentText(message)
.setOngoing(true)
.setContentIntent(pendingIntent)
.setAutoCancel(true)
.setTicker(message)
.setChannelId(App.CHANNEL_ID2)
.setPriority(NotificationCompat.PRIORITY_LOW)
.setProgress(max_progress, progress, indeterminate)
.setVibrate(LongArray(0))
startForeground(id, builder.build())
}
fun getImageUri(inContext: Context, inImage: Bitmap) {
val bytes = ByteArrayOutputStream()
inImage.compress(Bitmap.CompressFormat.JPEG, 100, bytes)
var path: String?=null
try {
path = MediaStore.Images.Media.insertImage(inContext.contentResolver, inImage, "Title", null)
}catch (e: java.lang.Exception){
e.localizedMessage?.toString()?.let { Log.d(myTag, it) }
}
if (path!=null){
Log.d(myTag, Uri.parse(path).toString())
}
else{
Log.d(myTag, "Path is null ")
}
}
private fun uploadImages(
notification_id: Int,
index: Int,
imagesList: ArrayList<Image>,
currentUser_id: String?,
description: String?,
uploadedImagesUrl: ArrayList<String>?,
postID:String,
title: String,
originalPrice:String,
discountPrice:String,
city:String
) {
val imgCount = index + 1
var imageUri: Uri
val imageUri0: Uri?= Uri.fromFile(File(imagesList[index].path))
if (Build.VERSION.SDK_INT >= 29) {
try {
bitmap = imageUri0?.let { ImageDecoder.createSource(this.contentResolver,it)}?.let { ImageDecoder.decodeBitmap(it) }
} catch (e: IOException) {
e.printStackTrace()
e.localizedMessage?.toString()?.let { Log.d(myTag, " errore is $it") }
}
} else {
// Use older version
try {
bitmap = MediaStore.Images.Media.getBitmap(this.contentResolver, imageUri0)
} catch (e: IOException) {
e.printStackTrace()
e.localizedMessage?.toString()?.let { Log.d(myTag, " errore is $it") }
}
}
// val bitmap = BitmapFactory.decodeFile(file.getAbsolutePath())
resized = bitmap?.let { Bitmap.createScaledBitmap(it, 600, 600, true) }
// Log.d(myTag, "path is ${bitmap.toString()}")
var path :String?=null
try {
// path = MediaStore.Images.Media.insertImage(this.contentResolver, resized, "Title", null)
path = MediaStore.Images.Media.insertImage(this.contentResolver, resized, "IMG_"
+ System.currentTimeMillis(), null)
Log.d(myTag, "path is $path")
}catch (e :java.lang.Exception){
Log.d(myTag, "path is exception $path" )
Log.d(myTag, e.localizedMessage.toString() )
}
imageUri = Uri.parse(path)
// imageUri = try {
//
// val compressedFile: File = id.zelory.compressor.Compressor()
// .setQuality(80)
// .setCompressFormat(Bitmap.CompressFormat.JPEG)
// .compressToFile(File(imagesList[index].path))
// Uri.fromFile(compressedFile)
// } catch (e: Exception) {
// e.printStackTrace()
// Uri.fromFile(File(imagesList!![index].path))
// }
val fileToUpload =
currentUser_id?.let {
FirebaseStorage.getInstance().reference.child("Offers").child(it)
.child(postID)
.child("Voila_"+ System.currentTimeMillis() + "_" + imagesList[index].name)
}
fileToUpload?.putFile(imageUri)?.addOnSuccessListener {
Log.d(myTag, "Uploaded Successfully")
fileToUpload.downloadUrl
.addOnSuccessListener { uri: Uri ->
uploadedImagesUrl!!.add(uri.toString())
val nextIndex = index + 1
try {
if (!TextUtils.isEmpty(imagesList[index + 1].path)) {
uploadImages(
notification_id,
nextIndex,
imagesList,
currentUser_id,
description,
uploadedImagesUrl,
postID,
title,originalPrice, discountPrice,city)
} else {
uploadPost(
notification_id,
currentUser_id,
description,
uploadedImagesUrl,
postID,
title,originalPrice,discountPrice,city)
}
} catch (e: Exception) {
e.printStackTrace()
uploadPost(
notification_id,
currentUser_id,
description,
uploadedImagesUrl, postID,
title, originalPrice, discountPrice,city)
}
}
.addOnFailureListener { obj: Exception -> obj.printStackTrace() }
}?.addOnFailureListener { obj: Exception ->
obj.printStackTrace()
obj.localizedMessage?.toString()?.let { Log.d(myTag, "Exception is $it") }
}?.addOnProgressListener { taskSnapshot: UploadTask.TaskSnapshot ->
if (count == 1) {
val title = "Uploading " + imgCount + "/" + imagesList.size + " images..."
val progress = (100.0 * taskSnapshot.bytesTransferred / taskSnapshot.totalByteCount).toInt()
notifyProgress(notification_id, R.drawable.stat_sys_upload, title, "$progress%",
applicationContext, 100, progress, true)
} else if (count > 1) {
notifyProgress(
notification_id,
R.drawable.stat_sys_upload,
"Viola",
"Uploading $count posts",
applicationContext,
100,
0,
true
)
}
}
}
}
In order to avoid crashing your app, you must call startForeground(notification) inside your onStartCommand method, to show notification immediately, or as soon as the service is started.
The new Context.startForegroundService() method starts a foreground service. The system allows apps to call Context.startForegroundService() even while the app is in the background. However, the app must call that service's startForeground() method within five seconds after the service is created.