Приложение вылетает после того, как разрешение на хранение предоставляется только при первом запуске - PullRequest
0 голосов
/ 27 августа 2018

Когда мой app запускается впервые, и я перехожу на вкладку, где он запрашивает storage permission, он вылетает.После этого все работает просто отлично.По сути, он должен создать папку на external storage с файлом, который у меня есть в assets folder в моем проекте после предоставления storage permission.После первого сбоя и повторного открытия он не падает и правильно размещает каталог и файл.Если папка уже находится на external storage, она не падает при первом запуске.Кроме того, позже я понял, что могу полностью избавиться от сбоя, настроив таргетинг на SDK version 21, но если я это сделаю, я не смогу обновить приложение на Play Store, поскольку я уже представил его с надеждой исправить это сбой позже.Вот logcat во время аварии:

    --------- beginning of crash
08-27 01:16:58.548 17674-17674/com.thirdeclarity.rcmloader E/AndroidRuntime: FATAL EXCEPTION: main
Process: com.thirdeclarity.rcmloader, PID: 17674
java.lang.RuntimeException: Failure delivering result ResultInfo{who=@android:requestPermissions:, request=65661, result=-1, data=Intent { act=android.content.pm.action.REQUEST_PERMISSIONS (has extras) }} to activity {com.thirdeclarity.rcmloader/com.pavelrekun.rekado.screens.main_activity.MainActivity}: java.io.FileNotFoundException: /storage/emulated/0/RCM Loader/hekate-4.0.bin (No such file or directory)
    at android.app.ActivityThread.deliverResults(ActivityThread.java:4269)
    at android.app.ActivityThread.handleSendResult(ActivityThread.java:4313)
    at android.app.ActivityThread.-wrap19(Unknown Source:0)
    at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1645)
    at android.os.Handler.dispatchMessage(Handler.java:106)
    at android.os.Looper.loop(Looper.java:164)
    at android.app.ActivityThread.main(ActivityThread.java:6499)
    at java.lang.reflect.Method.invoke(Native Method)
    at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:440)
    at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:807)
 Caused by: java.io.FileNotFoundException: /storage/emulated/0/RCM Loader/hekate-4.0.bin (No such file or directory)
    at java.io.FileOutputStream.open0(Native Method)
    at java.io.FileOutputStream.open(FileOutputStream.java:287)
    at java.io.FileOutputStream.<init>(FileOutputStream.java:223)
    at java.io.FileOutputStream.<init>(FileOutputStream.java:110)
    at com.pavelrekun.rekado.services.utils.MemoryUtils.copyAsset(MemoryUtils.kt:15)
    at com.pavelrekun.rekado.screens.payload_fragment.PayloadsView.initList(PayloadsView.kt:47)
    at com.pavelrekun.rekado.screens.payload_fragment.PayloadsView.onRequestPermissionsResult(PayloadsView.kt:81)
    at com.pavelrekun.rekado.screens.payload_fragment.PayloadsFragment.onRequestPermissionsResult(PayloadsFragment.kt:33)
    at android.support.v4.app.FragmentActivity.onRequestPermissionsResult(FragmentActivity.java:804)
    at android.app.Activity.dispatchRequestPermissionsResult(Activity.java:7429)
    at android.app.Activity.dispatchActivityResult(Activity.java:7280)
    at android.app.ActivityThread.deliverResults(ActivityThread.java:4265)
    at android.app.ActivityThread.handleSendResult(ActivityThread.java:4313) 
    at android.app.ActivityThread.-wrap19(Unknown Source:0) 
    at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1645) 
    at android.os.Handler.dispatchMessage(Handler.java:106) 
    at android.os.Looper.loop(Looper.java:164) 
    at android.app.ActivityThread.main(ActivityThread.java:6499) 
    at java.lang.reflect.Method.invoke(Native Method) 
    at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:440) 
   at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:807) 
  08-27 01:16:58.689 17674-17689/com.thirdeclarity.rcmloader I/zygote: Background concurrent copying GC freed 22378(1560KB) AllocSpace objects, 2(104KB) LOS objects, 50% free, 2MB/4MB, paused 2.770ms total 145.331ms

Я новичок в разработке для Android, и код, с которым я работаю, взят из проекта с открытым исходным кодом, но я считаю, что это соответствующий код для вкладки, которая дает сбой:

package com.pavelrekun.rekado.screens.payload_fragment

import android.Manifest
import android.content.pm.PackageManager
import android.support.v4.app.Fragment
import android.support.v7.widget.LinearLayoutManager
import android.widget.Toast
import com.pavelrekun.konae.Konae
import com.pavelrekun.konae.filters.ExtensionFileFilter
import com.pavelrekun.rang.utils.ColorsHelper
import com.pavelrekun.rekado.R
import com.pavelrekun.rekado.base.BaseActivity
import com.pavelrekun.rekado.data.Payload
import com.pavelrekun.rekado.screens.payload_fragment.adapters.PayloadsAdapter
import com.pavelrekun.rekado.services.eventbus.Events
import com.pavelrekun.rekado.services.logs.LogHelper
import com.pavelrekun.rekado.services.payloads.PayloadHelper
import com.pavelrekun.rekado.services.utils.MemoryUtils
import com.pavelrekun.rekado.services.utils.PermissionsUtils
import kotlinx.android.synthetic.main.fragment_payloads.*
import org.greenrobot.eventbus.EventBus
import java.io.File
import java.io.IOException


class PayloadsView(private val activity: BaseActivity, private val fragment: Fragment) : PayloadsContract.View {

    private lateinit var adapter: PayloadsAdapter

    override fun initViews() {
        activity.setTitle(R.string.navigation_payloads)

        prepareList()
        initClickListeners()
        initDesign()
    }

    override fun prepareList() {
        if (!PermissionsUtils.checkPermissionGranted(activity, Manifest.permission.WRITE_EXTERNAL_STORAGE)) {
            PermissionsUtils.showPermissionDialog(activity, fragment, PermissionsUtils.PERMISSIONS_READ_REQUEST_CODE)
        } else {
            initList()
        }
    }

    override fun initList() {
        MemoryUtils.copyAsset()

        adapter = PayloadsAdapter(PayloadHelper.getAll())

        activity.payloadsList.setHasFixedSize(true)
        activity.payloadsList.layoutManager = LinearLayoutManager(activity)
        activity.payloadsList.adapter = adapter
    }

    override fun initDesign() {
        activity.payloadsAdd.setColorFilter(ColorsHelper.getContrastColor(activity, ColorsHelper.resolveAccentColor(activity)))
    }

    override fun updateList() {
        if (this::adapter.isInitialized) {
            adapter.updateList()
        }
    }

    override fun initClickListeners() {
        activity.payloadsAdd.setOnClickListener { addPayload() }
    }

    override fun addPayload() {
        if (!PermissionsUtils.checkPermissionGranted(activity, Manifest.permission.WRITE_EXTERNAL_STORAGE)) {
            PermissionsUtils.showPermissionDialog(activity, fragment, PermissionsUtils.PERMISSIONS_WRITE_REQUEST_CODE)
        } else {
            getPayloadFromStorage()
        }
    }

    override fun onRequestPermissionsResult(requestCode: Int, permissions: Array<out String>, grantResults: IntArray) {
        when (requestCode) {
            PermissionsUtils.PERMISSIONS_READ_REQUEST_CODE -> if (grantResults.isNotEmpty() && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
                initList()
            }
            PermissionsUtils.PERMISSIONS_WRITE_REQUEST_CODE -> if (grantResults.isNotEmpty() && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
                getPayloadFromStorage()
            } else {
                Toast.makeText(activity, R.string.permission_storage_error, Toast.LENGTH_SHORT).show()
            }
        }
    }

    private fun getPayloadFromStorage() {
        Konae().with(activity)
                .withChosenListener(object : Konae.Result {
                    override fun onChoosePath(dirFile: File) {
                        onChosenFileListener(dirFile)
                    }
                })
                .withFileFilter(ExtensionFileFilter("bin"))
                .withTitle(activity.getString(R.string.dialog_file_chooser_payload_title))
                .build()
                .show()
    }

    private fun onChosenFileListener(pathFile: File) {
        val payload = Payload(PayloadHelper.getName(pathFile.absolutePath), PayloadHelper.getPath(PayloadHelper.getName(pathFile.absolutePath)))

        if (!payload.name.contains("bin")) {
            Toast.makeText(activity, activity.getString(R.string.helper_error_file_payload_wrong), Toast.LENGTH_SHORT).show()
        }

        try {
            MemoryUtils.toFile(pathFile, (PayloadHelper.FOLDER_PATH + "/" + payload.name))

            EventBus.getDefault().post(Events.UpdatePayloadsListEvent())
            LogHelper.log(LogHelper.INFO, "Added new payload: ${payload.name}")
        } catch (e: IOException) {
            e.printStackTrace()
            LogHelper.log(LogHelper.ERROR, "Failed to add payload: ${payload.name}")
        }
    }
}

Вот еще код, который, скорее всего, актуален:

package com.pavelrekun.rekado.services.payloads

import android.os.Environment
import com.pavelrekun.rekado.data.Payload
import io.paperdb.Paper
import java.io.File


object PayloadHelper {

    val FOLDER_PATH = "${Environment.getExternalStorageDirectory()}/RCM Loader/"
    const val BASIC_PAYLOAD_NAME = "hekate-4.0.bin"

    private const val CHOSEN_PAYLOAD = "CHOSEN_PAYLOAD"

    fun init() {
        val folderFile = File(FOLDER_PATH)
        if (!folderFile.exists()) folderFile.mkdirs()
    }

    fun getAll(): MutableList<Payload> {
        val payloads: MutableList<Payload> = ArrayList()

        File(FOLDER_PATH).listFiles().forEach {
            if (it.path.contains("bin")) {
                payloads.add(Payload(getName(it.path), it.path))
            }
        }

        return payloads
    }

    fun clearFolder() {
        File(FOLDER_PATH).listFiles().forEach {
            if (it.name != BASIC_PAYLOAD_NAME) {
                it.delete()
            }
        }
    }

    fun getNames(): MutableList<String> {
        val payloads: MutableList<String> = ArrayList()

        for (payload in getAll()) {
            payloads.add(payload.name)
        }

        return payloads
    }

    fun getName(path: String): String {
        return File(path).name
    }

    fun getPath(name: String): String {
        return "$FOLDER_PATH/$name"
    }

    fun find(name: String): Payload? {
        for (payload in getAll()) {
            if (payload.name == name) {
                return payload
            }
        }

        return null
    }

    fun putChosen(payload: Payload) {
        Paper.book().write(CHOSEN_PAYLOAD, payload)
    }

    fun getChosen(): Payload {
        return Paper.book().read(CHOSEN_PAYLOAD)
    }
}

- пакет com.pavelrekun.rekado.services.utils

import android.Manifest
import android.app.Activity
import android.content.pm.PackageManager
import android.support.v4.app.Fragment
import android.support.v4.content.ContextCompat
import android.support.v7.app.AlertDialog

import com.pavelrekun.rekado.R

object PermissionsUtils {

    const val PERMISSIONS_READ_REQUEST_CODE = 125
    const val PERMISSIONS_WRITE_REQUEST_CODE = 126

    private fun requestPermissions(fragment: Fragment, permissions: Array<String>, code: Int) {
        fragment.requestPermissions(permissions, code)
    }

    fun checkPermissionGranted(activity: Activity, permission: String): Boolean {
        val result = ContextCompat.checkSelfPermission(activity, permission)
        return result == PackageManager.PERMISSION_GRANTED
    }

    fun showPermissionDialog(activity: Activity, fragment: Fragment, code: Int) {
        val builder = AlertDialog.Builder(activity)
        builder.setTitle(R.string.permission_storage_dialog_title)
        builder.setMessage(R.string.permission_storage_dialog_description)

        val storagePermissionDialog = builder.create()
        storagePermissionDialog.setButton(AlertDialog.BUTTON_POSITIVE, activity.getString(R.string.permission_storage_button)) { _, _ ->
            storagePermissionDialog.dismiss()
            requestPermissions(fragment, arrayOf(Manifest.permission.WRITE_EXTERNAL_STORAGE), code)
        }

        storagePermissionDialog.show()
    }
}

MemoryUtils:

package com.pavelrekun.rekado.services.utils

import com.pavelrekun.rekado.RekadoApplication
import com.pavelrekun.rekado.services.eventbus.Events
import com.pavelrekun.rekado.services.payloads.PayloadHelper
import org.greenrobot.eventbus.EventBus
import java.io.*

object MemoryUtils {

    fun copyAsset() {
        val assetManager = RekadoApplication.instance.applicationContext.assets
        val sxPayloadFile = assetManager.open(PayloadHelper.BASIC_PAYLOAD_NAME)

        copyFile(sxPayloadFile, FileOutputStream("${PayloadHelper.FOLDER_PATH}/${PayloadHelper.BASIC_PAYLOAD_NAME}"))

        EventBus.getDefault().post(Events.UpdatePayloadsListEvent())
    }

    @Throws(IOException::class)
    private fun copyFile(inputStream: InputStream, outputStream: OutputStream) {
        inputStream.use { input ->
            outputStream.use { output ->
                input.copyTo(output)
            }
        }
    }

    fun removeFile(path: String) {
        File(path).delete()
    }

    fun toFile(file: File, path: String): File {
        return file.copyTo(File(path), true)
    }
}

RekadoApplication

package com.pavelrekun.rekado

import android.annotation.SuppressLint
import android.app.Application
import android.support.v7.app.AppCompatDelegate
import com.pavelrekun.rang.Rang
import com.pavelrekun.rekado.services.logs.LogHelper
import com.pavelrekun.rekado.services.payloads.PayloadHelper
import io.paperdb.Paper

@SuppressLint("StaticFieldLeak")
class RekadoApplication : Application() {

    companion object {
        lateinit var instance: RekadoApplication
    }

    override fun onCreate() {
        super.onCreate()

        instance = this

        Paper.init(this)

        LogHelper.init()
        PayloadHelper.init()

        Rang.defaults().primaryColor().accentColor().nightMode().oledMode()
        Rang.init(this)
    }

}

Я был бы чрезвычайно признателен, если кто-то изучит код и попытается выяснить, почему происходит сбой при нажатии на вкладку «Полезные нагрузки» в приложении (только один раз после первоговремя установки) сразу после запроса и предоставления разрешения на хранение, и папка «RCM Loader» не найдена в хранилище.Приложение работает нормально после сбоя и создает папку с файлом bin в комплекте, но я пытаюсь выяснить, что вызывает сбой, в первую очередь: https://github.com/ThirdEyeClarity/RCM-Loader?files=1

1 Ответ

0 голосов
/ 27 августа 2018

Глядя на logcat с такой строкой:

Caused by: java.io.FileNotFoundException: /storage/emulated/0/RCM Loader/hekate-4.0.bin (No such file or directory)

В коде, который вы нам показываете, я задаюсь вопросом о методе PayloadHelper.init():

fun init() {
    val folderFile = File(FOLDER_PATH)
    if (!folderFile.exists()) folderFile.mkdirs()
}

Iнигде в этих примерах не видно ни одного вызова к нему.Не могли бы вы показать нам, где используется метод init()?

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...