Manage External Storage Permission not clickable - android

So, I am creating an app, with the goal of turning text to pdf, and saving it to the external storage. After running the app with no errors, I encountered a weird bug, the "Manage External Storage Permission" button was not clickable. After reading the stack overflow posts, it seems like I have wrote the proper functions, but all the examples were in activities, so the problem may be there
Any help?
class CreatePdfFragment : Fragment(R.layout.fragment_create_pdf) {
private lateinit var binding: FragmentCreatePdfBinding
private val STORAGE_PERMISSION_CODE: Int = 100
override fun onCreateView(
inflater: LayoutInflater, container: ViewGroup?,
savedInstanceState: Bundle?
): View {
binding = FragmentCreatePdfBinding.inflate(inflater, container, false)
return binding.root
}
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
binding.btnToPdf.setOnClickListener {
if (checkPermission()) {
Log.d(TAG, "onViewCreated: Permission already granted, create folder")
savePdf()
} else {
Log.d(TAG, "onViewCreated: Permission was not granted, request")
requestPermission()
}
}
}
override fun onRequestPermissionsResult(
requestCode: Int,
permissions: Array<out String>,
grantResults: IntArray
) {
super.onRequestPermissionsResult(requestCode, permissions, grantResults)
if (requestCode == STORAGE_PERMISSION_CODE) {
if (grantResults.isNotEmpty()) {
val write = grantResults[0] == PackageManager.PERMISSION_GRANTED
val read = grantResults[1] == PackageManager.PERMISSION_GRANTED
if (write && read) {
Log.d(TAG, "onRequestPermissionsResult: External Storage Permission granted")
savePdf()
} else {
Log.d(TAG, "onRequestPermissionsResult: External Storage Permission denied...")
toast("External Storage Permission denied...")
}
}
}
}
private fun savePdf() {
//create object of Document class
val mDoc = Document()
//pdf file name
val mFileName = SimpleDateFormat("yyyyMMdd_HHmmss", Locale.getDefault()).format(System.currentTimeMillis())
//pdf file path
val mFilePath = Environment.getExternalStorageDirectory().toString() + "/" + mFileName +".pdf"
try {
//create instance of PdfWriter class
PdfWriter.getInstance(mDoc, FileOutputStream(mFilePath))
//open the document for writing
mDoc.open()
//get text from EditText i.e. textEt
val mText = binding.etPdfText.text.toString()
//add author of the document (metadata)
mDoc.addAuthor("Atif Pervaiz")
//add paragraph to the document
mDoc.add(Paragraph(mText))
//close document
mDoc.close()
//show file saved message with file name and path
toast("$mFileName.pdf\nis saved to\n$mFilePath")
}
catch (e: Exception){
//if anything goes wrong causing exception, get and show exception message
toast(e.message.toString())
}
}
private val storageActivityResultLauncher = registerForActivityResult(ActivityResultContracts.StartActivityForResult()) {
Log.d(TAG, "storageActivityResultLauncher: ")
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) {
if (Environment.isExternalStorageManager()) {
Log.d(TAG, "storageActivityResultLauncher: ")
savePdf()
} else {
Log.d(TAG, "storageActivityResultLauncher: Manage External Storage Permission is denied...")
toast("Manage External Storage Permission is denied...")
}
} else {
}
}
private fun requestPermission() {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) {
try {
Log.d(TAG, "requestPermission: try")
val intent = Intent()
intent.action = Settings.ACTION_MANAGE_APP_ALL_FILES_ACCESS_PERMISSION
val uri = Uri.fromParts("package", this#CreatePdfFragment.requireActivity().packageName, null)
intent.data = uri
storageActivityResultLauncher.launch(intent)
} catch (e: Exception) {
Log.d(TAG, "requestPermission: ", e)
val intent = Intent()
intent.action = Settings.ACTION_MANAGE_APP_ALL_FILES_ACCESS_PERMISSION
storageActivityResultLauncher.launch(intent)
}
} else {
ActivityCompat.requestPermissions(this#CreatePdfFragment.requireActivity(),
arrayOf(Manifest.permission.WRITE_EXTERNAL_STORAGE, Manifest.permission.READ_EXTERNAL_STORAGE),
STORAGE_PERMISSION_CODE)
}
}
private fun checkPermission(): Boolean {
return if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) {
Environment.isExternalStorageManager()
} else {
val write = ContextCompat.checkSelfPermission(this#CreatePdfFragment.requireActivity(), Manifest.permission.WRITE_EXTERNAL_STORAGE)
val read = ContextCompat.checkSelfPermission(this#CreatePdfFragment.requireActivity(), Manifest.permission.READ_EXTERNAL_STORAGE)
write == PackageManager.PERMISSION_GRANTED && read == PackageManager.PERMISSION_GRANTED
}
}
private fun toast(message: String) {
Toast.makeText(this#CreatePdfFragment.requireActivity(), message, Toast.LENGTH_SHORT).show()
}
}

Please ignore, the permission below was missing
<uses-permission android:name="android.permission.MANAGE_EXTERNAL_STORAGE"/>

Related

requestPermissions(arrayOf(Manifest.permission.BLUETOOTH_CONNECT), REQUEST_CODE) not showing pop up in Android 10 but its working in Android 12

The below code is Working for Android 12 but same not working Android 10 the problem its it showing the run time permission pop up for BLUETOOTH_CONNECT
Here is the below code i have written inside the fragment
class FirstFragment : Fragment() {
private var _binding: FragmentFirstBinding? = null
private var ctx: Context? = null
val bluetoothAdapter: BluetoothAdapter? = BluetoothAdapter.getDefaultAdapter()
companion object {
private const val BLUETOOTH_PERMISSION_CODE = 100
private const val BLUETOOTH_CONNECT_PERMISSION_CODE = 101
}
// This property is only valid between onCreateView and
// onDestroyView.
private val binding get() = _binding!!
override fun onCreateView(
inflater: LayoutInflater, container: ViewGroup?,
savedInstanceState: Bundle?
): View? {
_binding = FragmentFirstBinding.inflate(inflater, container, false)
return binding.root
}
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
this.ctx = view.context
//get the devie manifrature name
System.out.println(android.os.Build.MANUFACTURER)
//get the type of the bluetooth device
getBluetoothDeviceType()
checkPermission(
Manifest.permission.BLUETOOTH_CONNECT,
BLUETOOTH_CONNECT_PERMISSION_CODE
)
binding.buttonFirst.setOnClickListener {
findNavController().navigate(R.id.action_FirstFragment_to_SecondFragment)
}
}
private fun requestBluetoothPermission() {
}
private fun getBluetoothDeviceType() {
if (ActivityCompat.checkSelfPermission(
ctx!!,
Manifest.permission.BLUETOOTH_CONNECT
) != PackageManager.PERMISSION_GRANTED
) {
if (BluetoothClass.Device.PHONE_CELLULAR == 0x0204) {
System.out.println("permission is granted")
}
} else {
if (BluetoothClass.Device.PHONE_CELLULAR != 0x0204) {
System.out.println("permission is not granted")
}
}
}
private fun checkPermission(permission: String, requestCode: Int) {
if (ContextCompat.checkSelfPermission(
ctx!! as Activity,
permission
) != PackageManager.PERMISSION_GRANTED
) {
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.Q) {
println("permission is not required")
} else {
requestPermissions(arrayOf(permission), requestCode)
}
// Requesting the permission
//Fragment.requestPermission.launch(Manifest.permission.CAMERA)
} else {
Toast.makeText(ctx!! as Activity, "Permission already granted", Toast.LENGTH_SHORT)
.show()
}
}
override fun onRequestPermissionsResult(
requestCode: Int,
permissions: Array<String>,
grantResults: IntArray
) {
super.onRequestPermissionsResult(requestCode, permissions, grantResults)
if (requestCode == BLUETOOTH_CONNECT_PERMISSION_CODE) {
//permission granted
if (grantResults.isNotEmpty() && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
if (bluetoothAdapter == null) {
// Handle the situation where Bluetooth is not available
} else {
// Get a set of currently paired devices
if (ContextCompat.checkSelfPermission(
ctx!! as Activity,
permissions[0]
) == PackageManager.PERMISSION_GRANTED
) {
val pairedDevices: Set<BluetoothDevice> = bluetoothAdapter.bondedDevices
// If there are paired devices
if (pairedDevices.isNotEmpty()) {
// Loop through paired devices
for (device in pairedDevices) {
// Check if the device is a scanner
if (device.bluetoothClass.majorDeviceClass == BluetoothClass.Device.Major.IMAGING) {
// Device is a scanner
val scannerDevice = device
println("Scanner found: ${scannerDevice.name}")
}
}
} else {
// Handle the situation where there are no paired devices
}
}
Toast.makeText(
ctx!! as Activity,
"Bluetooth Connect Permission Granted",
Toast.LENGTH_SHORT
).show()
}
} else {
Toast.makeText(
ctx!! as Activity,
"Bluetooth Connect Permission Denied",
Toast.LENGTH_SHORT
).show()
}
}
}
override fun onDestroyView() {
super.onDestroyView()
_binding = null
}
}
here how below my build.gradle looks like
android {
compileSdk 33
defaultConfig {
applicationId "com.demo"
minSdk 23
targetSdk 32
versionCode 1
versionName "1.0"
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
}

Creating custom ActivityResultContract to ask for location permission

I would like to create a custom ActivityResultContract to request both coarse and fine location that has a custom response.
class LocationPermission : ActivityResultContract<Void?, LocationPermissionResult>() {
override fun createIntent(context: Context, input: Array<String>): Intent {
val requestPermissions = arrayOf(
Manifest.permission.ACCESS_FINE_LOCATION,
Manifest.permission.ACCESS_COARSE_LOCATION
)
return Intent(ActivityResultContracts.RequestMultiplePermissions.ACTION_REQUEST_PERMISSIONS)
.putExtra(ActivityResultContracts.RequestMultiplePermissions.EXTRA_PERMISSIONS, requestPermissions)
}
...
}
Calling that from an activity:
private val reportLocationIntent = registerForActivityResult(LocationPermission()) { result ->
}
...
reportLocationIntent.launch()
However when doing so createIntent is never called. What am I doing wrong?
Your code in question has compilation errors, however this approach seems to work. I don't really know what the "custom response" should be from the question directly, so I've created a class called class LocationPermissionResult(val granted: Boolean) based on your question. It is mostly compiled from RequestMultiplePermissions from ActivityResultContracts.
Tested on API 30 and API 33 emulator, the permission dialog opens and the returned result is correct as well. (Make sure the permissions are added to AndroidManifest.xml)
Here is the source code:
class LocationPermission : ActivityResultContract<Void?, LocationPermissionResult>() {
private val permissions = arrayOf(
Manifest.permission.ACCESS_FINE_LOCATION,
Manifest.permission.ACCESS_COARSE_LOCATION
)
override fun createIntent(context: Context, input: Void?): Intent {
return Intent(ActivityResultContracts.RequestMultiplePermissions.ACTION_REQUEST_PERMISSIONS).putExtra(
ActivityResultContracts.RequestMultiplePermissions.EXTRA_PERMISSIONS, permissions)
}
override fun getSynchronousResult(context: Context,
input: Void?): SynchronousResult<LocationPermissionResult>? {
val allGranted = permissions.all { permission ->
ContextCompat.checkSelfPermission(
context,
permission
) == PackageManager.PERMISSION_GRANTED
}
return if (allGranted) {
SynchronousResult(LocationPermissionResult(true))
} else null
}
override fun parseResult(resultCode: Int, intent: Intent?): LocationPermissionResult {
if (resultCode != Activity.RESULT_OK) return LocationPermissionResult(false)
if (intent == null) return LocationPermissionResult(false)
val grantResults = intent.getIntArrayExtra(
ActivityResultContracts.RequestMultiplePermissions.EXTRA_PERMISSION_GRANT_RESULTS)
return LocationPermissionResult(grantResults?.all { it == PackageManager.PERMISSION_GRANTED } == true)
}
}
class LocationPermissionResult(val granted: Boolean)
this is my solution to request both coarse and fine location, i hope this will do the job
object Permission {
private const val REQUEST_CODE_PERMISSION: Int = 1
#SuppressLint("ObsoleteSdkInt")
fun isGrantedLocationPermission(context: Context): Boolean {
return if (Build.VERSION.SDK_INT < Build.VERSION_CODES.M) {
true
} else {
context.checkSelfPermission(Manifest.permission.ACCESS_FINE_LOCATION) == PackageManager.PERMISSION_GRANTED ||
context.checkSelfPermission(Manifest.permission.ACCESS_COARSE_LOCATION) == PackageManager.PERMISSION_GRANTED
}
}
fun grantLocationPermission(context: Context) {
val permissions = arrayOf(
Manifest.permission.ACCESS_FINE_LOCATION,
Manifest.permission.ACCESS_COARSE_LOCATION
)
(context as MainActivity).requestPermissions(permissions, REQUEST_CODE_PERMISSION)
}
}
Use it from MainActivity:
override fun onCreate(savedInstanceState: Bundle?) {
...
val button = findViewById<Button>(R.id.btnGetLocation)
button.setOnClickListener {
getLocation()
}
}
private fun getLocation() {
//check if permission isnt granted:
if (!Permission.isGrantedLocationPermission(this))
Permission.grantLocationPermission(this)
else {
...
}
}
//Check if user give permission or not:
override fun onRequestPermissionsResult(
requestCode: Int,
permissions: Array<out String>,
grantResults: IntArray
) {
if (grantResults.isNotEmpty() && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
//permission granted
} else {
//permission denied
}
super.onRequestPermissionsResult(requestCode, permissions, grantResults)
}

Upload captured image Using volley at max qualtiy kotlin

i need to upload image to php server but i need the image to be at max quality before it would capture and upload a bitmap but i need the image to be clear so i tried this code but cant seem to get it to work.
so basically i need to upload the image stored on this line
cameraIntent.putExtra(MediaStore.EXTRA_OUTPUT, image_uri)
class capture : AppCompatActivity() {
private val PERMISSION_CODE = 1000;
private val IMAGE_CAPTURE_CODE = 1001
var image_uri: Uri? = null
var bitmap: Bitmap? = null
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_capture)
//button click
btn_take_photo.setOnClickListener {
//if system os is Marshmallow or Above, we need to request runtime permission
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M){
if (checkSelfPermission(Manifest.permission.CAMERA)
== PackageManager.PERMISSION_DENIED ||
checkSelfPermission(Manifest.permission.WRITE_EXTERNAL_STORAGE)
== PackageManager.PERMISSION_DENIED){
//permission was not enabled
val permission = arrayOf(Manifest.permission.CAMERA, Manifest.permission.WRITE_EXTERNAL_STORAGE)
//show popup to request permission
requestPermissions(permission, PERMISSION_CODE)
}
else{
//permission already granted
openCamera()
}
}
else{
//system os is < marshmallow
openCamera()
}
}
}
private fun openCamera() {
val values = ContentValues()
values.put(MediaStore.Images.Media.TITLE, "New Picture")
values.put(MediaStore.Images.Media.DESCRIPTION, "From the Camera")
image_uri = contentResolver.insert(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, values)
//camera intent
val cameraIntent = Intent(MediaStore.ACTION_IMAGE_CAPTURE)
cameraIntent.putExtra(MediaStore.EXTRA_OUTPUT, image_uri)
startActivityForResult(cameraIntent, IMAGE_CAPTURE_CODE)
}
override fun onRequestPermissionsResult(requestCode: Int, permissions: Array<out String>, grantResults: IntArray) {
//called when user presses ALLOW or DENY from Permission Request Popup
when(requestCode){
PERMISSION_CODE -> {
if (grantResults.size > 0 && grantResults[0] ==
PackageManager.PERMISSION_GRANTED){
//permission from popup was granted
openCamera()
}
else{
//permission from popup was denied
Toast.makeText(this, "Permission denied", Toast.LENGTH_SHORT).show()
}
}
}
}
override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
super.onActivityResult(requestCode, resultCode, data)
//called when image was captured from camera intent
if (resultCode == Activity.RESULT_OK){
val takenImage: Bitmap = BitmapFactory.decodeFile(image_uri.toString())
//set image captured to image view
imgv_capture_image_preview.setImageURI(image_uri)
val url = connection.server_url + "body_pictures.php"
val rq: RequestQueue = Volley.newRequestQueue(this)
val sr = object : StringRequest(Method.POST, url, Response.Listener { response ->
val check: String = response
val checknew = check.replace("\\s".toRegex(), "")
if (checknew == "success") {
Toast.makeText(
this,
"Image uploaded Successful",
Toast.LENGTH_LONG
).show()
} else {
Toast.makeText(
this,
"ERROR image upload failed, " + checknew,
Toast.LENGTH_LONG
).show()
}
}, Response.ErrorListener { error ->
Toast.makeText(
this,
"Server TIME OUT",
Toast.LENGTH_LONG
).show()
}) {
override fun getParams(): MutableMap<String, String> {
val map = HashMap<String, String>()
val images = takenImage?.let { getStringImage(it) }
if (images != null) {
map.put("image_data", images)
}
return map
}
}
rq.add(sr)
}
}
fun getStringImage(bitmap: Bitmap): String? {
val baos = ByteArrayOutputStream()
bitmap.compress(Bitmap.CompressFormat.JPEG, 100, baos)
val b = baos.toByteArray()
return Base64.encodeToString(b, Base64.DEFAULT)
}

How to save on Camera Photo on Custom Location?

I am currently using the following code here:
val cameraRequestCode = 1
val cameraPermissionCode = 1
var imageUri : Uri? = null
#RequiresApi(api = Build.VERSION_CODES.M)
override fun onActivityResult(
requestCode: Int,
resultCode: Int,
data: Intent?
) {
super.onActivityResult(requestCode, resultCode, data)
if (requestCode == cameraRequestCode) {
if (resultCode == Activity.RESULT_OK) {
var stream: FileOutputStream? = null
try {
val photo: Bitmap =
MediaStore.Images.Media.getBitmap(contentResolver, imageUri)
val saveFilePath: String = getRealPathFromURI(imageUri)
stream = FileOutputStream(saveFilePath)
photo.compress(Bitmap.CompressFormat.JPEG, 25, stream)
} catch (e: IOException) {
e.printStackTrace()
Toast.makeText(
applicationContext,
"Can't save image !",
Toast.LENGTH_SHORT
).show()
} finally {
try {
if (stream != null) {
stream.close()
Toast.makeText(
applicationContext,
"Image saved successfully !",
Toast.LENGTH_SHORT
).show()
} else {
Toast.makeText(
applicationContext,
"Can't save image, try again !",
Toast.LENGTH_SHORT
).show()
}
} catch (e: IOException) {
e.printStackTrace()
}
}
farmersPixImageView.setImageURI(imageUri)
} else if (resultCode == Activity.RESULT_CANCELED) {
Toast.makeText(applicationContext, "Cancelled", Toast.LENGTH_SHORT).show()
} else {
Toast.makeText(applicationContext, "Can't capture image !", Toast.LENGTH_SHORT)
.show()
}
}
}
private fun getRealPathFromURI(contentUri: Uri?): String {
val proj = arrayOf(MediaStore.Images.Media.DATA)
val cursor: Cursor = managedQuery(contentUri, proj, null, null, null)
val column_index: Int = cursor.getColumnIndexOrThrow(MediaStore.Images.Media.DATA)
cursor.moveToFirst()
return cursor.getString(column_index)
}
#RequiresApi(Build.VERSION_CODES.M)
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_add)
farmersPixImageView.setOnClickListener {
//if system os is Marshmallow or Above, we need to request runtime permission
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
if (checkSelfPermission(Manifest.permission.CAMERA)
== PackageManager.PERMISSION_DENIED ||
checkSelfPermission(Manifest.permission.WRITE_EXTERNAL_STORAGE)
== PackageManager.PERMISSION_DENIED
) {
//permission was not enabled
val permission = arrayOf(
Manifest.permission.CAMERA,
Manifest.permission.WRITE_EXTERNAL_STORAGE
)
//show popup to request permission
requestPermissions(permission, cameraPermissionCode)
} else {
val values = ContentValues()
values.put(
MediaStore.Images.Media.TITLE,
"${relativeFileName}_${System.currentTimeMillis()}"
)
values.put(
MediaStore.Images.Media.DISPLAY_NAME,
"${relativeFileName}_${getDate(
System.currentTimeMillis(),
"MM/dd/yyyy hh:mm:ss.SSS"
)}"
)
values.put(MediaStore.Images.Media.DESCRIPTION, "My Photos")
values.put(MediaStore.Images.Media.MIME_TYPE, "image/jpeg")
imageUri = contentResolver.insert(
MediaStore.Images.Media.EXTERNAL_CONTENT_URI,
values
)
val cameraIntent =
Intent(MediaStore.ACTION_IMAGE_CAPTURE)
cameraIntent.putExtra(MediaStore.EXTRA_OUTPUT, imageUri)
startActivityForResult(cameraIntent, cameraRequestCode)
}
}
}
}
I am using this because I could not get the sample from the Official Documentation to work.
I previously used:
values.put(MediaStore.Images.Media.RELATIVE_PATH, relativeLocation)
but it is only available on Android Q onwards.
I also don't know how to use imageUri to save to custom location because it using contentResolver:
imageUri = contentResolver.insert(
MediaStore.Images.Media.EXTERNAL_CONTENT_URI,
values
)
How do I save the photo on custom location using the above code?

Why I am not able to open camera from webview in android?

I am having problem that I am not able to open camera from webview in that I am having php page so I have to open gallery and camera from there but I am not able to do what I got from this link "https://gist.github.com/jhonsore/8a8378c147ec00ac6f3fa53569c82ef8".
I can open gallery but not camera please give me any solution.
A working example in Kotlin for Android 7+
Add camera permissions
<uses-permission android:name="android.permission.CAMERA" />
<uses-permission android:name="android.permission.CAMERA2" />
Configure your WebView
private fun configureWebViewSettings() {
binding.webView.settings.javaScriptEnabled = true
binding.webView.settings.domStorageEnabled = true
binding.webView.settings.setSupportZoom(false)
binding.webView.settings.allowFileAccess = true
binding.webView.settings.allowContentAccess = true
binding.webView.webChromeClient = getCustomWebChromeClient()
}
Add the lines below to your Activity
private var imagePathCallback: ValueCallback<Array<Uri>>? = null
private var cameraImagePath: String? = null
Implement a WebChromeClient and add it to your WebView
private fun getCustomWebChromeClient() = object : WebChromeClient() {
override fun onShowFileChooser(
view: WebView?,
filePath: ValueCallback<Array<Uri>>?,
fileChooserParams: FileChooserParams?
): Boolean {
if (checkSelfPermission(Manifest.permission.CAMERA) != PackageManager.PERMISSION_GRANTED)
requestPermissions(arrayOf(Manifest.permission.CAMERA), CAMERA_REQUEST_CODE)
imagePathCallback?.onReceiveValue(null)
imagePathCallback = null
imagePathCallback = filePath
val takePictureIntent = createImageCaptureIntent()
val contentSelectionIntent = Intent(Intent.ACTION_GET_CONTENT)
contentSelectionIntent.addCategory(Intent.CATEGORY_OPENABLE)
contentSelectionIntent.type = INTENT_FILE_TYPE
val intentArray: Array<Intent?>
intentArray = takePictureIntent?.let { arrayOf(it) } ?: arrayOfNulls(0)
val chooserIntent = Intent(Intent.ACTION_CHOOSER)
chooserIntent.putExtra(Intent.EXTRA_INTENT, contentSelectionIntent)
chooserIntent.putExtra(Intent.EXTRA_TITLE, getString(R.string.file_chooser_title))
chooserIntent.putExtra(Intent.EXTRA_INITIAL_INTENTS, intentArray)
try {
startActivityForResult(chooserIntent, REQUEST_SELECT_FILE)
} catch (e: ActivityNotFoundException) {
imagePathCallback = null
cameraImagePath = null
Toast.makeText(
this#MainActivity,
getString(R.string.cannot_open_file_chooser_txt),
Toast.LENGTH_LONG
).show()
return false
}
return true
}
private fun createImageCaptureIntent(): Intent? {
var captureImageIntent: Intent? = Intent(MediaStore.ACTION_IMAGE_CAPTURE)
if (captureImageIntent?.resolveActivity(packageManager) != null) {
var imageFile: File? = null
try {
imageFile = createImageFile()
captureImageIntent.putExtra("CameraImagePath", cameraImagePath)
} catch (ex: IOException) {
ex.printStackTrace()
}
if (imageFile != null) {
cameraImagePath = CAMERA_PHOTO_PATH_POSTFIX + imageFile.absolutePath
captureImageIntent.putExtra(MediaStore.EXTRA_OUTPUT, Uri.fromFile(imageFile))
} else {
captureImageIntent = null
}
}
return captureImageIntent
}
private fun createImageFile(): File? {
val timeStamp = SimpleDateFormat.getDateInstance().format(Date())
val imageFileName = PHOTO_NAME_POSTFIX + timeStamp + "_"
val storageDir = getExternalFilesDir(Environment.DIRECTORY_PICTURES)
return File.createTempFile(imageFileName, PHOTO_FORMAT, storageDir)
}
Implement onRequestPermissionsResult in your Activity
override fun onRequestPermissionsResult(
requestCode: Int,
permissions: Array<out String>,
grantResults: IntArray
) {
super.onRequestPermissionsResult(requestCode, permissions, grantResults)
if (requestCode == CAMERA_REQUEST_CODE) {
if (grantResults[0] == PackageManager.PERMISSION_GRANTED) {
Toast.makeText(
this,
getString(R.string.amera_permission_granted_txt),
Toast.LENGTH_LONG
).show()
} else {
Toast.makeText(
this,
getString(R.string.camera_permission_denied_txt),
Toast.LENGTH_LONG
).show()
}
}
}
Implement onActivityResult in your Activity
override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
super.onActivityResult(requestCode, resultCode, data)
if (requestCode != REQUEST_SELECT_FILE || imagePathCallback == null) return
var results: Array<Uri>? = null
if (resultCode == RESULT_OK) {
if (data == null) {
if (cameraImagePath != null) results = arrayOf(Uri.parse(cameraImagePath))
} else {
val dataString = data.dataString
if (dataString != null) results = arrayOf(Uri.parse(dataString))
}
}
imagePathCallback?.onReceiveValue(results)
imagePathCallback = null
}
Constants
companion object {
private const val CAMERA_REQUEST_CODE = 113
private const val REQUEST_SELECT_FILE = 13
private const val INTENT_FILE_TYPE = "image/*"
private const val CAMERA_PHOTO_PATH_POSTFIX = "file:"
private const val PHOTO_NAME_POSTFIX = "JPEG_"
private const val PHOTO_FORMAT = ".jpg"
}
Try and see, it should work.
Did you grant Camera permission into your WebView's WebChromeClient?
Please add camera permission into your AndroidManifest.xml.
<uses-permission android:name="android.permission.CAMERA" />
<uses-permission android:name="android.permission.CAMERA2" />
Set WebChromeClient into your WebView.
webView.setWebChromeClient(new ChromeClient())
Define the your ChromeClient class.
public class ChromeClient extends WebChromeClient {
#Override
public boolean onShowFileChooser(WebView view, ValueCallback<Uri[]> filePath, WebChromeClient.FileChooserParams fileChooserParams) {
if (!hasPermissions(MainActivity.this, PERMISSIONS)) {
checkStoragePermission();
return false;
}
// Double check that we don't have any existing callbacks
if (mFilePathCallback != null) {
mFilePathCallback.onReceiveValue(null);
}
mFilePathCallback = filePath;
Intent takePictureIntent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
if (takePictureIntent.resolveActivity(getPackageManager()) != null) {
// Create the File where the photo should go
File photoFile = createImageFile();
takePictureIntent.putExtra("PhotoPath", mCameraPhotoPath);
// Continue only if the File was successfully created
if (photoFile != null) {
mCameraPhotoPath = "file:" + photoFile.getAbsolutePath();
takePictureIntent.putExtra(MediaStore.EXTRA_OUTPUT,
Uri.fromFile(photoFile));
} else {
takePictureIntent = null;
}
}
Intent contentSelectionIntent = new Intent(Intent.ACTION_GET_CONTENT);
contentSelectionIntent.addCategory(Intent.CATEGORY_OPENABLE);
contentSelectionIntent.setType("image/*");
Intent[] intentArray;
if (takePictureIntent != null) {
intentArray = new Intent[]{takePictureIntent};
} else {
intentArray = new Intent[0];
}
Intent chooserIntent = new Intent(Intent.ACTION_CHOOSER);
chooserIntent.putExtra(Intent.EXTRA_INTENT, contentSelectionIntent);
chooserIntent.putExtra(Intent.EXTRA_TITLE, "Select Photo");
chooserIntent.putExtra(Intent.EXTRA_INITIAL_INTENTS, intentArray);
startActivityForResult(chooserIntent, Constant.INPUT_FILE_REQUEST_CODE);
return true;
}
}
Here are variables.
String[] PERMISSIONS = {
Manifest.permission.CAMERA,
Manifest.permission.WRITE_EXTERNAL_STORAGE
};
private ValueCallback<Uri[]> mFilePathCallback;
private String mCameraPhotoPath;
Check the storage and camera permission.
private void checkStoragePermission() {
String permission = Manifest.permission.WRITE_EXTERNAL_STORAGE;
if (ContextCompat.checkSelfPermission(this, permission) != PackageManager.PERMISSION_GRANTED) {
ActivityCompat.requestPermissions(MainActivity.this, new String[]{permission}, Constant.REQUEST_STORAGE_PERMISSION);
} else {
checkCameraPermission();
}
}
private void checkCameraPermission() {
String permission = Manifest.permission.CAMERA;
if (ContextCompat.checkSelfPermission(this, permission) != PackageManager.PERMISSION_GRANTED) {
ActivityCompat.requestPermissions(MainActivity.this, new String[]{permission}, Constant.REQUEST_CAMERA_PERMISSION);
} else {
onPermissionGranted();
}
}
After that, I can access to camera and gallery.
Hope it to be helpful.
For Android 10, SDK 30
Add android:requestLegacyExternalStorage="true" in application tag in manifest
https://stackoverflow.com/a/65415381/7775500
this might help you ..
Surely you need the permissions to open the camera on android.
Edit the manifest like this:
<uses-permission android:name="android.permission.CAMERA" />
You might also need a library not included
I also had this problem too. I will share it with others who are likely to have this problem in the future.
You must have the camera permission in the manifest and grant it in the onPermissionRequest methode in your WebChromeClient and be sure to set setMediaPlaybackRequiresUserGesture to false in the webView setting.
Add this permission:
<uses-permission android:name="android.permission.CAMERA" />
Add this in webView setting:
binding.webView.getSettings().setMediaPlaybackRequiresUserGesture(false);
And grant the permission in onPermissionRequest methode:
#Override
public void onPermissionRequest(final PermissionRequest request) {
final String[] requestedResources = request.getResources();
request.grant(requestedResources);
}
for more information see this link:
StackOverFlow solution

Categories

Resources