Я учусь кодировать и пытаюсь создать простое приложение 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
}
}
Любая помощь будет принята с благодарностью!