调用前台服务时应用程序崩溃[重复]
Posted
技术标签:
【中文标题】调用前台服务时应用程序崩溃[重复]【英文标题】:App crashing when calling foreground service [duplicate] 【发布时间】:2021-09-26 13:44:30 【问题描述】:我正在尝试调用 startForegroundService(intent),但我的应用程序在几秒钟后崩溃,但我可以在我的其他活动中调用 startForegroundService(intent),它工作正常,并且两个活动都有相同的代码。我无法弄清楚是什么导致了这个问题。我正在尝试在活动一中上传一些照片,它可以正常工作,并且在此活动中,它在几秒钟后使应用程序崩溃,我单击按钮
堆栈跟踪
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(): ServiceRecorddac122 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)
我的代码
活动
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)
服务
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
)
【问题讨论】:
使用 Logcat 检查与您的崩溃相关的堆栈跟踪。 @CommonsWare 我添加了堆栈跟踪 每个前台服务都需要一个通知并且它必须满足特定的标准(意味着它不能为空等) 启动服务的activity是否在后台? @TomTaylor 启动服务后,我完成了活动 【参考方案1】:为了避免您的应用崩溃,您必须在 onStartCommand 方法中调用 startForeground(notification) 以立即显示通知,或在服务启动后立即显示。
Check the information here
新的 Context.startForegroundService() 方法启动前台服务。即使应用在后台,系统也允许应用调用 Context.startForegroundService()。但是,应用程序必须在服务创建后五秒内调用该服务的 startForeground() 方法。
【讨论】:
以上是关于调用前台服务时应用程序崩溃[重复]的主要内容,如果未能解决你的问题,请参考以下文章
接收新的FCM消息(前台和后台)时Android应用程序崩溃