Как совместить загрузку файлов с вкладками в веб-просмотре? - PullRequest
0 голосов
/ 08 июля 2019

Я учусь кодировать и пытаюсь создать простое приложение Android Webview с двумя вкладками, куда пользователь сможет загружать файлы.

Я не очень опытен в Java и Kotlin, и хотя я не спал много ночей, эта проблема оказывается выше моих способностей.

Мне удалось сделать то, что я хочу в отдельных приложениях , но я просто не могу объединить две функции (просмотр веб-страниц с вкладками и загрузка файлов) в одном приложении. Это сводит меня с ума.

Я думаю, что проблема в том, что веб-представление с вкладками использует класс фрагмента, но при загрузке файла используется класс mainactivity. Если я попытаюсь поместить код загрузки файла в класс фрагмента, он полностью сломается.

Также, если я попытаюсь поместить класс MainActivity: AppCompatActivity () в класс FragmentTwo: Fragment (), он запускается, но просто показывает пустую страницу.

Вот файл фрагмента с функционирующим простым веб-представлением.

class FragmentOne : Fragment() {

    private lateinit var mWebView: WebView

    override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?,
                              savedInstanceState: Bundle?): View? {

        val v = inflater.inflate(R.layout.fragment_one, container, false)
        mWebView = v.findViewById(R.id.webview)
        mWebView.loadUrl("https://www.google.com")

        // Enable Javascript
        val webSettings = mWebView.settings
        webSettings.javaScriptEnabled = true

        // Force links and redirects to open in the WebView instead of in a browser
        mWebView.webViewClient = WebViewClient()

        return v
    }
    companion object {
        fun newInstance(): FragmentOne = FragmentOne()
    }
}

Вот код загрузки файла.

class MainActivity : AppCompatActivity() {

    private var webView: WebView? = null
    private var mCM: String? = null
    private var mUM: ValueCallback<Uri>? = null
    private var mUMA: ValueCallback<Array<Uri>>? = null

    //select whether you want to upload multiple files (set 'true' for yes)
    private val multiplefiles = false

    override fun onActivityResult(requestCode: Int, resultCode: Int, intent: Intent?) {
        super.onActivityResult(requestCode, resultCode, intent)
        if (Build.VERSION.SDK_INT >= 21) {
            var results: Array<Uri>? = null
            //checking if response is positive
            if (resultCode == Activity.RESULT_OK) {
                if (requestCode == FCR) {
                    if (null == mUMA) {
                        return
                    }
                    if (intent == null || intent.data == null) {
                        if (mCM != null) {
                            results = arrayOf(Uri.parse(mCM))
                        }
                    } else {
                        val dataString = intent.dataString
                        if (dataString != null) {
                            results = arrayOf(Uri.parse(dataString))
                        } else {
                            if (multiplefiles) {
                                if (intent.clipData != null) {
                                    val numSelectedFiles = intent.clipData!!.itemCount
                                    val results = arrayOfNulls<Uri>(numSelectedFiles)
                                    for (i in 0 until numSelectedFiles) {
                                        results[i] = intent.clipData!!.getItemAt(i).uri
                                    }
                                }
                            }
                        }
                    }
                }
            }
            mUMA!!.onReceiveValue(results)
            mUMA = null
        } else {
            if (requestCode == FCR) {
                if (null == mUM) return
                val result = if (intent == null || resultCode != Activity.RESULT_OK) null else intent.data
                mUM!!.onReceiveValue(result)
                mUM = null
            }
        }
    }

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)

        webView = findViewById<View>(R.id.webview) as WebView
        assert(webView != null)
        val webSettings = webView!!.settings
        webSettings.javaScriptEnabled = true
        webSettings.allowFileAccess = true

        if (Build.VERSION.SDK_INT >= 21) {
            webSettings.mixedContentMode = 0
            webView!!.setLayerType(View.LAYER_TYPE_HARDWARE, null)
        } else if (Build.VERSION.SDK_INT >= 19) {
            webView!!.setLayerType(View.LAYER_TYPE_HARDWARE, null)
        } else {
            webView!!.setLayerType(View.LAYER_TYPE_SOFTWARE, null)
        }
        webView!!.webViewClient = Callback()
        webView!!.loadUrl("https://imgbb.com") //add your test web/page address here
        webView!!.webChromeClient = object : WebChromeClient() {
            /*
             * openFileChooser is not a public Android API and has never been part of the SDK.
             */
            //handling input[type="file"] requests for android API 16+
            @SuppressLint("ObsoleteSdkInt")
            fun openFileChooser(uploadMsg: ValueCallback<Uri>) {
                mUM = uploadMsg
                val i = Intent(Intent.ACTION_GET_CONTENT)
                i.addCategory(Intent.CATEGORY_OPENABLE)
                i.type = "*/*"
                if (multiplefiles && Build.VERSION.SDK_INT >= 18) {
                    i.putExtra(Intent.EXTRA_ALLOW_MULTIPLE, true)
                }
                startActivityForResult(Intent.createChooser(i, "File Chooser"), FCR)
            }

            //handling input[type="file"] requests for android API 21+
            @SuppressLint("InlinedApi")
            override fun onShowFileChooser(
                    webView: WebView,
                    filePathCallback: ValueCallback<Array<Uri>>,
                    fileChooserParams: WebChromeClient.FileChooserParams
            ): Boolean {
                if (filepermission()) {
                    val perms = arrayOf(
                            Manifest.permission.WRITE_EXTERNAL_STORAGE,
                            Manifest.permission.READ_EXTERNAL_STORAGE,
                            Manifest.permission.CAMERA
                    )

                    //checking for storage permission to write images for upload
                    if (ContextCompat.checkSelfPermission(
                                    this@MainActivity,
                                    Manifest.permission.WRITE_EXTERNAL_STORAGE
                            ) != PackageManager.PERMISSION_GRANTED && ContextCompat.checkSelfPermission(
                                    this@MainActivity,
                                    Manifest.permission.CAMERA
                            ) != PackageManager.PERMISSION_GRANTED
                    ) {
                        ActivityCompat.requestPermissions(this@MainActivity, perms, FCR)

                        //checking for WRITE_EXTERNAL_STORAGE permission
                    } else if (ContextCompat.checkSelfPermission(
                                    this@MainActivity,
                                    Manifest.permission.WRITE_EXTERNAL_STORAGE
                            ) != PackageManager.PERMISSION_GRANTED
                    ) {
                        ActivityCompat.requestPermissions(
                                this@MainActivity,
                                arrayOf(
                                        Manifest.permission.WRITE_EXTERNAL_STORAGE,
                                        Manifest.permission.READ_EXTERNAL_STORAGE
                                ),
                                FCR
                        )

                        //checking for CAMERA permissions
                    } else if (ContextCompat.checkSelfPermission(
                                    this@MainActivity,
                                    Manifest.permission.CAMERA
                            ) != PackageManager.PERMISSION_GRANTED
                    ) {
                        ActivityCompat.requestPermissions(
                                this@MainActivity,
                                arrayOf(Manifest.permission.CAMERA),
                                FCR
                        )
                    }
                    if (mUMA != null) {
                        mUMA!!.onReceiveValue(null)
                    }
                    mUMA = filePathCallback
                    var takePictureIntent: Intent? = Intent(MediaStore.ACTION_IMAGE_CAPTURE)
                    if (takePictureIntent!!.resolveActivity(this@MainActivity.packageManager) != null) {
                        var photoFile: File? = null
                        try {
                            photoFile = createImageFile()
                            takePictureIntent.putExtra("PhotoPath", mCM)
                        } catch (ex: IOException) {
                            Log.e(TAG, "Image file creation failed", ex)
                        }

                        if (photoFile != null) {
                            mCM = "file:" + photoFile.absolutePath
                            takePictureIntent.putExtra(MediaStore.EXTRA_OUTPUT, Uri.fromFile(photoFile))
                        } else {
                            takePictureIntent = null
                        }
                    }
                    val contentSelectionIntent = Intent(Intent.ACTION_GET_CONTENT)
                    contentSelectionIntent.addCategory(Intent.CATEGORY_OPENABLE)
                    contentSelectionIntent.type = "*/*"
                    if (multiplefiles) {
                        contentSelectionIntent.putExtra(Intent.EXTRA_ALLOW_MULTIPLE, true)
                    }
                    val intentArray: Array<Intent?>
                    if (takePictureIntent != null) {
                        intentArray = arrayOf(takePictureIntent)
                    } else {
                        intentArray = arrayOfNulls<Intent>(0)
                    }

                    val chooserIntent = Intent(Intent.ACTION_CHOOSER)
                    chooserIntent.putExtra(Intent.EXTRA_INTENT, contentSelectionIntent)
                    chooserIntent.putExtra(Intent.EXTRA_TITLE, "File Chooser")
                    chooserIntent.putExtra(Intent.EXTRA_INITIAL_INTENTS, intentArray)
                    startActivityForResult(chooserIntent, FCR)
                    return true
                } else {
                    return false
                }
            }
        }
    }

    //callback reporting if error occurs
    inner class Callback : WebViewClient() {
        override fun onReceivedError(
                view: WebView,
                errorCode: Int,
                description: String,
                failingUrl: String
        ) {
            Toast.makeText(applicationContext, "Failed loading app!", Toast.LENGTH_SHORT).show()
        }
    }

    fun filepermission(): Boolean {
        return if (Build.VERSION.SDK_INT >= 23 && (ContextCompat.checkSelfPermission(
                        this,
                        Manifest.permission.WRITE_EXTERNAL_STORAGE
                ) != PackageManager.PERMISSION_GRANTED || ContextCompat.checkSelfPermission(
                        this,
                        Manifest.permission.CAMERA
                ) != PackageManager.PERMISSION_GRANTED)
        ) {
            ActivityCompat.requestPermissions(
                    this@MainActivity,
                    arrayOf(Manifest.permission.WRITE_EXTERNAL_STORAGE, Manifest.permission.CAMERA),
                    1
            )
            false
        } else {
            true
        }
    }

    //creating new image file here
    @Throws(IOException::class)
    private fun createImageFile(): File {
        @SuppressLint("SimpleDateFormat") val timeStamp = SimpleDateFormat("yyyyMMdd_HHmmss")
        val imageFileName = "img_" + timeStamp + "_"
        val storageDir = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_PICTURES)
        return File.createTempFile(imageFileName, ".jpg", storageDir)
    }

    //back/down key handling
    override fun onKeyDown(keyCode: Int, event: KeyEvent): Boolean {
        if (event.action == KeyEvent.ACTION_DOWN) {
            when (keyCode) {
                KeyEvent.KEYCODE_BACK -> {
                    if (webView!!.canGoBack()) {
                        webView!!.goBack()
                    } else {
                        finish()
                    }
                    return true
                }
            }
        }
        return super.onKeyDown(keyCode, event)
    }


    companion object {
        private val TAG = MainActivity::class.java.simpleName
        private const val FCR = 1
    }
}

Любая помощь будет принята с благодарностью!

...