调用前台服务时应用程序崩溃

时间:2021-07-18 16:53:12

标签: android kotlin android-service

我正在尝试调用 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(): 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)

我的代码

<块引用>

活动

    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
                )
            }
        }
    }
}

1 个答案:

答案 0 :(得分:0)

为了避免您的应用程序崩溃,您必须在 onStartCommand 方法中调用 startForeground(notification),以立即或在服务启动后立即显示通知。

Check the information here

<块引用>

新的 Context.startForegroundService() 方法启动前台服务。即使应用程序在后台,系统也允许应用程序调用 Context.startForegroundService()。但是,应用必须在服务创建后的五秒内调用该服务的 startForeground() 方法。