I want to upload image on server using Volley Library - kotlin

I'm selecting the image from my phone gallery and want to upload image on server but my app crash every time i don't know the reason.. i already study many tutorials and Question but i did not understand. please help me.
Here is my code
class profileCreate : AppCompatActivity() {
var context: Context? = null
var imageUri: Uri? = null
var picturePath: String? = null
val url = "https://apps.faizeqamar.website/charity/api/donnor_add"
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_profile_create)
val et_name = findViewById<EditText>(R.id.et_name)
val et_cnic = findViewById<EditText>(R.id.et_cnic)
val et_email = findViewById<EditText>(R.id.et_email)
val et_phon = findViewById<EditText>(R.id.et_phon)
val et_address = findViewById<EditText>(R.id.et_address)
val profile_image = findViewById<ImageView>(R.id.profile_image)
profile_image.setOnClickListener {
checkPermission()
}
val btn_create_profile = findViewById<Button>(R.id.btn_create_profile)
btn_create_profile.setOnClickListener {
imageUpload()
}
}
Volley Code
private fun imageUpload() {
val smr =
SimpleMultiPartRequest(
Request.Method.POST, url,
Response.Listener { response ->
Log.d("Response", response)
Toast.makeText(
applicationContext,
"xyz",
Toast.LENGTH_LONG
).show()
}, Response.ErrorListener { error ->
Toast.makeText(
applicationContext,
error.message,
Toast.LENGTH_LONG
).show()
})
var fname = et_name.text.toString()
var cnic = et_cnic.text.toString()
var email = et_email.text.toString()
var phone = et_phon.text.toString()
var address = et_address.text.toString()
smr.addFile("user_image", picturePath)
smr.addStringParam("fname", fname)
smr.addStringParam("cnic", cnic)
smr.addStringParam("email", email)
smr.addStringParam("phone", phone)
smr.addStringParam("address", address)
val mRequestQueue = Volley.newRequestQueue(applicationContext)
mRequestQueue.add(smr)
}
Pick Image from phone
//*********pick image from phone************
var READIMAGE: Int = 253
fun checkPermission() {
if (Build.VERSION.SDK_INT >= 23) {
if (ActivityCompat.checkSelfPermission(
this,
android.Manifest.permission.READ_EXTERNAL_STORAGE
) !=
PackageManager.PERMISSION_GRANTED
) {
requestPermissions(
arrayOf(android.Manifest.permission.READ_EXTERNAL_STORAGE),
READIMAGE
)
return
}
}
loadImage()
}
override fun onRequestPermissionsResult(
requestCode: Int,
permissions: Array<out String>,
grantResults: IntArray
) {
when (requestCode) {
READIMAGE -> {
if (grantResults[0] == PackageManager.PERMISSION_GRANTED) {
loadImage()
} else {
Toast.makeText(
applicationContext,
"cannot access your images",
Toast.LENGTH_LONG
).show()
}
}
else -> super.onRequestPermissionsResult(requestCode, permissions, grantResults)
}
}
val PICK_IMAGE_CODE = 123
fun loadImage() {
var intent = Intent(
Intent.ACTION_PICK,
MediaStore.Images.Media.EXTERNAL_CONTENT_URI
)
startActivityForResult(intent, PICK_IMAGE_CODE)
}
override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
super.onActivityResult(requestCode, resultCode, data)
if (requestCode == PICK_IMAGE_CODE && data != null && resultCode == RESULT_OK) {
imageUri = data.data
val filePathColum = arrayOf(MediaStore.Images.Media.DATA)
val cursor = contentResolver.query(imageUri!!, filePathColum, null, null, null)
cursor!!.moveToFirst()
val columnIndex = cursor.getColumnIndex(filePathColum[0])
picturePath = cursor.getString(columnIndex)
cursor.close()
profile_image?.setImageBitmap(BitmapFactory.decodeFile(picturePath))
}
}
}

Encode your image to string and send to the server like sending strings
change your onACtivityresult as below
override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
super.onActivityResult(requestCode, resultCode, data)
try {
if (requestCode == PICK_IMAGE_CODE && data != null && resultCode == RESULT_OK) {
val contentURI = data!!.data
try {
logBitmap = MediaStore.Images.Media.getBitmap(this.contentResolver, contentURI)
encodedImgString = getStringImage(logBitmap!!)
profile_image!!.setImageBitmap(logBitmap)
} catch (e: IOException) {
e.printStackTrace()
Toast.makeText(this, "Failed!", Toast.LENGTH_SHORT).show()
}
}else if (requestCode== IMAGE_CAPTURE_CODE){
img_logo.setImageURI(image_uri)
}
} catch (e: Exception) {
e.printStackTrace()
}
}
here is the getStringImage function
private fun getStringImage(bmp: Bitmap): String {
val baos = ByteArrayOutputStream()
bmp.compress(Bitmap.CompressFormat.JPEG, 100, baos)
val imageBytes = baos.toByteArray()
return Base64.encodeToString(imageBytes, Base64.DEFAULT)
}
You can send the encodedImgString to the server and decode from there

Related

Error While Upload Image From Galley Using Drjacky Image Picker And Retrofit 2

hi guys I got an error like the one below when trying to upload an image from the galley:
java.lang.SecurityException: Permission Denial: opening provider com.android.providers.media.MediaDocumentsProvider from ProcessRecord{efed650 15275:app.fadlyproject.com/u0a158} (pid=15275, uid=10158) requires that you obtain access using ACTION_OPEN_DOCUMENT or related APIs
the error comes from this line of code:
val parcelFileDescriptor =
contentResolver.openFileDescriptor(selectedImageUri!!, "r", null) ?: return
I'm using 3rd party libraries namely DrJacky and Retrofit 2. I've added some necessary things to the manifest as below:
Dependencies :
implementation 'com.squareup.retrofit2:retrofit:2.9.0'
implementation 'com.squareup.retrofit2:converter-gson:2.9.0'
implementation 'com.github.Drjacky:ImagePicker:2.3.19'
Manifest :
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
image_view = findViewById(R.id.image_view)
button_upload = findViewById(R.id.button_upload)
image_view!!.setOnClickListener {
openImageChooser()
}
button_upload!!.setOnClickListener {
uploadImage()
}
}
private val profileLauncher =
registerForActivityResult(ActivityResultContracts.StartActivityForResult()) {
if (it.resultCode == Activity.RESULT_OK) {
val uri = it.data?.data!!
selectedImageUri = uri
image_view!!.setImageURI(selectedImageUri)
} else parseError(it)
}
private fun openImageChooser() {
ImagePicker.with(this)
.provider(ImageProvider.BOTH)
.setDismissListener {
Log.d("ImagePicker", "onDismiss");
}
.createIntentFromDialog { profileLauncher.launch(it) }
}
override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
super.onActivityResult(requestCode, resultCode, data)
if (resultCode == Activity.RESULT_OK) {
when (requestCode) {
REQUEST_CODE_PICK_IMAGE -> {
selectedImageUri = data?.data
image_view!!.setImageURI(selectedImageUri)
}
}
}
}
private fun uploadImage() {
if (selectedImageUri == null) {
layout_root!!.snackbar("Select an Image First")
return
}
val parcelFileDescriptor =
contentResolver.openFileDescriptor(selectedImageUri!!, "r", null) ?: return
val inputStream = FileInputStream(parcelFileDescriptor.fileDescriptor)
val file = File(cacheDir, contentResolver.getFileName(selectedImageUri!!))
val outputStream = FileOutputStream(file)
inputStream.copyTo(outputStream)
progress_bar!!.progress = 0
val body = UploadRequestBody(file, "image", this)
MyAPI().uploadImage(
MultipartBody.Part.createFormData(
"file",
file.name,
body
),
RequestBody.create(MediaType.parse("multipart/form-data"), "json")
).enqueue(object : Callback<UploadResponse> {
override fun onFailure(call: Call<UploadResponse>, t: Throwable) {
layout_root!!.snackbar(t.message!!)
progress_bar!!.progress = 0
}
override fun onResponse(
call: Call<UploadResponse>,
response: Response<UploadResponse>
) {
response.body()?.let {
layout_root!!.snackbar(it.message)
progress_bar!!.progress = 100
classes!!.text = it.data.classes
layout!!.visibility = View.VISIBLE
Glide.with(this#MainActivity).load("http://167.172.72.26:1337/"+ it.data.image_after_preprocessing).into(
image_view!!
)
}
}
})
}
override fun onProgressUpdate(percentage: Int) {
progress_bar!!.progress = percentage
}
companion object {
const val REQUEST_CODE_PICK_IMAGE = 101
}
This answer is late but it might help others.
I just added .crop() to it like this.
ImagePicker.with(this)
.crop()
.provider(ImageProvider.BOTH)
.setDismissListener {
Log.d("ImagePicker", "onDismiss");
}
.createIntentFromDialog { profileLauncher.launch(it) }
I noticed that the error only persist when using the gallery and adding the .crop() is the only solution to it.
In case you don't use Crop option, you just need to add:
mGalleryUri?.let { galleryUri ->
contentResolver.takePersistableUriPermission(
galleryUri, Intent.FLAG_GRANT_READ_URI_PERMISSION
)
}
https://developer.android.com/training/data-storage/shared/photopicker#persist-media-file-access
I'll change ACTION_GET_CONTENT to ACTION_OPEN_DOCUMENT on the next update.
[And if I could find a way to have both worlds(having crop and let developer use or not use takePersistableUriPermission, I'll update again.]

RecyclerView and OnItemClick: No value passed for parameter 'click' in Fragment

I'm trying to implement an OnClick listener for specific items in a recyclerview. I've done it before with activities, but now I want to do this in a fragment and I've run into a problem. I'm getting the error No value passed for parameter 'click'. This is the line of code that gives that error:
recyclerAdapterAbstract = abstractList.let {AbstractAdapter(requireActivity(),it)}
This the only error Android Studio is currently showing me. The logcat doesn't show any error. Only the Build Output shows what's wrong and it's exactly what I said earlier
Fragment Class
#Suppress("UNREACHABLE_CODE")
class AbstractWallpapers: Fragment(), PurchasesUpdatedListener, AbstractAdapter.OnItemClickListenerAbstract {
private lateinit var subscribeAbstract: Button
private var billingClient: BillingClient? = null
lateinit var recyclerView: RecyclerView
lateinit var abstractList: ArrayList<Abstract>
private var recyclerAdapterAbstract: AbstractAdapter? = null
private var myRef3: DatabaseReference? = null
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
return inflater.inflate(R.layout.fragment_abstract_wallpaper, container, false)
recyclerView = requireActivity().findViewById(R.id.abstract_recyclerView)
}
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
recyclerView = view.findViewById(R.id.abstract_recyclerView)
val layoutManager = GridLayoutManager(requireContext(), 2)
recyclerView.layoutManager = layoutManager
recyclerView.setHasFixedSize(true)
myRef3 = FirebaseDatabase.getInstance().reference
abstractList = ArrayList()
ClearAll()
GetDataFromFirebase()
subscribeAbstract = view.findViewById(R.id.abstract_subscribe_btn)
subscribeAbstract.setOnClickListener {
subscribeAbstract()
}
//Establish connection to billing client
//check subscription status from google play store cache
//to check if item is already Subscribed or subscription is not renewed and cancelled
billingClient = BillingClient.newBuilder(requireActivity()).enablePendingPurchases().setListener(this).build()
billingClient!!.startConnection(object : BillingClientStateListener {
override fun onBillingSetupFinished(billingResult: BillingResult) {
if (billingResult.responseCode == BillingClient.BillingResponseCode.OK) {
val queryPurchase = billingClient!!.queryPurchases(BillingClient.SkuType.SUBS)
val queryPurchases = queryPurchase.purchasesList
if (queryPurchases != null && queryPurchases.size > 0) {
handlePurchases(queryPurchases)
} else {
saveSubscribeValueToPref(false)
}
}
}
override fun onBillingServiceDisconnected() {
Toast.makeText(requireActivity(), "Service Disconnected", Toast.LENGTH_SHORT).show()
}
})
//item subscribed
if (subscribeValueFromPref) {
subscribeAbstract.visibility = View.GONE
} else {
subscribeAbstract.visibility = View.VISIBLE
}
}
// Code relating to my Firebase storage
#SuppressLint("NotifyDataSetChanged")
private fun GetDataFromFirebase() {
val query: Query = myRef3!!.child("Abstract")
query.addListenerForSingleValueEvent(object : ValueEventListener {
override fun onDataChange(snapshot: DataSnapshot) {
for (dataSnapshot: DataSnapshot in snapshot.children) {
val abstract = Abstract()
abstract.abstract = dataSnapshot.child("abstract").value.toString()
abstractList.add(abstract)}
recyclerAdapterAbstract = abstractList.let {AbstractAdapter(requireActivity(),it)}
recyclerView.adapter = recyclerAdapterAbstract
recyclerAdapterAbstract!!.notifyDataSetChanged()
}
override fun onCancelled(error: DatabaseError) {}
})
if (recyclerAdapterAbstract != null) recyclerAdapterAbstract!!.notifyDataSetChanged()
}
private fun ClearAll() {
abstractList.clear()
abstractList = ArrayList()
}
private val preferenceObject: SharedPreferences
get() = requireActivity().getSharedPreferences(PREF_FILE, 0)
private val preferenceEditObject: SharedPreferences.Editor
get() {
val pref = requireActivity().getSharedPreferences(PREF_FILE, 0)
return pref.edit()
}
private val subscribeValueFromPref: Boolean
get() = preferenceObject.getBoolean(SUBSCRIBE_KEY, false)
private fun saveSubscribeValueToPref(value: Boolean) {
preferenceEditObject.putBoolean(SUBSCRIBE_KEY, value).commit()
}
//initiate purchase on button click
fun subscribeAbstract() {
//check if service is already connected
if (billingClient!!.isReady) {
initiatePurchase()
} else {
billingClient = BillingClient.newBuilder(requireActivity()).enablePendingPurchases().setListener(this).build()
billingClient!!.startConnection(object : BillingClientStateListener {
override fun onBillingSetupFinished(billingResult: BillingResult) {
if (billingResult.responseCode == BillingClient.BillingResponseCode.OK) {
initiatePurchase()
} else {
Toast.makeText(requireActivity(), "Error " + billingResult.debugMessage, Toast.LENGTH_SHORT).show()
}
}
override fun onBillingServiceDisconnected() {
Toast.makeText(requireActivity(), "Service Disconnected ", Toast.LENGTH_SHORT).show()
}
})
}
}
private fun initiatePurchase() {
val skuList: MutableList<String> = ArrayList()
skuList.add(ITEM_SKU_SUBSCRIBE)
val params = SkuDetailsParams.newBuilder()
params.setSkusList(skuList).setType(BillingClient.SkuType.SUBS)
val billingResult = billingClient!!.isFeatureSupported(BillingClient.FeatureType.SUBSCRIPTIONS)
if (billingResult.responseCode == BillingClient.BillingResponseCode.OK) {
billingClient!!.querySkuDetailsAsync(params.build()
) { billingResult, skuDetailsList ->
if (billingResult.responseCode == BillingClient.BillingResponseCode.OK) {
if (skuDetailsList != null && skuDetailsList.size > 0) {
val flowParams = BillingFlowParams.newBuilder()
.setSkuDetails(skuDetailsList[0])
.build()
billingClient!!.launchBillingFlow(requireActivity(), flowParams)
} else {
//try to add subscription item "sub_example" in google play console
Toast.makeText(requireActivity(), "Item not Found", Toast.LENGTH_SHORT).show()
}
} else {
Toast.makeText(requireActivity(),
" Error " + billingResult.debugMessage, Toast.LENGTH_SHORT).show()
}
}
} else {
Toast.makeText(requireActivity(),
"Sorry Subscription not Supported. Please Update Play Store", Toast.LENGTH_SHORT).show()
}
}
override fun onPurchasesUpdated(billingResult: BillingResult, purchases: List<Purchase>?) {
//if item subscribed
if (billingResult.responseCode == BillingClient.BillingResponseCode.OK && purchases != null) {
handlePurchases(purchases)
}
else if (billingResult.responseCode == BillingClient.BillingResponseCode.ITEM_ALREADY_OWNED) {
val queryAlreadyPurchasesResult = billingClient!!.queryPurchases(BillingClient.SkuType.SUBS)
val alreadyPurchases = queryAlreadyPurchasesResult.purchasesList
alreadyPurchases?.let { handlePurchases(it) }
}
else if (billingResult.responseCode == BillingClient.BillingResponseCode.USER_CANCELED) {
Toast.makeText(requireActivity(), "Purchase Canceled", Toast.LENGTH_SHORT).show()
}
else {
Toast.makeText(requireActivity(), "Error " + billingResult.debugMessage, Toast.LENGTH_SHORT).show()
}
}
fun handlePurchases(purchases: List<Purchase>) {
for (purchase in purchases) {
//if item is purchased
if (ITEM_SKU_SUBSCRIBE == purchase.sku && purchase.purchaseState == Purchase.PurchaseState.PURCHASED) {
if (!verifyValidSignature(purchase.originalJson, purchase.signature)) {
// Invalid purchase
// show error to user
Toast.makeText(requireActivity(), "Error : invalid Purchase", Toast.LENGTH_SHORT).show()
return
}
// else purchase is valid
//if item is purchased and not acknowledged
if (!purchase.isAcknowledged) {
val acknowledgePurchaseParams = AcknowledgePurchaseParams.newBuilder()
.setPurchaseToken(purchase.purchaseToken)
.build()
billingClient!!.acknowledgePurchase(acknowledgePurchaseParams, ackPurchase)
} else {
// Grant entitlement to the user on item purchase
// restart activity
if (!subscribeValueFromPref) {
saveSubscribeValueToPref(true)
Toast.makeText(requireActivity(), "Item Purchased", Toast.LENGTH_SHORT).show()
recreate(requireActivity())
}
}
} else if (ITEM_SKU_SUBSCRIBE == purchase.sku && purchase.purchaseState == Purchase.PurchaseState.PENDING) {
Toast.makeText(requireActivity(),
"Purchase is Pending. Please complete Transaction", Toast.LENGTH_SHORT).show()
} else if (ITEM_SKU_SUBSCRIBE == purchase.sku && purchase.purchaseState == Purchase.PurchaseState.UNSPECIFIED_STATE) {
saveSubscribeValueToPref(false)
subscribeAbstract.visibility = View.VISIBLE
Toast.makeText(requireActivity(), "Purchase Status Unknown", Toast.LENGTH_SHORT).show()
}
}
}
var ackPurchase = AcknowledgePurchaseResponseListener { billingResult ->
if (billingResult.responseCode == BillingClient.BillingResponseCode.OK) {
//if purchase is acknowledged
// Grant entitlement to the user. and restart activity
saveSubscribeValueToPref(true)
recreate(requireActivity())
}
}
/**
* Verifies that the purchase was signed correctly for this developer's public key.
*
* Note: It's strongly recommended to perform such check on your backend since hackers can
* replace this method with "constant true" if they decompile/rebuild your app.
*
*/
private fun verifyValidSignature(signedData: String, signature: String): Boolean {
return try {
// To get key go to Developer Console > Select your app > Development Tools > Services & APIs.
val base64Key = "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAhBlajrk5nNjpRTPJjDtGxgtgAeKijz3Wc0KrRKKSCxxsViHl7DhsI+sUZfk4Y1jxSg4/3W1uRo/0UASM77XfJIq34bK9KYgoSAGYSuH8Z+4fK/MrPz7dHhsljkAi4GZkv8x9VhZdDdpn2GSHVFaxs8c+HBOFp9aWAErHrQhi9/7fYf39pQSTC3WkVcy9xNDZxiiKTfDN3dyEvS0XQ617ZJwqDuRdkU5Aw9+R8r+oXyURV/ekgCQkWfCUaTp/jWdySOIcR87Bde24lQAXbvJaL5uAYI4zPwO4sIP1AbXLuDtv3N2rFVmP/1cML/NHDcfI5FOoStz88jzJU26Ngpqu1QIDAQAB"
Security.verifyPurchase(base64Key, signedData, signature)
} catch (e: IOException) {
false
}
}
override fun onDestroy() {
super.onDestroy()
if (billingClient != null) {
billingClient!!.endConnection()
}
}
companion object {
const val PREF_FILE = "MyPref"
const val SUBSCRIBE_KEY = "subscribe"
const val ITEM_SKU_SUBSCRIBE = "abstract_wallpapers"
}
override fun onItemClick(item: String) {
}
}
Adapter class
class AbstractAdapter(private val mContext: Context, private val abstractList: ArrayList<Abstract>, private val click: OnItemClickListenerAbstract ) :
RecyclerView.Adapter<AbstractAdapter.ViewHolder>() {
interface OnItemClickListenerAbstract{
fun onItemClick(item:String)
}
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder {
val view = LayoutInflater.from(parent.context).inflate(R.layout.abstract_image_view, parent, false)
return ViewHolder(view)
}
override fun onBindViewHolder(holder: ViewHolder, position: Int) {
Glide.with(mContext)
.load(abstractList[position].abstract)
.into(holder.imageView)
holder.imageView.setOnClickListener {
val intent = Intent(mContext, AbstractPreview::class.java)
intent.putExtra("abstract", abstractList[position].abstract.toString())
Toast.makeText(mContext, "Fullscreen view", Toast.LENGTH_SHORT).show()
mContext.startActivity(intent)
}
holder.downloadBtn.setOnClickListener {
abstractList.get(position).abstract?.let { it1 -> click.onItemClick(it1) }
}
}
override fun getItemCount(): Int {
return abstractList.size
}
class ViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) {
val imageView: ImageView = itemView.findViewById(R.id.abstractImageView)
val downloadBtn: Button = itemView.findViewById(R.id.abstractDownloadBtn)
}
companion object
}
You have 3 parameters for the class AbstractAdapter
class AbstractAdapter(private val mContext: Context, private val abstractList: ArrayList<Abstract>, private val click: OnItemClickListenerAbstract )
but you are instantiating the object with only two parameters
AbstractAdapter(requireActivity(),it)
It's expecting the third parameter for the clickListener
AbstractAdapter(requireActivity(),it,this)
(send the Fragment as the third param)

Scanning with ML Firebase Barcode doesn't recognize format

I have been trying to use the MLKit to scan a barcode however I don't seem to get anything on return, the info that I'm getting back is
W/libc: Access denied finding property "ro.hardware.chipname"
This is the code that I'm trying, it does enter in the success listener however I doesn't seem to recognize the format.
private fun scanBarcodes(bitmap: Bitmap) {
val options = BarcodeScannerOptions.Builder()
.setBarcodeFormats(
Barcode.FORMAT_CODABAR,
Barcode.FORMAT_UPC_A,
Barcode.FORMAT_UPC_E
)
.build()
val scanner = BarcodeScanning.getClient(options)
val image = InputImage.fromBitmap(bitmap, 0)
scanner.process(image)
.addOnSuccessListener { barcodes ->
// It is succesful
for (barcode in barcodes) {
val bounds = barcode.boundingBox
val corners = barcode.cornerPoints
val rawValue = barcode.rawValue
Log.d("RAWVALUE ->>>", rawValue.toString())
when (barcode.valueType) {
Barcode.FORMAT_UPC_A -> {
Log.d("TASK SUCCESFUL ->>>>>>", "UPC A")
val upc = barcode.url
}
Barcode.FORMAT_UPC_E -> {
Log.d("TASK SUCCESFUL ->>>>>>", "UPC E")
}
Barcode.FORMAT_CODABAR -> {
val title = barcode.url!!.title
val url = barcode.url!!.url
}
}
}
}
.addOnFailureListener {
Log.d(TAG, "Problem")
}
}
The BitMap that I'm passing the scanBarcodes function is the one obtained underneath
override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
super.onActivityResult(requestCode, resultCode, data)
if (requestCode == 100 && resultCode == RESULT_OK) {
imageUri = data?.data!!
if (binding.switchCamera?.isChecked == true)
Picasso.get()!!.load(imageUri).resize(300, 300).centerCrop()
.into(binding.imageButton)
}
if (requestCode == cameraCode && resultCode == RESULT_OK) {
imageBitmap = data?.extras?.get("data") as Bitmap
val baos = ByteArrayOutputStream()
imageBitmap.compress(Bitmap.CompressFormat.JPEG, 100, baos)
data2 = baos.toByteArray()
val file = File(cacheDir, "filename.jpg")
file.createNewFile()
val fileOS = FileOutputStream(file)
fileOS.write(data2)
fileOS.flush()
fileOS.close()
if (binding.switchCamera?.isChecked == true) {
binding.imageButton.setImageBitmap(imageBitmap)
} else {
scanBarcodes(imageBitmap)
}
}
}

Choose file in external storage and get path

i know this question has been asked several times but everything i can find is only in Java and not very relevant to me...
I'm trying to select a file when i click on a button in my app (images or videos like : /storage/emulated/0/Download/giphy.gif ) and the when the picture or video is selected, i need the path to go inside an edittext.
I have found that code in kotlin for path :
class URIPathHelper {
fun getPath(context: Context, uri: Uri): String? {
val isKitKatorAbove = true
// DocumentProvider
if (isKitKatorAbove && DocumentsContract.isDocumentUri(context, uri)) {
// ExternalStorageProvider
if (isExternalStorageDocument(uri)) {
val docId = DocumentsContract.getDocumentId(uri)
val split = docId.split(":".toRegex()).toTypedArray()
val type = split[0]
if ("primary".equals(type, ignoreCase = true)) {
return Environment.getExternalStorageDirectory().toString() + "/" + split[1]
}
} else if (isDownloadsDocument(uri)) {
val id = DocumentsContract.getDocumentId(uri)
val contentUri = ContentUris.withAppendedId(Uri.parse("content://downloads/public_downloads"), java.lang.Long.valueOf(id))
return getDataColumn(context, contentUri, null, null)
} else if (isMediaDocument(uri)) {
val docId = DocumentsContract.getDocumentId(uri)
val split = docId.split(":".toRegex()).toTypedArray()
val type = split[0]
var contentUri: Uri? = null
if ("image" == type) {
contentUri = MediaStore.Images.Media.EXTERNAL_CONTENT_URI
} else if ("video" == type) {
contentUri = MediaStore.Video.Media.EXTERNAL_CONTENT_URI
} else if ("audio" == type) {
contentUri = MediaStore.Audio.Media.EXTERNAL_CONTENT_URI
}
val selection = "_id=?"
val selectionArgs = arrayOf(split[1])
return getDataColumn(context, contentUri, selection, selectionArgs)
}
} else if ("content".equals(uri.scheme, ignoreCase = true)) {
return getDataColumn(context, uri, null, null)
} else if ("file".equals(uri.scheme, ignoreCase = true)) {
return uri.path
}
return null
}
fun getDataColumn(context: Context, uri: Uri?, selection: String?, selectionArgs: Array<String>?): String? {
var cursor: Cursor? = null
val column = "_data"
val projection = arrayOf(column)
try {
cursor = uri?.let { context.getContentResolver().query(it, projection, selection, selectionArgs,null) }
if (cursor != null && cursor.moveToFirst()) {
val column_index: Int = cursor.getColumnIndexOrThrow(column)
return cursor.getString(column_index)
}
} finally {
if (cursor != null) cursor.close()
}
return null
}
fun isExternalStorageDocument(uri: Uri): Boolean {
return "com.android.externalstorage.documents" == uri.authority
}
fun isDownloadsDocument(uri: Uri): Boolean {
return "com.android.providers.downloads.documents" == uri.authority
}
fun isMediaDocument(uri: Uri): Boolean {
return "com.android.providers.media.documents" == uri.authority
}
}
And this is what i'm trying :
binding.redloader.setOnClickListener {
val uriPathHelper = URIPathHelper()
val filePath: String? = uriPathHelper.getPath(this, MediaStore.Images.Media.EXTERNAL_CONTENT_URI)
val uri: Uri = Uri.parse(filePath)
val intent = Intent(Intent.ACTION_VIEW)
intent.type = "image/*"
intent.putExtra(Intent.ACTION_VIEW, uri)
startActivity(Intent.createChooser(intent, "Open file"))
binding.redgif.setText(filePath)
}
When I click on the button it automatically chooses the first picture in the storage, and then it opens google picture but I cannot do anything except watch the pictures...
I'm sorry I know they are some stupid things in my code, I think I have something to do with intent but all I see on the internet is calling private void and it is not working for me...
I'm a complete beginner and I really hope someone can help me...
Update with what i'm trying, i think i'm close :
binding.redloader.setOnClickListener {
val uriPathHelper = URIPathHelper()
intent = Intent(Intent.ACTION_GET_CONTENT)
intent.type = "image/*"
intent.addCategory(Intent.CATEGORY_OPENABLE)
intent = Intent.createChooser(intent, "Choose a file")
val resultLauncher =
registerForActivityResult(ActivityResultContracts.StartActivityForResult()) { result ->
if (result.resultCode == Activity.RESULT_OK) {
val data: Intent? = result.data
if (data != null) {
val fileUri: Uri? = data.data
Log.i(LOG_TAG, fileUri.toString())
var fileURIPathHelper: String? = null
try {
fileURIPathHelper = uriPathHelper.getPath(this, EXTERNAL_CONTENT_URI)
} catch (e: Exception) {
Log.e(LOG_TAG, "Error: " + e)
Toast.makeText(this, "Error: " + e, Toast.LENGTH_SHORT).show()
}
this.binding.redgif.setText(fileURIPathHelper)
}
}
}
resultLauncher.launch(intent)
}
I solved it ! :)
val resultLauncher =
registerForActivityResult(ActivityResultContracts.StartActivityForResult()) { result ->
if (result.resultCode == Activity.RESULT_OK) {
val data: Intent? = result.data
if (data != null) {
val fileUri: Uri? = data.data
Log.i(PackageManagerCompat.LOG_TAG, fileUri.toString())
val contentUri: String?
try {
contentUri = uriPathHelper.getPath(this, fileUri!!)
this.binding.redgif.setText(contentUri)
} catch (e: Exception) {
Log.e(PackageManagerCompat.LOG_TAG, "Error: " + e)
Toast.makeText(this, "Error: " + e, Toast.LENGTH_SHORT).show()
}
}
}
}
binding.redloader.setOnClickListener {
val intent = Intent(Intent.ACTION_GET_CONTENT)
intent.type = "image/*"
intent.addCategory(Intent.CATEGORY_OPENABLE)
startActivity(Intent.createChooser(intent, "Open file"))
resultLauncher.launch(intent)
}

how do i get downloadurl from below code?

Below is the code I checked and it did not work.
I did get not url but get "com.google.android.gms.tasks.zzu#ffbfff5"
I think
val url=taskSnapshot.getMetadata()?.getReference()?.getDownloadUrl()?.toString()
should be amended but I dont know how to fix.
override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
if (requestCode == PICK_PROFILE_FROM_ALBUM && resultCode == Activity.RESULT_OK) {
var imageUri = data?.data
val uid = FirebaseAuth.getInstance().currentUser!!.uid
FirebaseStorage
.getInstance()
.reference
.child("userProfileImages")
.child(uid)
.putFile(imageUri!!)
.addOnSuccessListener { taskSnapshot ->
val url = taskSnapshot.getMetadata()?.getReference()?.getDownloadUrl()?.toString()
val map = HashMap<String, Any>()
map["image"] = url
FirebaseFirestore.getInstance().collection("profileImages").document(uid).set(map)
}
}
}
}