I have a cartActivity and when I click the proceed button it goes to PaymentActivity. Now, If I click baack button from the paymentActivity I want to go back to the CartActivity.
CartActivity
class CartActivity : AppCompatActivity() {
lateinit var toolbar: androidx.appcompat.widget.Toolbar
lateinit var txtOrderingFrom: TextView
lateinit var btnPlaceOrder: Button
lateinit var recyclerView: RecyclerView
lateinit var layoutManager: RecyclerView.LayoutManager
lateinit var menuAdapter: CartAdapter
lateinit var restaurantId: String
lateinit var restaurantName: String
lateinit var selectedItemsId: ArrayList<String>
lateinit var linearLayout: LinearLayout
lateinit var cartProgressLayout: RelativeLayout
var totalAmount = 0
var cartListItems = arrayListOf<CartItems>()
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_cart)
btnPlaceOrder = findViewById(R.id.btnPlaceOrder)
txtOrderingFrom = findViewById(R.id.txtOrderingFrom)
linearLayout = findViewById(R.id.linearLayout)
toolbar = findViewById(R.id.toolBar)
cartProgressLayout = findViewById(R.id.cartProgressLayout)
restaurantId = intent.getStringExtra("restaurantId").toString()
restaurantName = intent.getStringExtra("restaurantName").toString()
selectedItemsId = intent.getStringArrayListExtra("selectedItemsId") as ArrayList<String>
txtOrderingFrom.text = restaurantName
setToolBar()
fetchData()
btnPlaceOrder.setOnClickListener {
val sharedPreferences = this.getSharedPreferences(
getString(R.string.shared_preferences),
Context.MODE_PRIVATE
)
if (ConnectionManager().checkConnectivity(this)) {
cartProgressLayout.visibility = View.VISIBLE
try {
val foodArray = JSONArray()
for (foodItem in selectedItemsId) {
val singleItemObject = JSONObject()
singleItemObject.put("food_item_id", foodItem)
foodArray.put(singleItemObject)
}
val sendOrder = JSONObject()
sendOrder.put("user_id", sharedPreferences.getString("user_id", "0"))
sendOrder.put("restaurant_id", restaurantId)
sendOrder.put("total_cost", totalAmount)
sendOrder.put("food", foodArray)
val queue = Volley.newRequestQueue(this)
val url = "http://13.235.250.119/v2/place_order/fetch_result"
val jsonObjectRequest = object : JsonObjectRequest(
Method.POST,
url,
sendOrder,
Response.Listener {
val response = it.getJSONObject("data")
val success = response.getBoolean("success")
val LAUNCH_SECOND_ACTIVITY = 1
if (success) {
val intent = Intent(this, PaymentActivity::class.java)
intent.putExtra("total_amount",totalAmount)
startActivityForResult(intent,LAUNCH_SECOND_ACTIVITY)
finishAffinity()
} else {
val responseMessageServer =
response.getString("errorMessage")
Toast.makeText(
this,
responseMessageServer.toString(),
Toast.LENGTH_SHORT
).show()
}
cartProgressLayout.visibility = View.INVISIBLE
},
Response.ErrorListener {
Toast.makeText(
this,
"Some Error occurred!!!",
Toast.LENGTH_SHORT
).show()
}) {
override fun getHeaders(): MutableMap<String, String> {
val headers = HashMap<String, String>()
headers["Content-type"] = "application/json"
headers["token"] = "9bf534118365f1"
return headers
}
}
queue.add(jsonObjectRequest)
} catch (e: JSONException) {
Toast.makeText(
this,
"Some unexpected error occurred!!",
Toast.LENGTH_SHORT
).show()
}
} else {
val alterDialog = androidx.appcompat.app.AlertDialog.Builder(this)
alterDialog.setTitle("No Internet")
alterDialog.setMessage("Check Internet Connection!")
alterDialog.setPositiveButton("Open Settings") { _, _ ->
val settingsIntent = Intent(Settings.ACTION_SETTINGS)
startActivity(settingsIntent)
}
alterDialog.setNegativeButton("Exit") { _, _ ->
finishAffinity()
}
alterDialog.setCancelable(false)
alterDialog.create()
alterDialog.show()
}
}
layoutManager = LinearLayoutManager(this)
recyclerView = findViewById(R.id.recyclerViewCart)
}
fun fetchData() {
if (ConnectionManager().checkConnectivity(this)) {
cartProgressLayout.visibility = View.VISIBLE
try {
val queue = Volley.newRequestQueue(this)
val url = "http://13.235.250.119/v2/restaurants/fetch_result/$restaurantId"
val jsonObjectRequest = #SuppressLint("SetTextI18n")
object : JsonObjectRequest(
Method.GET,
url,
null,
Response.Listener {
val response = it.getJSONObject("data")
val success = response.getBoolean("success")
if (success) {
val data = response.getJSONArray("data")
cartListItems.clear()
totalAmount = 0
for (i in 0 until data.length()) {
val cartItem = data.getJSONObject(i)
if (selectedItemsId.contains(cartItem.getString("id"))) {
val menuObject = CartItems(
cartItem.getString("id"),
cartItem.getString("name"),
cartItem.getString("cost_for_one"),
cartItem.getString("restaurant_id")
)
totalAmount += cartItem.getString("cost_for_one").toString()
.toInt()
cartListItems.add(menuObject)
}
menuAdapter = CartAdapter(this, cartListItems)
recyclerView.adapter = menuAdapter
recyclerView.layoutManager = layoutManager
}
btnPlaceOrder.text = "Place Order(Total: Rs. $totalAmount)"
}
cartProgressLayout.visibility = View.INVISIBLE
},
Response.ErrorListener {
Toast.makeText(
this,
"Some Error occurred!!!",
Toast.LENGTH_SHORT
).show()
cartProgressLayout.visibility = View.INVISIBLE
}) {
override fun getHeaders(): MutableMap<String, String> {
val headers = HashMap<String, String>()
headers["Content-type"] = "application/json"
headers["token"] = "26c5144c5b9c13"
return headers
}
}
queue.add(jsonObjectRequest)
} catch (e: JSONException) {
Toast.makeText(
this,
"Some Unexpected error occurred!!!",
Toast.LENGTH_SHORT
).show()
}
} else {
val alterDialog = androidx.appcompat.app.AlertDialog.Builder(this)
alterDialog.setTitle("No Internet")
alterDialog.setMessage("Check Internet Connection!")
alterDialog.setPositiveButton("Open Settings") { _, _ ->
val settingsIntent = Intent(Settings.ACTION_SETTINGS)
startActivity(settingsIntent)
}
alterDialog.setNegativeButton("Exit") { _, _ ->
finishAffinity()
}
alterDialog.setCancelable(false)
alterDialog.create()
alterDialog.show()
}
}
fun setToolBar() {
setSupportActionBar(toolbar)
supportActionBar?.title = "My Cart"
supportActionBar?.setHomeButtonEnabled(true)
supportActionBar?.setDisplayHomeAsUpEnabled(true)
supportActionBar?.setHomeAsUpIndicator(R.drawable.ic_back_arrow)
}
override fun onOptionsItemSelected(item: MenuItem): Boolean {
when (item.itemId) {
android.R.id.home -> {
super.onBackPressed()
}
}
return super.onOptionsItemSelected(item)
}
}
PaymentActivity
class PaymentActivity : AppCompatActivity() {
var amountEt: TextView? = null
var nameEt: TextView? = null
var upiIdEt: TextView? = null
var send: Button? = null
val UPI_PAYMENT = 0
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_payment)
initializeViews()
send?.setOnClickListener {
payUsingUpi("1", "sruthikrithika0#okhdfcbank", "Sruthi")
}
}
fun initializeViews() {
send = findViewById(R.id.send)
amountEt = findViewById(R.id.amount_et)
nameEt = findViewById(R.id.upi_name)
upiIdEt = findViewById(R.id.upi_id)
}
fun payUsingUpi(amount: String?, upiId: String?, name: String?) {
val uri: Uri = Uri.parse("upi://pay").buildUpon()
.appendQueryParameter("pa", upiId)
.appendQueryParameter("pn", name)
.appendQueryParameter("am", amount)
.appendQueryParameter("cu", "INR")
.build()
val upiPayIntent = Intent(Intent.ACTION_VIEW)
upiPayIntent.data = uri
// will always show a dialog to user to choose an app
val chooser = Intent.createChooser(upiPayIntent, "Pay with")
// check if intent resolves
if (null != chooser.resolveActivity(packageManager)) {
startActivityForResult(chooser, UPI_PAYMENT)
} else {
Toast.makeText(
this#PaymentActivity,
"No UPI app found, please install one to continue",
Toast.LENGTH_SHORT
).show()
}
}
override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
super.onActivityResult(requestCode, resultCode, data)
when (requestCode) {
UPI_PAYMENT -> if (RESULT_OK == resultCode || resultCode == 11) {
if (data != null) {
val trxt = data.getStringExtra("response")
Log.d("UPI", "onActivityResult: $trxt")
val dataList: ArrayList<String?> = ArrayList()
dataList.add(trxt)
upiPaymentDataOperation(dataList)
} else {
Log.d("UPI", "onActivityResult: " + "Return data is null")
val dataList: ArrayList<String?> = ArrayList()
dataList.add("nothing")
upiPaymentDataOperation(dataList)
}
} else {
Log.d(
"UPI",
"onActivityResult: " + "Return data is null"
) //when user simply back without payment
val dataList: ArrayList<String?> = ArrayList()
dataList.add("nothing")
upiPaymentDataOperation(dataList)
}
}
}
private fun upiPaymentDataOperation(data: ArrayList<String?>) {
if (isConnectionAvailable(this#PaymentActivity)) {
var str = data[0]
Log.d("UPIPAY", "upiPaymentDataOperation: $str")
var paymentCancel = ""
if (str == null) str = "discard"
var status = ""
var approvalRefNo = ""
val response = str.split("&").toTypedArray()
for (i in response.indices) {
val equalStr = response[i].split("=").toTypedArray()
if (equalStr.size >= 2) {
if (equalStr[0].toLowerCase() == "Status".toLowerCase()) {
status = equalStr[1].toLowerCase()
} else if (equalStr[0].toLowerCase() == "ApprovalRefNo".toLowerCase() || equalStr[0].toLowerCase() == "txnRef".toLowerCase()) {
approvalRefNo = equalStr[1]
}
} else {
paymentCancel = "Payment cancelled by user."
}
}
if (status == "success") {
//Code to handle successful transaction here.
Toast.makeText(this#PaymentActivity, "Transaction successful.", Toast.LENGTH_SHORT)
.show()
Log.d("UPI", "responseStr: $approvalRefNo")
} else if ("Payment cancelled by user." == paymentCancel) {
Toast.makeText(this#PaymentActivity, "Payment cancelled by user.", Toast.LENGTH_SHORT)
.show()
} else {
Toast.makeText(
this#PaymentActivity,
"Transaction failed.Please try again",
Toast.LENGTH_SHORT
).show()
}
} else {
Toast.makeText(
this#PaymentActivity,
"Internet connection is not available. Please check and try again",
Toast.LENGTH_SHORT
).show()
}
}
companion object {
fun isConnectionAvailable(context: Context): Boolean {
val connectivityManager =
context.getSystemService(Context.CONNECTIVITY_SERVICE) as ConnectivityManager
if (connectivityManager != null) {
val netInfo = connectivityManager.activeNetworkInfo
if (netInfo != null && netInfo.isConnected
&& netInfo.isConnectedOrConnecting
&& netInfo.isAvailable
) {
return true
}
}
return false
}
}
}
Now, when I click back button from PaymentActivity the app crashes because the same state in the cartActivity is not present.How to resolve this ??
Manifest file:
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.foodly">
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<application
android:allowBackup="true"
android:hardwareAccelerated="true"
android:icon="#drawable/logo"
android:label="#string/app_name"
android:networkSecurityConfig="#xml/network_security_config"
android:resizeableActivity="false"
android:roundIcon="#mipmap/ic_launcher_round"
android:supportsRtl="true"
android:theme="#style/Theme.Foodly">
<activity android:name=".activity.OrderPlacedActivity"></activity>
<activity android:name=".activity.CartActivity" />
<activity android:name=".activity.OrderHistoryActivity" />
<activity
android:name=".activity.RestaurantMenuActivity" />
<activity
android:name=".activity.RegisterActivity" />
<activity
android:name=".activity.LoginActivity" />
<activity
android:name=".activity.PaymentActivity"/>
<activity
android:name=".activity.SplashActivity">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<activity
android:name=".activity.MainActivity" />
<meta-data
android:name="preloaded_fonts"
android:resource="#array/preloaded_fonts" />
</application>
</manifest>
Why do you call startActivity() in your OnBackPressed() callback ? You don't have to, it's automatic. If you need to retrieve parameters in the CartActivity, you have to launch the PaymentActivity with startActivityForResult()
Problem is with the
finishAffinity()
finishAffinity() is used to remove a number of Activitys belonging to a specific application from the current task (which may contain Activitys belonging to multiple applications).
You shouldn't be doing any finish on starting payment activity. you should be using finishAffinity() after payment success so the last activities should not come on back press.
For more info - https://developer.android.com/reference/android/app/Activity#finishAffinity()
Related
hi i am new in android and kotlin and i have a chat app that will work with sms and want save state of all chat for next run
i did use recyclerView and GroupieViewHolder for show chats , i see some post here but all was with java but i am using kotlin for this app
so if you can please help me and If possible, state the easiest way in the simplest possible way
app screenshot:
my smsActivity.kt:
class smsActivity : AppCompatActivity() {
private val messageAdapter = GroupAdapter<GroupieViewHolder>()
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_sms)
val recyclerView = findViewById<RecyclerView>(R.id.listmessage)
val button = findViewById<Button>(R.id.button)
val editmessage = findViewById<EditText>(R.id.editText)
val sharedPeref = getSharedPreferences("setNumber", MODE_PRIVATE)
val number = sharedPeref.getString("number", null)
recyclerView.adapter = messageAdapter
populateData()
receiveAutoResponse()
button.setOnClickListener {
val message = Message(text = editmessage.text.toString(), sendBy = "me")
val smssend = editmessage.text.toString()
val sendMessageItem = SendMessageItem(message)
messageAdapter.add(sendMessageItem)
editmessage.text.clear()
receiveAutoResponse()
recyclerView.scrollToPosition(messageAdapter.getItemCount() - 1);
try {
val smsManager: SmsManager = SmsManager.getDefault()
smsManager.sendTextMessage(number, null, smssend, null, null)
Toast.makeText(
applicationContext,
"بخاری 3 =دریافت گزارش ✅ دریافت گزارش چندین ثانیه زمان می برد ، لطفا برای ارسال دستور بعدی کمی صبر کنید",
Toast.LENGTH_LONG
).show()
} catch (e: Exception) {
Toast.makeText(
applicationContext,
"لطفا ابتدا شماره سیستم را وارد کنید !",
Toast.LENGTH_SHORT
).show()
val intent = Intent(this, setnumberActivity::class.java)
this.startActivity(intent)
}
}
}
fun ScrollView.scrollToBottom() {
val lastChild = getChildAt(childCount - 1)
val bottom = lastChild.bottom + paddingBottom
val delta = bottom - (scrollY + height)
smoothScrollBy(0, delta)
}
private fun populateData() {
val data = listOf<Message>()
data.forEach {
if (it.sendBy == "me") {
messageAdapter.add(SendMessageItem(it))
} else {
messageAdapter.add(ReceiveMessageItem(it))
}
}
}
private fun receiveAutoResponse() {
GlobalScope.launch(Dispatchers.Main) {
delay(1000)
val sharedPeref = getSharedPreferences("setNumber", MODE_PRIVATE)
val nums = "+98" + sharedPeref.getString("number", null)
val cursor: Cursor? = getContentResolver().query(
Uri.parse("content://sms"),
null,
"address='$nums'",
null,
null
)
cursor?.moveToFirst()
val messageSend = cursor?.getString(12)
val receive = Message(text = "$messageSend", sendBy = "me")
val receiveItem = ReceiveMessageItem(receive)
messageAdapter.add(receiveItem)
val recyclerView = findViewById<RecyclerView>(R.id.listmessage)
recyclerView.scrollToPosition(messageAdapter.getItemCount() - 1);
}
}
}
class SendMessageItem(private val message: Message) : BindableItem<ItemMessageSendBinding>() {
override fun getLayout(): Int {
return R.layout.item_message_send
}
override fun bind(viewBinding: ItemMessageSendBinding, position: Int) {
viewBinding.message = message
}
}
class ReceiveMessageItem(private val message: Message) : BindableItem<ItemMessageReceiveBinding>() {
override fun getLayout(): Int {
return R.layout.item_message_receive
}
override fun bind(viewBinding: ItemMessageReceiveBinding, position: Int) {
viewBinding.message = message
}
}
If you want ensure that Activity re-creation doesn't destroy your content, you can refer to this answer
If you want to connect the data to your local Storage, I suggest you using Room
I need to display the Telugu texts of Districts retrieved from API into Spinner, but random characters are displayed instead. How do I convert these characters to Telugu readable texts?
Sample Codes:
class MainActivity : AppCompatActivity() {
lateinit var spDistrict: Spinner
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
districtData = mutableListOf()
spDistrict = findViewById<Spinner>(R.id.district)
getDistrictData()
val jsonObject = JSONObject()
jsonObject.put("profile_pic", userImage.toString().replace("/storage/emulated/0/Pictures/",""))
jsonObject.put("district_id", districtData!![spDistrict.selectedItemPosition].id)
jsonObject.put("token", token)
Log.e("jsonObject", jsonObject.toString())
val url = Constant.BASE_URL + "register/"
Log.e("url", "---->$url")
val request = object : StringRequest(
Method.POST, url, Response.Listener { response ->
try {
val responseObj = JSONObject(response)
if (response.isNotEmpty()) {
next.hideProgress("నమోదు")
val status = responseObj.getString("status")
if (status == "success" && lang=="telugu") {
val message = responseObj.getString("response")
val token = responseObj.getString("token")
val prefs = SharedPrefs(this#TReg3)
prefs.token = (token)
if (userImage.isNotEmpty()) {
fileUpload()
} else {
showSuccessDialog(message)
dialog.dismiss()
}
} else {
next.hideProgress("నమోదు")
val message = responseObj.getString("response")
showCustomAlertDialog(message)
dialog.dismiss()
}
} else {
next.hideProgress("నమోదు")
showCustomAlertDialog("Something went wrong")
dialog.dismiss()
}
} catch (ex: Exception) {
next.hideProgress("నమోదు")
showCustomAlertDialog("Something went wrong")
dialog.dismiss()
}
},
Response.ErrorListener { error ->
next.hideProgress("ప్రవేశించండి")
val errorMessage = VolleyErrorParser.getVolleyErrorMessage(error)
showCustomAlertDialog(errorMessage)
dialog.dismiss()
}) {
override fun getHeaders(): MutableMap<String, String> {
val params = java.util.HashMap<String, String>()
params["Content-Type"] = "application/json"
return params
}
override fun getBody(): ByteArray {
return jsonObject.toString().toByteArray()
}
}
MySingleton.getInstance(this).addToRequestQueue(request)
}
}
private fun getDistrictData() {
val url = Constant.BASE_URL + "getDistricts/"
Log.e("districteUrl", url)
val request = StringRequest(Request.Method.GET, url, { response ->
try {
if (!response.isNullOrEmpty()) {
val jsonObject = JSONObject(response)
val status = jsonObject.getString("status")
if (status == "success") {
val data = jsonObject.getJSONArray("districts")
districtData = listOf(
*Gson().fromJson(
data.toString(),
Array<DistrictData>::class.java
)
)
if (districtData!!.isNotEmpty()) {
val categoryDataAdapter = ArrayAdapter<DistrictData>(
this,
android.R.layout.simple_list_item_1,
districtData!!)
categoryDataAdapter.setDropDownViewResource(android.R.layout.simple_list_item_1)
spDistrict.adapter = categoryDataAdapter
// getMandalData()
} else {
dialog.dismiss()
val response = jsonObject.getString("response")
Toast.makeText(this, response, Toast.LENGTH_SHORT).show()
}
} else {
dialog.dismiss()
val response = jsonObject.getString("response")
Toast.makeText(this, response, Toast.LENGTH_SHORT).show()
}
} else {
dialog.dismiss()
Toast.makeText(this, "Something Went Wrong", Toast.LENGTH_SHORT).show()
}
} catch (ex: Exception) {
Toast.makeText(this, "Something Went Wrong", Toast.LENGTH_SHORT).show()
dialog.dismiss()
ex.printStackTrace()
}
}, { error ->
dialog.dismiss()
val errorMessage = VolleyErrorParser.getVolleyErrorMessage(error)
Toast.makeText(this, errorMessage, Toast.LENGTH_SHORT).show()
})
VolleySingleton.getInstance(this!!).addToRequestQueue(request)
}
}
How do I make my app automatically detetct the Telugu text? Do I have to use a flag value?
I make a mobile application using the "io fotoapparat" library and I want to create a document with a random id and in the document in the id field, add the document id, the photo we will take was updated in the firebase store and in the previously made about the same id in the receipt collection when taking a photo
link from which I took "io fotoapparat"
EDIT
add to firestore document
binding.button.setOnClickListener {
// Inflate the layout for this fragment
val biedronka = "biedronka"
val price = "20"
val img = " "
val identificator = " "
val from = biedronka
val value = price
val image = img
val idd = identificator
val db = Firebase.firestore
val data = hashMapOf(
"from" to from,
"value" to value,
"image" to image,
"id" to idd
)
db.collection("receipts")
.add(data)
.addOnSuccessListener { documentReference ->
Log.d(SCAN_DEBUG, "DocumentSnapshot written with ID: ${documentReference.id}")
db.collection("receipts")
.document(documentReference.id)
.update("id", documentReference.id)
.addOnSuccessListener {
}
}
.addOnFailureListener { e ->
Log.w(SCAN_DEBUG, "Error adding document", e)
}
}
2 add to storage and to document (doesnt work)
override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
super.onActivityResult(requestCode, resultCode, data)
if (requestCode == REQUEST_CAPTURE_IMAGE && resultCode == RESULT_OK) {
val uid = profileVm.user.value?.uid!!
val imageBitmap = data?.extras?.get("data") as Bitmap
val userImage = binding.userImg
val stream = ByteArrayOutputStream()
val result = imageBitmap.compress(Bitmap.CompressFormat.JPEG, 100, stream)
val byteArray = stream.toByteArray()
if (result) profileVm.uploadUserPhoto(byteArray, "$uid.jpg")
}
}
repository to 2
fun uploadReceiptPhoto(bytes: ByteArray) {
storage.getReference("receipts")
.child("${docId}.jpg")
.putBytes(bytes)
.addOnCompleteListener{
Log.d(REPO_DEBUG, "COMPLETE UPLOAD PHOTO")
}
.addOnSuccessListener {
getReceiptPhotoDownloadUrl(it.storage)
}
.addOnFailureListener {
Log.d(REPO_DEBUG, it.message.toString())
}
}
private fun getReceiptPhotoDownloadUrl(storage: StorageReference) {
storage.downloadUrl
.addOnSuccessListener {
updateReceiptPhoto(it.toString())
}
.addOnFailureListener {
Log.d(REPO_DEBUG, it.message.toString())
}
}
private fun updateReceiptPhoto(url: String) {
cloud.collection("receipts")
.document(docId)
.update("image", url)
.addOnSuccessListener {
Log.d(REPO_DEBUG, "UPDATE USER PHOTO")
}
.addOnFailureListener {
Log.d(REPO_DEBUG, it.message.toString())
}
}
THE REST OF THE CODE (camera code "io fotoapparat" and take pictures)
class ScanFragment : Fragment(), OnReceiptsItemAdd {
private var _binding: FragmentScanBinding? = null
private val binding get() = _binding!!
private val scanVm by viewModels<ScanViewModel>()
private val SCAN_DEBUG = "SCAN_DEBUG"
private var fotoapparat: Fotoapparat? = null
private var fotoapparatState: FotoapparatState? = null
private var cameraStatus: CameraState? = null
private var flashState: FlashState? = null
private val permissions = arrayOf(Manifest.permission.CAMERA,
Manifest.permission.WRITE_EXTERNAL_STORAGE,
Manifest.permission.READ_EXTERNAL_STORAGE)
override fun onCreateView(
inflater: LayoutInflater, container: ViewGroup?,
savedInstanceState: Bundle?,
): View {
_binding = FragmentScanBinding.inflate(inflater, container, false)
createFotoapparat()
cameraStatus = CameraState.BACK
flashState = FlashState.OFF
fotoapparatState = FotoapparatState.OFF
binding.fabSwitchCamera.setOnClickListener {
switchCamera()
}
binding.fabFlash.setOnClickListener {
changeFlashState()
}
return binding.root
}
private fun createFotoapparat(){
val cameraView = binding.cameraView
fotoapparat = Fotoapparat(
context = requireContext(),
view = cameraView,
scaleType = ScaleType.CenterCrop,
lensPosition = back(),
logger = loggers(
logcat()
),
cameraErrorCallback = { error ->
println("Recorder errors: $error")
}
)
}
private fun changeFlashState() {
fotoapparat?.updateConfiguration(
CameraConfiguration(
flashMode = if(flashState == FlashState.TORCH) off() else torch()
)
)
flashState = if(flashState == FlashState.TORCH) FlashState.OFF
else FlashState.TORCH
}
private fun switchCamera() {
fotoapparat?.switchTo(
lensPosition = if (cameraStatus == CameraState.BACK) front() else back(),
cameraConfiguration = CameraConfiguration()
)
cameraStatus = if(cameraStatus == CameraState.BACK) CameraState.FRONT
else CameraState.BACK
}
private fun takePhoto() {
if (hasNoPermissions()) {
requestPermission()
}else{
fotoapparat
?.takePicture()
?.toBitmap()
}
}
override fun onStart() {
super.onStart()
if (hasNoPermissions()) {
requestPermission()
}else{
fotoapparat?.start()
fotoapparatState = FotoapparatState.ON
}
}
private fun hasNoPermissions(): Boolean{
return ContextCompat.checkSelfPermission(requireContext(),
Manifest.permission.READ_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED || ContextCompat.checkSelfPermission(requireContext(),
Manifest.permission.WRITE_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED || ContextCompat.checkSelfPermission(requireContext(),
Manifest.permission.CAMERA) != PackageManager.PERMISSION_GRANTED
}
private fun requestPermission(){
ActivityCompat.requestPermissions(requireActivity(), permissions,0)
}
override fun onStop() {
super.onStop()
fotoapparat?.stop()
FotoapparatState.OFF
}
}
enum class CameraState{
FRONT, BACK
}
enum class FlashState{
TORCH, OFF
}
enum class FotoapparatState{
ON, OFF
}
I implemented Scope Storage in a sample project. Where I Save, Load, and Modify Images in Local Storage and in Scope Storage as well.
Below is my Main Activity Class where I am Saving, Loading, and Modifying images in Local and Scope Storage. The below Code was working in API level 28 or Android 10. but when I run this app in Android 11 it gets hang and gives Application Not Responding. I am unable to find any error in Logcat. Below is my code Manifest File:
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
package="com.example.scopestorage">
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
<uses-permission
android:name="android.permission.WRITE_EXTERNAL_STORAGE"
android:maxSdkVersion="28" />
<application
android:allowBackup="true"
android:icon="#mipmap/ic_launcher"
android:label="#string/app_name"
android:roundIcon="#mipmap/ic_launcher_round"
android:supportsRtl="true"
android:theme="#style/Theme.ScopeStorage">
<activity android:name=".MainActivity">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
</application>
</manifest>
Now Below is my Main Activity Code:
class MainActivity : AppCompatActivity() {
private lateinit var binding: ActivityMainBinding
private lateinit var internalStoragePhotoAdapter: InternalStoragePhotoAdapter
private lateinit var externalStoragePhotoAdapter: SharedPhotoAdapter
private var readPermissionGranted = false
private var writePermissionGranted = false
private lateinit var permissionsLauncher: ActivityResultLauncher<Array<String>>
private lateinit var intentSenderLauncher: ActivityResultLauncher<IntentSenderRequest>
private lateinit var contentObserver: ContentObserver
private var deletedImageUri: Uri? = null
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
binding = ActivityMainBinding.inflate(layoutInflater)
setContentView(binding.root)
internalStoragePhotoAdapter = InternalStoragePhotoAdapter {
lifecycleScope.launch {
val isDeletionSuccessful = deletePhotoFromInternalStorage(it.name)
if(isDeletionSuccessful) {
loadPhotosFromInternalStorageIntoRecyclerView()
Toast.makeText(this#MainActivity, "Photo successfully deleted", Toast.LENGTH_SHORT).show()
} else {
Toast.makeText(this#MainActivity, "Failed to delete photo", Toast.LENGTH_SHORT).show()
}
}
}
externalStoragePhotoAdapter = SharedPhotoAdapter {
lifecycleScope.launch {
deletePhotoFromExternalStorage(it.contentUri)
deletedImageUri = it.contentUri
}
}
setupExternalStorageRecyclerView()
initContentObserver()
permissionsLauncher = registerForActivityResult(ActivityResultContracts.RequestMultiplePermissions()) { permissions ->
readPermissionGranted = permissions[Manifest.permission.READ_EXTERNAL_STORAGE] ?: readPermissionGranted
writePermissionGranted = permissions[Manifest.permission.WRITE_EXTERNAL_STORAGE] ?: writePermissionGranted
if(readPermissionGranted) {
loadPhotosFromExternalStorageIntoRecyclerView()
} else {
Toast.makeText(this, "Can't read files without permission.", Toast.LENGTH_LONG).show()
}
}
updateOrRequestPermissions()
intentSenderLauncher = registerForActivityResult(ActivityResultContracts.StartIntentSenderForResult()) {
if(it.resultCode == RESULT_OK) {
if(Build.VERSION.SDK_INT == Build.VERSION_CODES.Q) {
lifecycleScope.launch {
deletePhotoFromExternalStorage(deletedImageUri ?: return#launch)
}
}
Toast.makeText(this#MainActivity, "Photo deleted successfully", Toast.LENGTH_SHORT).show()
} else {
Toast.makeText(this#MainActivity, "Photo couldn't be deleted", Toast.LENGTH_SHORT).show()
}
}
val takePhoto = registerForActivityResult(ActivityResultContracts.TakePicturePreview()) {
lifecycleScope.launch {
val isPrivate = binding.switchPrivate.isChecked
val isSavedSuccessfully = when {
isPrivate -> savePhotoToInternalStorage(UUID.randomUUID().toString(), it)
writePermissionGranted -> savePhotoToExternalStorage(UUID.randomUUID().toString(), it)
else -> false
}
if(isPrivate) {
loadPhotosFromInternalStorageIntoRecyclerView()
}
if(isSavedSuccessfully) {
Toast.makeText(this#MainActivity, "Photo saved successfully", Toast.LENGTH_SHORT).show()
} else {
Toast.makeText(this#MainActivity, "Failed to save photo", Toast.LENGTH_SHORT).show()
}
}
}
binding.btnTakePhoto.setOnClickListener {
takePhoto.launch()
}
setupInternalStorageRecyclerView()
loadPhotosFromInternalStorageIntoRecyclerView()
loadPhotosFromExternalStorageIntoRecyclerView()
}
private fun initContentObserver() {
contentObserver = object : ContentObserver(null) {
override fun onChange(selfChange: Boolean) {
if(readPermissionGranted) {
loadPhotosFromExternalStorageIntoRecyclerView()
}
}
}
contentResolver.registerContentObserver(
MediaStore.Images.Media.EXTERNAL_CONTENT_URI,
true,
contentObserver
)
}
private suspend fun deletePhotoFromExternalStorage(photoUri: Uri) {
withContext(Dispatchers.IO) {
try {
contentResolver.delete(photoUri, null, null)
} catch (e: SecurityException) {
val intentSender = when {
Build.VERSION.SDK_INT >= Build.VERSION_CODES.R -> {
MediaStore.createDeleteRequest(contentResolver, listOf(photoUri)).intentSender
}
Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q -> {
val recoverableSecurityException = e as? RecoverableSecurityException
recoverableSecurityException?.userAction?.actionIntent?.intentSender
}
else -> null
}
intentSender?.let { sender ->
intentSenderLauncher.launch(
IntentSenderRequest.Builder(sender).build()
)
}
}
}
}
private suspend fun loadPhotosFromExternalStorage(): List<SharedStoragePhoto> {
return withContext(Dispatchers.IO) {
val collection = sdk29AndUp {
MediaStore.Images.Media.getContentUri(MediaStore.VOLUME_EXTERNAL)
} ?: MediaStore.Images.Media.EXTERNAL_CONTENT_URI
val projection = arrayOf(
MediaStore.Images.Media._ID,
MediaStore.Images.Media.DISPLAY_NAME,
MediaStore.Images.Media.WIDTH,
MediaStore.Images.Media.HEIGHT,
)
val photos = mutableListOf<SharedStoragePhoto>()
contentResolver.query(
collection,
projection,
null,
null,
"${MediaStore.Images.Media.DISPLAY_NAME} ASC"
)?.use { cursor ->
val idColumn = cursor.getColumnIndexOrThrow(MediaStore.Images.Media._ID)
val displayNameColumn = cursor.getColumnIndexOrThrow(MediaStore.Images.Media.DISPLAY_NAME)
val widthColumn = cursor.getColumnIndexOrThrow(MediaStore.Images.Media.WIDTH)
val heightColumn = cursor.getColumnIndexOrThrow(MediaStore.Images.Media.HEIGHT)
while(cursor.moveToNext()) {
val id = cursor.getLong(idColumn)
val displayName = cursor.getString(displayNameColumn)
val width = cursor.getInt(widthColumn)
val height = cursor.getInt(heightColumn)
val contentUri = ContentUris.withAppendedId(
MediaStore.Images.Media.EXTERNAL_CONTENT_URI,
id
)
photos.add(SharedStoragePhoto(id, displayName, width, height, contentUri))
}
photos.toList()
} ?: listOf()
}
}
private fun updateOrRequestPermissions() {
val hasReadPermission = ContextCompat.checkSelfPermission(
this,
Manifest.permission.READ_EXTERNAL_STORAGE
) == PackageManager.PERMISSION_GRANTED
val hasWritePermission = ContextCompat.checkSelfPermission(
this,
Manifest.permission.WRITE_EXTERNAL_STORAGE
) == PackageManager.PERMISSION_GRANTED
val minSdk29 = Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q
readPermissionGranted = hasReadPermission
writePermissionGranted = hasWritePermission || minSdk29
val permissionsToRequest = mutableListOf<String>()
if(!writePermissionGranted) {
permissionsToRequest.add(Manifest.permission.WRITE_EXTERNAL_STORAGE)
}
if(!readPermissionGranted) {
permissionsToRequest.add(Manifest.permission.READ_EXTERNAL_STORAGE)
}
if(permissionsToRequest.isNotEmpty()) {
permissionsLauncher.launch(permissionsToRequest.toTypedArray())
}
}
private suspend fun savePhotoToExternalStorage(displayName: String, bmp: Bitmap): Boolean {
return withContext(Dispatchers.IO) {
val imageCollection = sdk29AndUp {
MediaStore.Images.Media.getContentUri(MediaStore.VOLUME_EXTERNAL_PRIMARY)
} ?: MediaStore.Images.Media.EXTERNAL_CONTENT_URI
val contentValues = ContentValues().apply {
put(MediaStore.Images.Media.DISPLAY_NAME, "$displayName.jpg")
put(MediaStore.Images.Media.MIME_TYPE, "image/jpeg")
put(MediaStore.Images.Media.WIDTH, bmp.width)
put(MediaStore.Images.Media.HEIGHT, bmp.height)
}
try {
contentResolver.insert(imageCollection, contentValues)?.also { uri ->
contentResolver.openOutputStream(uri).use { outputStream ->
if(!bmp.compress(Bitmap.CompressFormat.JPEG, 95, outputStream)) {
throw IOException("Couldn't save bitmap")
}
}
} ?: throw IOException("Couldn't create MediaStore entry")
true
} catch(e: IOException) {
e.printStackTrace()
false
}
}
}
private fun setupInternalStorageRecyclerView() = binding.rvPrivatePhotos.apply {
adapter = internalStoragePhotoAdapter
layoutManager = StaggeredGridLayoutManager(3, RecyclerView.VERTICAL)
}
private fun setupExternalStorageRecyclerView() = binding.rvPublicPhotos.apply {
adapter = externalStoragePhotoAdapter
layoutManager = StaggeredGridLayoutManager(3, RecyclerView.VERTICAL)
}
private fun loadPhotosFromInternalStorageIntoRecyclerView() {
lifecycleScope.launch {
val photos = loadPhotosFromInternalStorage()
internalStoragePhotoAdapter.submitList(photos)
}
}
private fun loadPhotosFromExternalStorageIntoRecyclerView() {
lifecycleScope.launch {
val photos = loadPhotosFromExternalStorage()
externalStoragePhotoAdapter.submitList(photos)
}
}
private suspend fun deletePhotoFromInternalStorage(filename: String): Boolean {
return withContext(Dispatchers.IO) {
try {
deleteFile(filename)
} catch (e: Exception) {
e.printStackTrace()
false
}
}
}
private suspend fun loadPhotosFromInternalStorage(): List<InternalStoragePhoto> {
return withContext(Dispatchers.IO) {
val files = filesDir.listFiles()
files?.filter { it.canRead() && it.isFile && it.name.endsWith(".jpg") }?.map {
val bytes = it.readBytes()
val bmp = BitmapFactory.decodeByteArray(bytes, 0, bytes.size)
InternalStoragePhoto(it.name, bmp)
} ?: listOf()
}
}
private suspend fun savePhotoToInternalStorage(filename: String, bmp: Bitmap): Boolean {
return withContext(Dispatchers.IO) {
try {
openFileOutput("$filename.jpg", MODE_PRIVATE).use { stream ->
if(!bmp.compress(Bitmap.CompressFormat.JPEG, 95, stream)) {
throw IOException("Couldn't save bitmap.")
}
}
true
} catch(e: IOException) {
e.printStackTrace()
false
}
}
}
override fun onDestroy() {
super.onDestroy()
contentResolver.unregisterContentObserver(contentObserver)
}
}
Any sort of help would be highly appreciated.
I am getting a class not found exception when trying to click an image from the camera or while fetching it from the directory. The code is in kotlin and has been given below.
This is the class which implements the functionality to capture an image or picks them from the gallery.
The methods _openCamera() and openFileSelector() are implemented.
The main motive was to capture the images and upload them in the server but the implemented methods doesn't give the proper results.
class MainActivity : AppCompatActivity() {
private var drawerResult: Drawer? = null
private var jobschedular: JobScheduler? = null
private var jobschedularCode: Int = 1
private var phoneNumber: String? = null
private var toolbar: Toolbar? = null
private var familyId: String? = null
val TAG: String? = "Activity_Name"
val REQUEST_IMAGE_CAPTURE = 1
val REQUEST_CODE_FOR_GALLERY_CAPTURE = 2
var photoFile: File? = null
var progressDialog: Dialog? = null
private var doubleBackToExitPressedOnce = false
#SuppressLint("PrivateResource")
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
overridePendingTransition(R.anim.fade_in, R.anim.fade_out)
Log.d(TAG, "Inside MainActivity")
//onclick listener for open camera
onclickListenerForOpenCamera()
//starting the services here . .
val service_checkAddedtoFamily = Intent(this, checkAddedToFamily::class.java)
startService(service_checkAddedtoFamily)
val service_checkDocsToBeVerified = Intent(this, checkDocsToBeVerified::class.java)
startService(service_checkDocsToBeVerified)
/*findViewById<Button>(R.id.scan).setOnClickListener {
val i = Intent(this, Testers::class.java)
i.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION)
i.addFlags(Intent.FLAG_GRANT_WRITE_URI_PERMISSION)
startActivity(i)
overridePendingTransition(R.anim.fade_in, R.anim.fade_out)
}*/
//onclick listener for select image button
attach_onclick_listener_to_add_photos_from_gallery()
//onclick listener for select pdf files
onclickListenerForSelectPdfFile()
//get toolbar for drawer
toolbar = findViewById(R.id.toolbar_tabs)
//get phone number
val loginInfo = applicationContext.getSharedPreferences("loginInfo", Context.MODE_PRIVATE)
phoneNumber = loginInfo.getString("phoneNumber", "")
//onclick listener for upload button
//onclickListenerForUploadButton()
//onclick listener for retrieve button
onclickListenerForRetrieveButton()
//on click permanent diseases button
//onclickPermanentDiseasesButtton()
//navigation drawer
left_drawer(this, this#MainActivity, toolbar!!).createNavigationDrawer()
//verify auto upload
verifyAutoLoginInformation()
//create Sqlite database
DB_HELPER(this#MainActivity).writableDatabase
//get job schedular service
jobschedular = applicationContext.getSystemService(Context.JOB_SCHEDULER_SERVICE) as JobScheduler
schedulTheJobForHealthGoals()
schedulTheJobForHealthInsurance()
setPreferencesForNutrition()
schedulTheJobForNutrition()
schedulTheJobForSyncNutritionOnline()
}
/*override fun onBackPressed() {
if (doubleBackToExitPressedOnce) {
super.onBackPressed()
return
}
this.doubleBackToExitPressedOnce = true
Toast.makeText(this, "Press back again to exit", Toast.LENGTH_SHORT).show()
Handler().postDelayed(Runnable { doubleBackToExitPressedOnce = false }, 2000)
}*/
//job schedular
fun schedulTheJobForHealthGoals() {
val builder = JobInfo.Builder(jobschedularCode, ComponentName(this#MainActivity, health_goals_services::class.java))
.setPersisted(true)
.setPeriodic(5000)
.setRequiredNetworkType(JobInfo.NETWORK_TYPE_UNMETERED)
.setRequiresCharging(false)
.setRequiresDeviceIdle(false)
val bundle = PersistableBundle()
bundle.putString("key", "value")
builder.setExtras(bundle)
val s_response = jobschedular!!.schedule(builder.build())
if (s_response <= 0) {
//something goes wrong
}
}
fun schedulTheJobForHealthInsurance() {
val builder = JobInfo.Builder(jobschedularCode, ComponentName(this#MainActivity, health_insurance_service::class.java))
.setPersisted(true)
.setPeriodic(5000)
.setRequiredNetworkType(JobInfo.NETWORK_TYPE_UNMETERED)
.setRequiresCharging(false)
.setRequiresDeviceIdle(false)
val bundle = PersistableBundle()
bundle.putString("key", "value")
builder.setExtras(bundle)
val s_response = jobschedular!!.schedule(builder.build())
if (s_response <= 0) {
//something goes wrong
}
}
fun schedulTheJobForNutrition() {
val builder = JobInfo.Builder(jobschedularCode, ComponentName(this#MainActivity, nutrition_service::class.java))
.setPersisted(true)
.setPeriodic(5000) //change to 1 hour
.setRequiredNetworkType(JobInfo.NETWORK_TYPE_UNMETERED)
.setRequiresCharging(false)
.setRequiresDeviceIdle(false)
val bundle = PersistableBundle()
bundle.putString("key", "value")
builder.setExtras(bundle)
val s_response = jobschedular!!.schedule(builder.build())
if (s_response <= 0) {
//something goes wrong
}
}
fun setPreferencesForNutrition() {
val nutritionInfo = getSharedPreferences("nutrition", Context.MODE_PRIVATE)
val editor = nutritionInfo.edit()
editor.putString("breakFastTime_Hour", "7")
editor.putString("lunchTime_Hour", "14") //TODO: change to 13
editor.putString("DinnerTime_Hour", "20")
editor.apply()
}
fun schedulTheJobForSyncNutritionOnline() {
val builder = JobInfo.Builder(jobschedularCode, ComponentName(this#MainActivity, sync_nutrition_online::class.java))
.setPersisted(true)
.setPeriodic(5000)
.setRequiredNetworkType(JobInfo.NETWORK_TYPE_UNMETERED)
.setRequiresCharging(false)
.setRequiresDeviceIdle(false)
val bundle = PersistableBundle()
bundle.putString("key", "value")
builder.setExtras(bundle)
val s_response = jobschedular!!.schedule(builder.build())
if (s_response <= 0) {
//something goes wrong
}
}
//buttons on home screen
/*fun onclickListenerForUploadButton(){
findViewById<ImageView>(R.id.uploadButton).setOnClickListener{
openModeOfUploadActivity()
}
}*/
fun onclickListenerForRetrieveButton() {
findViewById<Button>(R.id.retrieveButton).setOnClickListener {
openHistoryActivity()
}
}
/*fun onclickPermanentDiseasesButtton(){
findViewById<Button>(R.id.permanentDiseasesButton).setOnClickListener{
openPermanentDiseases()
}
}*/
/*fun openModeOfUploadActivity(){
val intent = Intent(this,MainActivity::class.java)
startActivity(intent)
}*/
fun openHistoryActivity() {
val intent = Intent(this, history_pickFamilyMember::class.java)
startActivity(intent)
overridePendingTransition(R.anim.fade_in, R.anim.fade_out)
}
/*fun openPermanentDiseases(){
val intent = Intent(this,permanentDiseaese::class.java)
startActivity(intent)
}
*/
//verify auto login information
fun verifyAutoLoginInformation() {
val loginInfo = applicationContext.getSharedPreferences("loginInfo", Context.MODE_PRIVATE)
if (loginInfo.contains("familyOrIndividual") == true) {
//for family
if (loginInfo.getString("familyOrIndividual", "").toString() == "f") {
if (loginInfo.contains("phoneNumber") == true && loginInfo.contains("password") == true) {
val phoneNumber = loginInfo.getString("phoneNumber", "")
val password = loginInfo.getString("password", "")
individual_family_login(this#MainActivity).makeFamilyLoginApiRequest(phoneNumber, password)
} else {
left_drawer(this, this#MainActivity, toolbar!!).makeUserLogOut()
}
}
//for individual
if (loginInfo.getString("familyOrIndividual", "").toString() == "i") {
if (loginInfo.contains("phoneNumber") == true && loginInfo.contains("password") == true) {
val phoneNumber = loginInfo.getString("phoneNumber", "")
val password = loginInfo.getString("password", "")
individual_family_login(this#MainActivity).makeLoginApiRequest(phoneNumber, password)
} else {
left_drawer(this, this#MainActivity, toolbar!!).makeUserLogOut()
}
}
//for security
if (loginInfo.getString("familyOrIndividual", "").toString() != "i" && loginInfo.getString("familyOrIndividual", "").toString() != "f") {
left_drawer(this, this#MainActivity, toolbar!!).makeUserLogOut()
}
} else {
left_drawer(this, this#MainActivity, toolbar!!).makeUserLogOut()
}
}
//camera scan
fun onclickListenerForOpenCamera() {
findViewById<ImageView>(R.id.openCamera).setOnClickListener {
get_permissions_camera()
}
}
fun _openCamera() {
Log.d("Errors__", "inside _openCamera()")
try {
val takePictureIntent = Intent(MediaStore.ACTION_IMAGE_CAPTURE)
if (takePictureIntent.resolveActivity(getPackageManager()) != null) {
try {
photoFile = createImageFile()
} catch (ex: Exception) {
Log.d("Errors__", "inside: " + ex.toString())
}
if (photoFile != null) {
val builder: StrictMode.VmPolicy.Builder = StrictMode.VmPolicy.Builder()
StrictMode.setVmPolicy(builder.build())
val photoURI: Uri = Uri.fromFile(photoFile!!)
Log.d("Path__", "photoURI: $photoURI")
Log.d("Path__", "photoURI.path: " + photoURI.path)
takePictureIntent.putExtra(MediaStore.EXTRA_OUTPUT, photoURI)
takePictureIntent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION)
startActivityForResult(takePictureIntent, REQUEST_IMAGE_CAPTURE)
}
}
} catch (e: Exception) {
Log.d("Errors__", "_openCamera" + e.toString())
}
}
fun createImageFile(): File {
Log.d("Errors__", "inside createImageFile()")
val mCurrentPhotoPath: String
val imageFileName = "camera"
val storageDir: File = getExternalFilesDir(Environment.DIRECTORY_PICTURES)
val image = File.createTempFile(
imageFileName, /* prefix */
".jpg", /* suffix */
storageDir /* directory */
)
// Save a file: path for use with ACTION_VIEW intents
mCurrentPhotoPath = image.getAbsolutePath()
Log.d("Path__", "Image: $image")
return image
}
//file selector
fun onclickListenerForSelectPdfFile() {
findViewById<ImageView>(R.id.selectPdfFile).setOnClickListener {
get_permissions_fileExplorer()
}
}
#SuppressLint("SdCardPath")
fun openFileSelector() {
val properties = DialogProperties()
properties.selection_mode = DialogConfigs.MULTI_MODE;
properties.selection_type = DialogConfigs.FILE_SELECT;
properties.root = File(DialogConfigs.DEFAULT_DIR);
properties.error_dir = File(DialogConfigs.DEFAULT_DIR);
properties.offset = File(DialogConfigs.DEFAULT_DIR);
properties.extensions = null;
val dialog: FilePickerDialog = FilePickerDialog(this#MainActivity, properties)
dialog.setTitle("Select a File")
dialog.setDialogSelectionListener(object : DialogSelectionListener {
override fun onSelectedFilePaths(files: Array<out String>?) {
convertPdfToImages(files!!)
}
})
dialog.show()
}
fun convertPdfToImages(files: Array<out String>) {
showProcessProgress()
doAsync {
var uriList: MutableList<Uri>? = mutableListOf()
val no_of_files = files.size
var counter = 0
while (counter < no_of_files) {
var pdfFile = File(files[counter])
val decodeService = DecodeServiceBase(PdfContext())
decodeService.setContentResolver(applicationContext.getContentResolver())
decodeService.open(Uri.fromFile(pdfFile))
val pageCount: Int = decodeService.getPageCount()
var i = 0
while (i < pageCount) {
val page: PdfPage = decodeService.getPage(i) as PdfPage
val rectF = RectF(0.toFloat(), 0.toFloat(), 1.toFloat(), 1.toFloat())
// do a fit center to 1920x1080
val scaleBy = 1
val with: Int = (page.getWidth() * scaleBy)
val height: Int = (page.getHeight() * scaleBy)
val bitmap: Bitmap = page.renderBitmap(with, height, rectF)
try {
val outputFile = File(applicationContext.externalCacheDir,
System.currentTimeMillis().toString() + ".jpg")
val outputStream = FileOutputStream(outputFile)
// a bit long running
bitmap.compress(Bitmap.CompressFormat.JPEG, 100, outputStream)
uriList!!.add(Uri.fromFile(outputFile))
outputStream.close()
} catch (e: IOException) {
}
i++
}
counter++
}
uiThread {
progressDialog!!.hide()
openPreview(uriList!!)
Log.d("mess", "size: " + uriList.size + " " + uriList.toString())
}
}
}
//select image
fun attach_onclick_listener_to_add_photos_from_gallery() {
findViewById<ImageView>(R.id.selectImage).setOnClickListener {
get_permissions_gallery()
}
}
fun open_selector() {
Matisse.from(this)
.choose(MimeType.allOf())
.countable(true)
.maxSelectable(200)
.restrictOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT)
.thumbnailScale(0.85f)
.imageEngine(PicassoEngine())
.forResult(REQUEST_CODE_FOR_GALLERY_CAPTURE)
}
//activity results
override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
if (requestCode == REQUEST_IMAGE_CAPTURE && resultCode == Activity.RESULT_OK) {
var uriOfImage = Uri.fromFile(photoFile)
Log.d("fileCapturing__", "URI Image: $uriOfImage")
//start croper
CropImage.activity(uriOfImage)
.start(this)
}
if (requestCode == REQUEST_CODE_FOR_GALLERY_CAPTURE && resultCode == Activity.RESULT_OK) {
var selected_images = Matisse.obtainResult(data)
openPreview(selected_images!!)
}
//for croper
if (requestCode == CropImage.CROP_IMAGE_ACTIVITY_REQUEST_CODE) {
val result: CropImage.ActivityResult = CropImage.getActivityResult(data)
if (resultCode == RESULT_OK) {
doAsync {
val builder: StrictMode.VmPolicy.Builder = StrictMode.VmPolicy.Builder()
StrictMode.setVmPolicy(builder.build())
var resultUri: Uri = result.getUri()
//save cropped image for persisitance
val croppedImage = createImageFile() //empty
val outputStream = FileOutputStream(croppedImage)
// a bit long running
(Picasso.with(this#MainActivity)
.load(resultUri)
.get()
).compress(Bitmap.CompressFormat.JPEG, 100, outputStream)
Log.d("fileCapturing__", "outputStream: $outputStream")
resultUri = Uri.fromFile(croppedImage)
outputStream.close()
uiThread {
//add to mu list
var mu_list = ArrayList<Uri>(1)
mu_list.add(resultUri)
Log.d("fileCapturing__", "camera uri" + resultUri.toString())
openPreview(mu_list)
}
}
} else if (resultCode == CropImage.CROP_IMAGE_ACTIVITY_RESULT_ERROR_CODE) {
val error: Exception = result.getError()
Log.d("fileCapturing__", "Error: $error")
}
}
}
//preview
fun openPreview(list: MutableList<Uri>) {
val _object = list
val i = Intent(this, typeOfDocument::class.java)
val args = Bundle()
args.putSerializable("ARRAYLIST", _object as java.io.Serializable)
i.putExtra("BUNDLE", args)
startActivity(i)
finish()
}
//get permissions
//Camera
fun get_permissions_camera() {
if (ContextCompat.checkSelfPermission(this#MainActivity, android.Manifest.permission.CAMERA) != PackageManager.PERMISSION_GRANTED) {
MaterialDialog.Builder(this#MainActivity)
.title("Camera permission")
.content("Camera permissions are required for opening Camera")
.negativeText("Cancel")
.onNegative(object : MaterialDialog.SingleButtonCallback {
override fun onClick(dialog: MaterialDialog, which: DialogAction) {
}
})
.positiveText("Give Permissions")
.onPositive(object : MaterialDialog.SingleButtonCallback {
override fun onClick(dialog: MaterialDialog, which: DialogAction) {
getPermissionsUsingDexter_camera(
android.Manifest.permission.CAMERA
)
}
})
.show()
} else {
_openCamera()
}
}
fun getPermissionsUsingDexter_camera(permissionString: String) {
Dexter.withActivity(this)
.withPermissions(
permissionString
).withListener(object : MultiplePermissionsListener {
override fun onPermissionRationaleShouldBeShown(permissions: MutableList<PermissionRequest>?, token: PermissionToken?) {
}
override fun onPermissionsChecked(report: MultiplePermissionsReport?) {
if (report!!.areAllPermissionsGranted() == true) {
_openCamera()
Log.d("mess", "permission given")
} else {
Log.d("mess", "permission not granted")
}
}
})
.check()
}
//gallery
fun get_permissions_gallery() {
if (ContextCompat.checkSelfPermission(this#MainActivity, android.Manifest.permission.READ_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED) {
MaterialDialog.Builder(this#MainActivity)
.title("Storage permission")
.content("Storage permissions are required for opening the Gallery")
.negativeText("Cancel")
.onNegative(object : MaterialDialog.SingleButtonCallback {
override fun onClick(dialog: MaterialDialog, which: DialogAction) {
}
})
.positiveText("Give Permissions")
.onPositive(object : MaterialDialog.SingleButtonCallback {
override fun onClick(dialog: MaterialDialog, which: DialogAction) {
getPermissionsUsingDexter_gallery(
android.Manifest.permission.READ_EXTERNAL_STORAGE
)
}
})
.show()
} else {
open_selector()
}
}
fun getPermissionsUsingDexter_gallery(permissionString: String) {
Dexter.withActivity(this)
.withPermissions(
permissionString
).withListener(object : MultiplePermissionsListener {
override fun onPermissionRationaleShouldBeShown(permissions: MutableList<PermissionRequest>?, token: PermissionToken?) {
}
override fun onPermissionsChecked(report: MultiplePermissionsReport?) {
if (report!!.areAllPermissionsGranted() == true) {
open_selector()
Log.d("mess", "permission given")
} else {
Log.d("mess", "permission not granted")
}
}
})
.check()
}
//file exploer
fun get_permissions_fileExplorer() {
if (ContextCompat.checkSelfPermission(this#MainActivity, android.Manifest.permission.READ_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED) {
MaterialDialog.Builder(this#MainActivity)
.title("Storage permission")
.content("Storage access permissions are required for opening File Explorer")
.negativeText("Cancel")
.onNegative(object : MaterialDialog.SingleButtonCallback {
override fun onClick(dialog: MaterialDialog, which: DialogAction) {
}
})
.positiveText("Give Permissions")
.onPositive(object : MaterialDialog.SingleButtonCallback {
override fun onClick(dialog: MaterialDialog, which: DialogAction) {
getPermissionsUsingDexter_fileExplores(
android.Manifest.permission.READ_EXTERNAL_STORAGE
)
}
})
.show()
} else {
openFileSelector()
}
}
fun getPermissionsUsingDexter_fileExplores(permissionString: String) {
Dexter.withActivity(this)
.withPermissions(
permissionString
).withListener(object : MultiplePermissionsListener {
override fun onPermissionRationaleShouldBeShown(permissions: MutableList<PermissionRequest>?, token: PermissionToken?) {
}
override fun onPermissionsChecked(report: MultiplePermissionsReport?) {
if (report!!.areAllPermissionsGranted() == true) {
openFileSelector()
Log.d("mess", "permission given")
} else {
Log.d("mess", "permission not granted")
}
}
})
.check()
}
//progress bar
fun showProcessProgress() {
progressDialog = MaterialDialog.Builder(this)
.title("Please Wait")
.content("Converting Pdf to Images")
.progress(true, 0)
.show()
}
}
The error shows when I try to click an image or fetch from the library.
The provider path used is given below:
<paths xmlns:android="http://schemas.android.com/apk/res/android">
<external-path
name="external_files"
path="." />
</paths>
I have tried changing the path to "/" but it didn't work. The error wasn't showing earlier but the error exists now.
Here is the snapshot of the logs.
All suggestions are accepted. Thanks in advance.