尝试压缩位图时出现空指针异常,无法拍照并上传到服务器

发布于 2025-01-15 17:37:33 字数 24694 浏览 7 评论 0原文

当我尝试在相机应用程序上拍照并将其上传到服务器端时,我收到 NullPointerException ,但有些设备工作正常,有些设备却出现问题。我不知道是什么问题,在某些设备上它只能工作一次然后崩溃。

这些问题是通过使用 firebase CrashAnalytics 来识别的。

片段类。

class PhotoUploadFragment : BaseFragment() {

    private lateinit var viewModel: SelectOptionViewModel

    //define caseId type
    private var caseId: String? = ""

    //define caseNo type
    private var caseNo: String? = ""

    //define image clarity
    private var imageClarity: String? = ""

    //define image width
    private var imageWidth: String? = ""

    //define image height
    private var imageHeight: String? = ""

    //location
    lateinit var mFusedLocationClient: FusedLocationProviderClient

    //random id
    val PERMISSION_ID = 42

    //Initialize lat and long  to get loc address
    var longitude = 0.0
    var latitude = 0.0

    //Capture bitmap image
    var capturedBitmap = BitmapFactory.decodeStream(null)

    //Set timestamp when giving name while saving image
    var addrTimeStamp = ""

    //Initialize location address
    var locationAddress = ""

    companion object {
        private var args: Bundle? = null

        //pass the argument that needs to be displayed
        fun newInstance(case_id: String, case_number: String): Fragment {
//            fun newInstance(case_id: String, case_number: String): Fragment {
            args = Bundle()
            //pass the value caseId
            args!!.putString(CASE_ID, case_id)
            //pass the value caseNo
            args!!.putString(CASE_NO, case_number)
            val fragment = PhotoUploadFragment()
            fragment.arguments = args
            return fragment
        }
    }

    override fun onCreateView(
        inflater: LayoutInflater,
        container: ViewGroup?,
        savedInstanceState: Bundle?
    ): View {
        //setup view model
        viewModel = ViewModelProviders.of(this)[SelectOptionViewModel::class.java]
//        homeViewModel = ViewModelProviders.of(this)[HomeViewModel::class.java]
        val view: View = inflater.inflate(
            layout.fragment_tab_photo_upload,
            container,
            false
        )
        //get caseId
        caseId = arguments?.getString(CASE_ID)

        //get caseNo
        caseNo = arguments?.getString(CASE_NO)
        if (caseNo == null || caseNo == "") {
            caseNo = "Nil"
        }

        //get imageClarity
        imageClarity = PrefsHelper().getPref<String>(Constants.IMAGE_CLARITY)

        //get imageWidth
        imageWidth = PrefsHelper().getPref<String>(Constants.IMAGE_WIDTH)

        //get imageHeight
        imageHeight = PrefsHelper().getPref<String>(Constants.IMAGE_HEIGHT)

        mFusedLocationClient = LocationServices.getFusedLocationProviderClient(this.activity!!)
        return view

    }

    override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
        //to clear all the data inside the fragment to avoid multiple API calls
        viewModel.imageUploadresponseLiveData.value = null

        //to enable upload btn only after image is taken
        photo_upload_button_upload.isEnabled = false

        getLastLocation()
        setUpListeners()
        setupObservers()
    }

    private fun setupObservers() {
        viewModel.imageUploadresponseLiveData.observe(this, androidx.lifecycle.Observer {
            if (it != null) {
                //photo upload success
                if (it.success == 1 && it.result.success == 1) {
                    Toast.makeText(context, "Image uploaded successfully.", Toast.LENGTH_SHORT)
                        .show()
                    //delete file after upload
                    val root = Environment.getExternalStorageDirectory().toString()
                    val myDir = File(root + "/CV App/nomedia/images/")
                    myDir.deleteRecursively()
                    photo_upload_imageview_photo.setImageBitmap(null)
                    //to enable upload btn only after image is taken
                    photo_upload_button_upload.isEnabled = false
                }
                //photo upload fail
                else {
                    Toast.makeText(
                        context,
                        "Failed to update image. Please try again.",
                        Toast.LENGTH_SHORT
                    ).show()
                }
            }
        })
        //observe API call status
        viewModel.imageUploadAPICallStatus.observe(this, androidx.lifecycle.Observer {
            processStatus(it)
        })
    }


    private fun setUpListeners() {

        photo_upload_button_open.setOnClickListener {
            //Check camera permission
            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
                if (checkSelfPermission(
                        this.activity!!,
                        Manifest.permission.CAMERA
                    ) != PackageManager.PERMISSION_GRANTED
                ) {
                    ActivityCompat.requestPermissions(
                        this.activity!!,
                        arrayOf(Manifest.permission.CAMERA),
                        1
                    )
                }

            }
            //Check storage permission
            if (ActivityCompat.checkSelfPermission(
                    this.activity!!,
                    Manifest.permission.WRITE_EXTERNAL_STORAGE
                ) != PackageManager.PERMISSION_GRANTED
            ) {

                ActivityCompat.requestPermissions(
                    this.activity!!,
                    arrayOf(Manifest.permission.WRITE_EXTERNAL_STORAGE), REQUEST_PERM_WRITE_STORAGE
                )

            }
            //if permission is allowed,open camera
            else {
                startCamera()
            }

            photo_upload_button_upload.setOnClickListener {
                showDialogUpload()
            }

        }
    }


    private fun startCamera() {

        Intent(MediaStore.ACTION_IMAGE_CAPTURE).also { cameraIntent ->
            // Ensure that there's a camera activity to handle the intent
            cameraIntent.resolveActivity(context!!.packageManager)?.also {
                // Create the File where the photo should go
                val photoFile: File? = try {
                    createImageFile()
                } catch (ex: IOException) {
                    // Error occurred while creating the File
                    //...
                    null
                }
                //    Continue only if the File was successfully created
                photoFile?.also {
                    val photoURI: Uri = FileProvider.getUriForFile(
                        this.activity!!,
                        "com.xyzshopapp.fileprovider",
                        it
                    )
                    cameraIntent.putExtra(MediaStore.EXTRA_OUTPUT, photoURI)
                    cameraIntent.putExtra("return-data", true)
                    this.startActivityForResult(cameraIntent, ACTION_IMAGE_CAPTURE)
                }
            }
        }
    }


    /**
     * Create external image file, this file will be passed to Camera for saving the captured image
     */
    @Throws(IOException::class)
    private fun createImageFile(): File {

        // Create an image file name
        val timeStamp: String = SimpleDateFormat("yyyyMMdd_HHmmss").format(Date())
        //Set timestamp to addrTimeStamp
        addrTimeStamp = timeStamp
        val root = Environment.getExternalStorageDirectory().toString()
        val myDir = File("$root/CV App/nomedia/images")

        myDir.mkdirs()

        return File.createTempFile(
            "JPG_${addrTimeStamp}_", /* prefix */
            ".jpg", /* suffix */
            myDir /* directory */
        ).apply {
            // Save a file: path for use with ACTION_VIEW intents
            fileTemp = this
            //Save the complete file path to string
            imageFileName = this.toURI().path.toString()

        }
    }

    //show thumbnail
    override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
        super.onActivityResult(requestCode, resultCode, data)

        if (resultCode == Activity.RESULT_OK ) {
            when (requestCode) {
                ACTION_IMAGE_CAPTURE -> {
                    val imageQuality = imageClarity
                    val byteArrayOutputStream = ByteArrayOutputStream()

                    //Decode file to bitmap
                    capturedBitmap = BitmapFactory.decodeFile(imageFileName)


                    val a = capturedBitmap
                    val destinationHeight = imageHeight
                    val destinationWidth = imageWidth
                    var imageToScale = capturedBitmap

                    //test
                    var uncompressed = capturedBitmap
                    if (destinationHeight != null) {
                        if (destinationWidth != null) {
                            if (destinationHeight.toInt() > 0 && destinationWidth.toInt() > 0 && imageToScale != null) {
                                val width = imageToScale.width
                                val height = imageToScale.height

                                //Calculate the max changing amount and decide which dimension to use
                                val widthRatio = destinationWidth.toFloat() / width.toFloat()
                                val heightRatio = destinationHeight.toFloat() / height.toFloat()

                                //Use the ratio that will fit the image into the desired sizes
                                var finalWidth = floor((width * widthRatio).toDouble()).toInt()
                                var finalHeight = floor((height * widthRatio).toDouble()).toInt()
                                if (finalWidth > destinationWidth.toInt() || finalHeight > destinationHeight.toInt()) {
                                    finalWidth = floor((width * heightRatio).toDouble()).toInt()
                                    finalHeight = floor((height * heightRatio).toDouble()).toInt()
                                }

                                //Scale given bitmap to fit into the desired area
                                imageToScale = Bitmap.createScaledBitmap(imageToScale, finalWidth, finalHeight, false)

                                //Created a bitmap with desired sizes
                                val scaledImage =
                                    Bitmap.createBitmap(destinationWidth.toInt(), destinationHeight.toInt(), Bitmap.Config.ARGB_8888)
                                uncompressed = imageToScale
                            }
                        }
                    }

                    //compress by quality
                    if (imageQuality != null) {
                        uncompressed.compress(
                            Bitmap.CompressFormat.JPEG,
                            imageQuality.toInt(),
                            byteArrayOutputStream
                        )
                       /*try{

                       }catch (e:Exception)
                       {
                           println("this is exception $e")
                       }*/

                    }
                    val byteArray = byteArrayOutputStream.toByteArray()
                    //Encode bitmap to file
                    val compressedImageFile = FileOutputStream(imageFileName)
                    compressedImageFile.write(byteArray)
                    compressedImageFile.flush()
                    compressedImageFile.close()
                    //Set image in thumbnail
                    photo_upload_imageview_photo.setImageBitmap(a)
                    //to enable upload btn only after image is taken
                    photo_upload_button_upload.isEnabled = true
                }
                else -> {
                    Toast.makeText(context, "Unrecognized request code.", Toast.LENGTH_SHORT).show()
                }
            }

        }

    }

    //popup box for uploading photo
    fun showDialogUpload() {
        val dialog = Dialog(context!!)
        dialog.requestWindowFeature(Window.FEATURE_NO_TITLE)
        dialog.setCancelable(true)
        dialog.setContentView(layout.photo_upload)

        val photo_upload_submit =
            dialog.findViewById(com.xyz.shopapp.R.id.image_button_submit) as Button
        val spinner =
            dialog.findViewById(com.xyz.shopapp.R.id.photo_upload_spinner_image_name) as Spinner
        //get array of image names
        val imageName = (PrefsHelper().getPref<String>("ImageName"))

        //convert array to string
        val gson = Gson()
        val imageNameList = gson.fromJson(imageName, Array<String>::class.java).asList()

        //dropdown menu
        if (spinner != null) {
            val adapter =
                ArrayAdapter<String>(context!!, android.R.layout.simple_spinner_item, imageNameList)
            // Set layout to use when the list of choices appear
            adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item)
            // Set Adapter to Spinner
            spinner.adapter = adapter

            //get image name
            var itemSpinnerSelected = ""
            spinner.onItemSelectedListener = object : AdapterView.OnItemSelectedListener {
                override fun onItemSelected(
                    parent: AdapterView<*>,
                    view: View,
                    position: Int,
                    id: Long
                ) {
                    // Get the selected item
                    itemSpinnerSelected = "${parent.getItemAtPosition(position)}"
                }

                override fun onNothingSelected(parent: AdapterView<*>) {
                    // Another interface callback
                }
            }

            photo_upload_submit.setOnClickListener {

                if (getAddress()) {
                    viewModel.submitImageData(
                        caseId, caseNo,
                        imageFileName, latitude, longitude, itemSpinnerSelected, locationAddress
                    )
//                    viewModel.submitImageData(
//                        caseId, caseNo,
//                        imageFileName, latitude, longitude, itemSpinnerSelected, locationAddress
//                    )
//                viewModel.submitImageData(caseId,caseNo,rootDir + "/CV App/nomedia/images/avc6937492103605367617.jpg",latitude,longitude,itemSpinnerSelected, locationAddress)
//                dismissDialog()
//                val progressBar = findViewById(com.xyz.shopapp.R.id.progresbar) as ProgressBar
//                progressBar.visibility = View.INVISIBLE

                }
                dialog.dismiss()
            }

        }
        dialog.show()
    }

    //get location
    //check whether location is enabled for application
    @SuppressLint("MissingPermission")
    private fun getLastLocation() {
//       var latitude = 0.0
        if (checkPermissions()) {
            //if (isLocationEnabled()) {

                     mFusedLocationClient.lastLocation.addOnCompleteListener(this.activity!!) { task ->
                         val location: Location? = task.result

                         if (location == null) {
                             requestNewLocationData()
                         } else {
                             latitude = location.latitude
                             longitude = location.longitude
                             getAddress()
                         }
                     }

            /*mFusedLocationClient.lastLocation.addOnCompleteListener(this.activity!!) { task ->
                var location: Location? = task.result

                if (location == null) {
                    requestNewLocationData()
                } else {
                    latitude = location.latitude
                    longitude = location.longitude
                    getAddress()
                }
            }*/
//            } else {
//                Toast.makeText(context, "Turn on your location.", Toast.LENGTH_LONG).show()
//                val intent = Intent(Settings.ACTION_LOCATION_SOURCE_SETTINGS)
//                startActivity(intent)
//            }


        } else {
            //requestPermissions()
            //Manifest.permission.ACCESS_COARSE_LOCATION, Manifest.permission.ACCESS_FINE_LOCATION

            //to get location in first try itself
            val coraseLocationPermission = checkSelfPermission(
                this.activity!!,
                Manifest.permission.ACCESS_COARSE_LOCATION
            )
            val accessFineLocation = checkSelfPermission(
                this.activity!!,
                Manifest.permission.ACCESS_FINE_LOCATION
            )

            if (coraseLocationPermission != PackageManager.PERMISSION_GRANTED && accessFineLocation != PackageManager.PERMISSION_GRANTED) {

                requestPermissions(
                    arrayOf(
                        Manifest.permission.ACCESS_COARSE_LOCATION,
                        Manifest.permission.ACCESS_FINE_LOCATION
                    ),
                    PERMISSION_ID
                )
            }
        }
    }

    @SuppressLint("MissingPermission")
    private fun requestNewLocationData() {


        val mLocationRequest = LocationRequest()
        mLocationRequest.priority = LocationRequest.PRIORITY_HIGH_ACCURACY
        mLocationRequest.interval = 0
        mLocationRequest.fastestInterval = 0
        mLocationRequest.numUpdates = 1

        mFusedLocationClient = LocationServices.getFusedLocationProviderClient(this.activity!!)
        mFusedLocationClient.requestLocationUpdates(
            mLocationRequest, mLocationCallback,
            Looper.myLooper()

        )
    }

    private val mLocationCallback = object : LocationCallback() {
        override fun onLocationResult(locationResult: LocationResult) {
            val mLastLocation: Location = locationResult.lastLocation
            latitude = mLastLocation.latitude
            longitude = mLastLocation.longitude
        }
    }

//    private fun isLocationEnabled(): Boolean {
//        var locationManager: LocationManager = getSystemService(Context.LOCATION_SERVICE) as LocationManager
//        return locationManager.isProviderEnabled(LocationManager.GPS_PROVIDER) || locationManager.isProviderEnabled(
//            LocationManager.NETWORK_PROVIDER
//        )
//    }


    private fun checkPermissions(): Boolean {
        if (ActivityCompat.checkSelfPermission(
                this.activity!!,
                Manifest.permission.ACCESS_COARSE_LOCATION
            ) == PackageManager.PERMISSION_GRANTED &&
            ActivityCompat.checkSelfPermission(
                this.activity!!,
                Manifest.permission.ACCESS_FINE_LOCATION
            ) == PackageManager.PERMISSION_GRANTED
        ) {
            return true
        }
        return false
    }

    //check location permission
    private fun requestPermissions() {
        ActivityCompat.requestPermissions(
            this.activity!!
            ,
            arrayOf(
                Manifest.permission.ACCESS_COARSE_LOCATION,
                Manifest.permission.ACCESS_FINE_LOCATION
            ),
            PERMISSION_ID
        )
    }

    //request location permission
    override fun onRequestPermissionsResult(
        requestCode: Int,
        permissions: Array<String>,
        grantResults: IntArray
    ) {
        if (requestCode == PERMISSION_ID) {
            if ((grantResults.isNotEmpty() && grantResults[0] == PackageManager.PERMISSION_GRANTED)) {

                mFusedLocationClient.lastLocation.addOnCompleteListener(this.activity!!) { task ->
                    val location: Location? = task.result

                    if (location == null) {
                        requestNewLocationData()
                    } else {
                        latitude = location.latitude
                        longitude = location.longitude
                        // Call API
                    }
                }
                requestNewLocationData()
            } else {
                getLastLocation()
            }
        }
    }

    //get address from location
    var addresses: List<Address> = emptyList()
    private fun getAddress(): Boolean {
//        showDialog()
        var flag = false
        locationAddress = ""
        try {
            val geocoder = Geocoder(context, Locale.getDefault())
            addresses = geocoder.getFromLocation(latitude,
                longitude, 1
            ) // Here 1 represent max location result to returned, by documents it recommended 1 to 5
            //null checking
            val address_size = addresses.size
            if (address_size > 0) {
                locationAddress = addresses.get(0)
                    .getAddressLine(0) // If any additional address line present than only, check with max available address lines by getMaxAddressLineIndex()
                flag = true
            }

        } catch (ioException: IOException) {
            val errorMessage = getString(string.service_not_available)
            Log.e(ContentValues.TAG, errorMessage + " saf not avail", ioException)
        }

        dismissDialog()
        return flag
    }

    private fun processStatus(resource: ResourceStatus) {

        when (resource.status) {
            StatusType.SUCCESS -> {
                dismissDialog()
//                Toast.makeText(context, "Photo Uploaded Successfully.", Toast.LENGTH_SHORT).show()
            }
            StatusType.EMPTY_RESPONSE -> {
                dismissDialog()
            }
            StatusType.PROGRESSING -> {
                showDialog()
            }
            StatusType.SWIPE_RELOADING -> {

            }
            StatusType.ERROR -> {
//                var fail_status = "Failed to update image. Please try again."
//                Toast.makeText(context, fail_status, Toast.LENGTH_SHORT).show()
                dismissDialog()

            }
            StatusType.LOADING_MORE -> {
                // CommonUtils().showSnackbar(binding.root, "Loading more..")
            }
            StatusType.NO_NETWORK -> {
                val internet_failure = "Please check your internet connection."
                Toast.makeText(context, internet_failure, Toast.LENGTH_SHORT).show()
            }
            StatusType.SESSION_EXPIRED -> {
//                var session_expired = "Invalid credentials. Login failed"
//                Toast.makeText(this, session_expired, Toast.LENGTH_SHORT).show()
            }
        }
    }


    ///


}   


导致错误的行是

uncompressed.compress(Bitmap.CompressFormat.JPEG,imageQuality.toInt(),byteArrayOutputStream)

firebase crashAnalytics 控制台中显示的错误日志:

Caused by java.lang.NullPointerException: Attempt to invoke virtual method 'boolean android.graphics.Bitmap.compress(android.graphics.Bitmap$CompressFormat, int, java.io.OutputStream)' on a null object reference
       at com.axionz.shopapp.ui.tabfragment.PhotoUploadFragment.onActivityResult(PhotoUploadFragment.kt:353)
       at androidx.fragment.app.FragmentActivity.onActivityResult(FragmentActivity.java:170)
       at android.app.Activity.dispatchActivityResult(Activity.java:8464)
       at android.app.ActivityThread.deliverResults(ActivityThread.java:5355)
       at android.app.ActivityThread.performResumeActivity(ActivityThread.java:4755)
       at android.app.ActivityThread.handleResumeActivity(ActivityThread.java:4810)
       at android.app.servertransaction.ResumeActivityItem.execute(ResumeActivityItem.java:52)
       at android.app.servertransaction.TransactionExecutor.executeLifecycleState(TransactionExecutor.java:187)
       at android.app.servertransaction.TransactionExecutor.execute(TransactionExecutor.java:102)
       at android.app.ActivityThread$H.handleMessage(ActivityThread.java:2307)
       at android.os.Handler.dispatchMessage(Handler.java:106)
       at android.os.Looper.loop(Looper.java:254)
       at android.app.ActivityThread.main(ActivityThread.java:8243)
       at java.lang.reflect.Method.invoke(Method.java)
       at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:612)
       at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1006)
 

I am getting a NullPointerException when trying to take a photo on camera application and upload it on to the server side, but some devices it works fine, and some getting issues. i don't know what is the issues, in some devices it works once and getting crashed.

the issues are identified by using firebase CrashAnalytics.

the fragment class.

class PhotoUploadFragment : BaseFragment() {

    private lateinit var viewModel: SelectOptionViewModel

    //define caseId type
    private var caseId: String? = ""

    //define caseNo type
    private var caseNo: String? = ""

    //define image clarity
    private var imageClarity: String? = ""

    //define image width
    private var imageWidth: String? = ""

    //define image height
    private var imageHeight: String? = ""

    //location
    lateinit var mFusedLocationClient: FusedLocationProviderClient

    //random id
    val PERMISSION_ID = 42

    //Initialize lat and long  to get loc address
    var longitude = 0.0
    var latitude = 0.0

    //Capture bitmap image
    var capturedBitmap = BitmapFactory.decodeStream(null)

    //Set timestamp when giving name while saving image
    var addrTimeStamp = ""

    //Initialize location address
    var locationAddress = ""

    companion object {
        private var args: Bundle? = null

        //pass the argument that needs to be displayed
        fun newInstance(case_id: String, case_number: String): Fragment {
//            fun newInstance(case_id: String, case_number: String): Fragment {
            args = Bundle()
            //pass the value caseId
            args!!.putString(CASE_ID, case_id)
            //pass the value caseNo
            args!!.putString(CASE_NO, case_number)
            val fragment = PhotoUploadFragment()
            fragment.arguments = args
            return fragment
        }
    }

    override fun onCreateView(
        inflater: LayoutInflater,
        container: ViewGroup?,
        savedInstanceState: Bundle?
    ): View {
        //setup view model
        viewModel = ViewModelProviders.of(this)[SelectOptionViewModel::class.java]
//        homeViewModel = ViewModelProviders.of(this)[HomeViewModel::class.java]
        val view: View = inflater.inflate(
            layout.fragment_tab_photo_upload,
            container,
            false
        )
        //get caseId
        caseId = arguments?.getString(CASE_ID)

        //get caseNo
        caseNo = arguments?.getString(CASE_NO)
        if (caseNo == null || caseNo == "") {
            caseNo = "Nil"
        }

        //get imageClarity
        imageClarity = PrefsHelper().getPref<String>(Constants.IMAGE_CLARITY)

        //get imageWidth
        imageWidth = PrefsHelper().getPref<String>(Constants.IMAGE_WIDTH)

        //get imageHeight
        imageHeight = PrefsHelper().getPref<String>(Constants.IMAGE_HEIGHT)

        mFusedLocationClient = LocationServices.getFusedLocationProviderClient(this.activity!!)
        return view

    }

    override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
        //to clear all the data inside the fragment to avoid multiple API calls
        viewModel.imageUploadresponseLiveData.value = null

        //to enable upload btn only after image is taken
        photo_upload_button_upload.isEnabled = false

        getLastLocation()
        setUpListeners()
        setupObservers()
    }

    private fun setupObservers() {
        viewModel.imageUploadresponseLiveData.observe(this, androidx.lifecycle.Observer {
            if (it != null) {
                //photo upload success
                if (it.success == 1 && it.result.success == 1) {
                    Toast.makeText(context, "Image uploaded successfully.", Toast.LENGTH_SHORT)
                        .show()
                    //delete file after upload
                    val root = Environment.getExternalStorageDirectory().toString()
                    val myDir = File(root + "/CV App/nomedia/images/")
                    myDir.deleteRecursively()
                    photo_upload_imageview_photo.setImageBitmap(null)
                    //to enable upload btn only after image is taken
                    photo_upload_button_upload.isEnabled = false
                }
                //photo upload fail
                else {
                    Toast.makeText(
                        context,
                        "Failed to update image. Please try again.",
                        Toast.LENGTH_SHORT
                    ).show()
                }
            }
        })
        //observe API call status
        viewModel.imageUploadAPICallStatus.observe(this, androidx.lifecycle.Observer {
            processStatus(it)
        })
    }


    private fun setUpListeners() {

        photo_upload_button_open.setOnClickListener {
            //Check camera permission
            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
                if (checkSelfPermission(
                        this.activity!!,
                        Manifest.permission.CAMERA
                    ) != PackageManager.PERMISSION_GRANTED
                ) {
                    ActivityCompat.requestPermissions(
                        this.activity!!,
                        arrayOf(Manifest.permission.CAMERA),
                        1
                    )
                }

            }
            //Check storage permission
            if (ActivityCompat.checkSelfPermission(
                    this.activity!!,
                    Manifest.permission.WRITE_EXTERNAL_STORAGE
                ) != PackageManager.PERMISSION_GRANTED
            ) {

                ActivityCompat.requestPermissions(
                    this.activity!!,
                    arrayOf(Manifest.permission.WRITE_EXTERNAL_STORAGE), REQUEST_PERM_WRITE_STORAGE
                )

            }
            //if permission is allowed,open camera
            else {
                startCamera()
            }

            photo_upload_button_upload.setOnClickListener {
                showDialogUpload()
            }

        }
    }


    private fun startCamera() {

        Intent(MediaStore.ACTION_IMAGE_CAPTURE).also { cameraIntent ->
            // Ensure that there's a camera activity to handle the intent
            cameraIntent.resolveActivity(context!!.packageManager)?.also {
                // Create the File where the photo should go
                val photoFile: File? = try {
                    createImageFile()
                } catch (ex: IOException) {
                    // Error occurred while creating the File
                    //...
                    null
                }
                //    Continue only if the File was successfully created
                photoFile?.also {
                    val photoURI: Uri = FileProvider.getUriForFile(
                        this.activity!!,
                        "com.xyzshopapp.fileprovider",
                        it
                    )
                    cameraIntent.putExtra(MediaStore.EXTRA_OUTPUT, photoURI)
                    cameraIntent.putExtra("return-data", true)
                    this.startActivityForResult(cameraIntent, ACTION_IMAGE_CAPTURE)
                }
            }
        }
    }


    /**
     * Create external image file, this file will be passed to Camera for saving the captured image
     */
    @Throws(IOException::class)
    private fun createImageFile(): File {

        // Create an image file name
        val timeStamp: String = SimpleDateFormat("yyyyMMdd_HHmmss").format(Date())
        //Set timestamp to addrTimeStamp
        addrTimeStamp = timeStamp
        val root = Environment.getExternalStorageDirectory().toString()
        val myDir = File("$root/CV App/nomedia/images")

        myDir.mkdirs()

        return File.createTempFile(
            "JPG_${addrTimeStamp}_", /* prefix */
            ".jpg", /* suffix */
            myDir /* directory */
        ).apply {
            // Save a file: path for use with ACTION_VIEW intents
            fileTemp = this
            //Save the complete file path to string
            imageFileName = this.toURI().path.toString()

        }
    }

    //show thumbnail
    override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
        super.onActivityResult(requestCode, resultCode, data)

        if (resultCode == Activity.RESULT_OK ) {
            when (requestCode) {
                ACTION_IMAGE_CAPTURE -> {
                    val imageQuality = imageClarity
                    val byteArrayOutputStream = ByteArrayOutputStream()

                    //Decode file to bitmap
                    capturedBitmap = BitmapFactory.decodeFile(imageFileName)


                    val a = capturedBitmap
                    val destinationHeight = imageHeight
                    val destinationWidth = imageWidth
                    var imageToScale = capturedBitmap

                    //test
                    var uncompressed = capturedBitmap
                    if (destinationHeight != null) {
                        if (destinationWidth != null) {
                            if (destinationHeight.toInt() > 0 && destinationWidth.toInt() > 0 && imageToScale != null) {
                                val width = imageToScale.width
                                val height = imageToScale.height

                                //Calculate the max changing amount and decide which dimension to use
                                val widthRatio = destinationWidth.toFloat() / width.toFloat()
                                val heightRatio = destinationHeight.toFloat() / height.toFloat()

                                //Use the ratio that will fit the image into the desired sizes
                                var finalWidth = floor((width * widthRatio).toDouble()).toInt()
                                var finalHeight = floor((height * widthRatio).toDouble()).toInt()
                                if (finalWidth > destinationWidth.toInt() || finalHeight > destinationHeight.toInt()) {
                                    finalWidth = floor((width * heightRatio).toDouble()).toInt()
                                    finalHeight = floor((height * heightRatio).toDouble()).toInt()
                                }

                                //Scale given bitmap to fit into the desired area
                                imageToScale = Bitmap.createScaledBitmap(imageToScale, finalWidth, finalHeight, false)

                                //Created a bitmap with desired sizes
                                val scaledImage =
                                    Bitmap.createBitmap(destinationWidth.toInt(), destinationHeight.toInt(), Bitmap.Config.ARGB_8888)
                                uncompressed = imageToScale
                            }
                        }
                    }

                    //compress by quality
                    if (imageQuality != null) {
                        uncompressed.compress(
                            Bitmap.CompressFormat.JPEG,
                            imageQuality.toInt(),
                            byteArrayOutputStream
                        )
                       /*try{

                       }catch (e:Exception)
                       {
                           println("this is exception $e")
                       }*/

                    }
                    val byteArray = byteArrayOutputStream.toByteArray()
                    //Encode bitmap to file
                    val compressedImageFile = FileOutputStream(imageFileName)
                    compressedImageFile.write(byteArray)
                    compressedImageFile.flush()
                    compressedImageFile.close()
                    //Set image in thumbnail
                    photo_upload_imageview_photo.setImageBitmap(a)
                    //to enable upload btn only after image is taken
                    photo_upload_button_upload.isEnabled = true
                }
                else -> {
                    Toast.makeText(context, "Unrecognized request code.", Toast.LENGTH_SHORT).show()
                }
            }

        }

    }

    //popup box for uploading photo
    fun showDialogUpload() {
        val dialog = Dialog(context!!)
        dialog.requestWindowFeature(Window.FEATURE_NO_TITLE)
        dialog.setCancelable(true)
        dialog.setContentView(layout.photo_upload)

        val photo_upload_submit =
            dialog.findViewById(com.xyz.shopapp.R.id.image_button_submit) as Button
        val spinner =
            dialog.findViewById(com.xyz.shopapp.R.id.photo_upload_spinner_image_name) as Spinner
        //get array of image names
        val imageName = (PrefsHelper().getPref<String>("ImageName"))

        //convert array to string
        val gson = Gson()
        val imageNameList = gson.fromJson(imageName, Array<String>::class.java).asList()

        //dropdown menu
        if (spinner != null) {
            val adapter =
                ArrayAdapter<String>(context!!, android.R.layout.simple_spinner_item, imageNameList)
            // Set layout to use when the list of choices appear
            adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item)
            // Set Adapter to Spinner
            spinner.adapter = adapter

            //get image name
            var itemSpinnerSelected = ""
            spinner.onItemSelectedListener = object : AdapterView.OnItemSelectedListener {
                override fun onItemSelected(
                    parent: AdapterView<*>,
                    view: View,
                    position: Int,
                    id: Long
                ) {
                    // Get the selected item
                    itemSpinnerSelected = "${parent.getItemAtPosition(position)}"
                }

                override fun onNothingSelected(parent: AdapterView<*>) {
                    // Another interface callback
                }
            }

            photo_upload_submit.setOnClickListener {

                if (getAddress()) {
                    viewModel.submitImageData(
                        caseId, caseNo,
                        imageFileName, latitude, longitude, itemSpinnerSelected, locationAddress
                    )
//                    viewModel.submitImageData(
//                        caseId, caseNo,
//                        imageFileName, latitude, longitude, itemSpinnerSelected, locationAddress
//                    )
//                viewModel.submitImageData(caseId,caseNo,rootDir + "/CV App/nomedia/images/avc6937492103605367617.jpg",latitude,longitude,itemSpinnerSelected, locationAddress)
//                dismissDialog()
//                val progressBar = findViewById(com.xyz.shopapp.R.id.progresbar) as ProgressBar
//                progressBar.visibility = View.INVISIBLE

                }
                dialog.dismiss()
            }

        }
        dialog.show()
    }

    //get location
    //check whether location is enabled for application
    @SuppressLint("MissingPermission")
    private fun getLastLocation() {
//       var latitude = 0.0
        if (checkPermissions()) {
            //if (isLocationEnabled()) {

                     mFusedLocationClient.lastLocation.addOnCompleteListener(this.activity!!) { task ->
                         val location: Location? = task.result

                         if (location == null) {
                             requestNewLocationData()
                         } else {
                             latitude = location.latitude
                             longitude = location.longitude
                             getAddress()
                         }
                     }

            /*mFusedLocationClient.lastLocation.addOnCompleteListener(this.activity!!) { task ->
                var location: Location? = task.result

                if (location == null) {
                    requestNewLocationData()
                } else {
                    latitude = location.latitude
                    longitude = location.longitude
                    getAddress()
                }
            }*/
//            } else {
//                Toast.makeText(context, "Turn on your location.", Toast.LENGTH_LONG).show()
//                val intent = Intent(Settings.ACTION_LOCATION_SOURCE_SETTINGS)
//                startActivity(intent)
//            }


        } else {
            //requestPermissions()
            //Manifest.permission.ACCESS_COARSE_LOCATION, Manifest.permission.ACCESS_FINE_LOCATION

            //to get location in first try itself
            val coraseLocationPermission = checkSelfPermission(
                this.activity!!,
                Manifest.permission.ACCESS_COARSE_LOCATION
            )
            val accessFineLocation = checkSelfPermission(
                this.activity!!,
                Manifest.permission.ACCESS_FINE_LOCATION
            )

            if (coraseLocationPermission != PackageManager.PERMISSION_GRANTED && accessFineLocation != PackageManager.PERMISSION_GRANTED) {

                requestPermissions(
                    arrayOf(
                        Manifest.permission.ACCESS_COARSE_LOCATION,
                        Manifest.permission.ACCESS_FINE_LOCATION
                    ),
                    PERMISSION_ID
                )
            }
        }
    }

    @SuppressLint("MissingPermission")
    private fun requestNewLocationData() {


        val mLocationRequest = LocationRequest()
        mLocationRequest.priority = LocationRequest.PRIORITY_HIGH_ACCURACY
        mLocationRequest.interval = 0
        mLocationRequest.fastestInterval = 0
        mLocationRequest.numUpdates = 1

        mFusedLocationClient = LocationServices.getFusedLocationProviderClient(this.activity!!)
        mFusedLocationClient.requestLocationUpdates(
            mLocationRequest, mLocationCallback,
            Looper.myLooper()

        )
    }

    private val mLocationCallback = object : LocationCallback() {
        override fun onLocationResult(locationResult: LocationResult) {
            val mLastLocation: Location = locationResult.lastLocation
            latitude = mLastLocation.latitude
            longitude = mLastLocation.longitude
        }
    }

//    private fun isLocationEnabled(): Boolean {
//        var locationManager: LocationManager = getSystemService(Context.LOCATION_SERVICE) as LocationManager
//        return locationManager.isProviderEnabled(LocationManager.GPS_PROVIDER) || locationManager.isProviderEnabled(
//            LocationManager.NETWORK_PROVIDER
//        )
//    }


    private fun checkPermissions(): Boolean {
        if (ActivityCompat.checkSelfPermission(
                this.activity!!,
                Manifest.permission.ACCESS_COARSE_LOCATION
            ) == PackageManager.PERMISSION_GRANTED &&
            ActivityCompat.checkSelfPermission(
                this.activity!!,
                Manifest.permission.ACCESS_FINE_LOCATION
            ) == PackageManager.PERMISSION_GRANTED
        ) {
            return true
        }
        return false
    }

    //check location permission
    private fun requestPermissions() {
        ActivityCompat.requestPermissions(
            this.activity!!
            ,
            arrayOf(
                Manifest.permission.ACCESS_COARSE_LOCATION,
                Manifest.permission.ACCESS_FINE_LOCATION
            ),
            PERMISSION_ID
        )
    }

    //request location permission
    override fun onRequestPermissionsResult(
        requestCode: Int,
        permissions: Array<String>,
        grantResults: IntArray
    ) {
        if (requestCode == PERMISSION_ID) {
            if ((grantResults.isNotEmpty() && grantResults[0] == PackageManager.PERMISSION_GRANTED)) {

                mFusedLocationClient.lastLocation.addOnCompleteListener(this.activity!!) { task ->
                    val location: Location? = task.result

                    if (location == null) {
                        requestNewLocationData()
                    } else {
                        latitude = location.latitude
                        longitude = location.longitude
                        // Call API
                    }
                }
                requestNewLocationData()
            } else {
                getLastLocation()
            }
        }
    }

    //get address from location
    var addresses: List<Address> = emptyList()
    private fun getAddress(): Boolean {
//        showDialog()
        var flag = false
        locationAddress = ""
        try {
            val geocoder = Geocoder(context, Locale.getDefault())
            addresses = geocoder.getFromLocation(latitude,
                longitude, 1
            ) // Here 1 represent max location result to returned, by documents it recommended 1 to 5
            //null checking
            val address_size = addresses.size
            if (address_size > 0) {
                locationAddress = addresses.get(0)
                    .getAddressLine(0) // If any additional address line present than only, check with max available address lines by getMaxAddressLineIndex()
                flag = true
            }

        } catch (ioException: IOException) {
            val errorMessage = getString(string.service_not_available)
            Log.e(ContentValues.TAG, errorMessage + " saf not avail", ioException)
        }

        dismissDialog()
        return flag
    }

    private fun processStatus(resource: ResourceStatus) {

        when (resource.status) {
            StatusType.SUCCESS -> {
                dismissDialog()
//                Toast.makeText(context, "Photo Uploaded Successfully.", Toast.LENGTH_SHORT).show()
            }
            StatusType.EMPTY_RESPONSE -> {
                dismissDialog()
            }
            StatusType.PROGRESSING -> {
                showDialog()
            }
            StatusType.SWIPE_RELOADING -> {

            }
            StatusType.ERROR -> {
//                var fail_status = "Failed to update image. Please try again."
//                Toast.makeText(context, fail_status, Toast.LENGTH_SHORT).show()
                dismissDialog()

            }
            StatusType.LOADING_MORE -> {
                // CommonUtils().showSnackbar(binding.root, "Loading more..")
            }
            StatusType.NO_NETWORK -> {
                val internet_failure = "Please check your internet connection."
                Toast.makeText(context, internet_failure, Toast.LENGTH_SHORT).show()
            }
            StatusType.SESSION_EXPIRED -> {
//                var session_expired = "Invalid credentials. Login failed"
//                Toast.makeText(this, session_expired, Toast.LENGTH_SHORT).show()
            }
        }
    }


    ///


}   


The line which causes the error is

uncompressed.compress(Bitmap.CompressFormat.JPEG,imageQuality.toInt(),byteArrayOutputStream)

error log shown in firebase crashAnalytics console:

Caused by java.lang.NullPointerException: Attempt to invoke virtual method 'boolean android.graphics.Bitmap.compress(android.graphics.Bitmap$CompressFormat, int, java.io.OutputStream)' on a null object reference
       at com.axionz.shopapp.ui.tabfragment.PhotoUploadFragment.onActivityResult(PhotoUploadFragment.kt:353)
       at androidx.fragment.app.FragmentActivity.onActivityResult(FragmentActivity.java:170)
       at android.app.Activity.dispatchActivityResult(Activity.java:8464)
       at android.app.ActivityThread.deliverResults(ActivityThread.java:5355)
       at android.app.ActivityThread.performResumeActivity(ActivityThread.java:4755)
       at android.app.ActivityThread.handleResumeActivity(ActivityThread.java:4810)
       at android.app.servertransaction.ResumeActivityItem.execute(ResumeActivityItem.java:52)
       at android.app.servertransaction.TransactionExecutor.executeLifecycleState(TransactionExecutor.java:187)
       at android.app.servertransaction.TransactionExecutor.execute(TransactionExecutor.java:102)
       at android.app.ActivityThread$H.handleMessage(ActivityThread.java:2307)
       at android.os.Handler.dispatchMessage(Handler.java:106)
       at android.os.Looper.loop(Looper.java:254)
       at android.app.ActivityThread.main(ActivityThread.java:8243)
       at java.lang.reflect.Method.invoke(Method.java)
       at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:612)
       at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1006)
 

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

眼角的笑意。 2025-01-22 17:37:33

请在您现有的代码上尝试以下方法可能会对您有所帮助,可能会从 api 28 更新访问内部存储上的数据目录和 Android 11 中的存储更新,您会遇到问题,因为您说它在某些设备中工作,但在某些设备上不起作用设备,请转到 https://developer.android.com/about/versions/11/privacy/storage
有关存储更新的详细信息。

您可以在 Android 10 的清单中使用 android:requestLegacyExternalStorage="true" 的一种方法,但这不是 Android 10 以上版本的解决方案。

Android 清单中的权限和提供程序

<!-- permission for media access -->
<uses-permission android:name="android.permission.CAMERA" />
<uses-feature android:name="android.hardware.camera" />
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />


<provider
        android:name="androidx.core.content.FileProvider"
        android:authorities="com.triassic.avapp.fileprovider"
        android:exported="false"
        android:grantUriPermissions="true">
       <meta-data
        android:name="android.support.FILE_PROVIDER_PATHS"
        android:resource="@xml/provider_paths" />
</provider>

provider_paths.xml

<?xml version="1.0" encoding="utf-8"?>
<paths xmlns:android="http://schemas.android.com/apk/res/android">
<external-path name="external_files" path="."/>
</paths>

您的活动类代码

class myActivityy:AppCompatActivity {
    private var ImageName: String? = null
    var capturedImageUri: Uri? = null
    fun launchCamer() {
        tv_take_photo.setOnClickListener(View.OnClickListener {
            try {
                ImageName = "Img_cm" + ".jpeg"
                val intent = Intent(MediaStore.ACTION_IMAGE_CAPTURE)
                if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
                    capturedImageUri = getPhotoFileUri(ImageName)
                    val resInfoList: List<ResolveInfo> = getActivity().getPackageManager()
                        .queryIntentActivities(intent, PackageManager.MATCH_DEFAULT_ONLY)
                    for (resolveInfo in resInfoList) {
                        val packageName = resolveInfo.activityInfo.packageName
                        getActivity().grantUriPermission(
                            packageName,
                            capturedImageUri,
                            Intent.FLAG_GRANT_WRITE_URI_PERMISSION or Intent.FLAG_GRANT_READ_URI_PERMISSION
                        )
                    }
                    intent.putExtra(MediaStore.EXTRA_OUTPUT, capturedImageUri)
                    try {
                        intent.putExtra("return-data", true)
                        startActivityForResult(intent, Constant.ACTION_REQUEST_CAMERA)
                    } catch (e: Exception) {
                        e.printStackTrace()
                    }
                } else {
                    val file: File = File(
                        getActivity().getExternalFilesDir(Environment.DIRECTORY_PICTURES)
                            .toString() + File.separator + ImageName
                    )
                    capturedImageUri = Uri.fromFile(file)
                    intent.putExtra(MediaStore.EXTRA_OUTPUT, capturedImageUri)
                    try {
                        intent.putExtra("return-data", true)
                        startActivityForResult(intent, Constant.ACTION_REQUEST_CAMERA)
                    } catch (e: Exception) {
                        e.printStackTrace()
                    }
                }
            } catch (e: Exception) {
                e.printStackTrace()
            }
        })
    }

    fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
        super.onActivityResult(requestCode, resultCode, data)
        try {
            if (resultCode == getActivity().RESULT_OK) {
                if (requestCode == Constant.ACTION_REQUEST_CAMERA) {
                    var thumbnail: Bitmap? = null
                    thumbnail = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
                        val takenPhotoUri = getPhotoFileUri(ImageName)
                        decodeSampledBitmapFromFileURI(getActivity(), takenPhotoUri, 1000, 1000)
                    } else {
                        decodeSampledBitmapFromFile(capturedImageUri!!.path, 1000, 1000)
                    }

                    //here you can get File and perform your next task according to your requirement
                    if (thumbnail != null) {
                        var imageFileEdit: File? = null
                        imageFileEdit = getTempFileImages(getActivity(), thumbnail, "Img_cm")
                    }
                }
            }
        } catch (e: Exception) {
            e.printStackTrace()
        }
    }

    /*Below code you can write in your Util class and then use*/
    private val isExternalStorageAvailable: Boolean
        private get() {
            val state = Environment.getExternalStorageState()
            return state == Environment.MEDIA_MOUNTED
        }

    fun getPhotoFileUri(fileName: String?): Uri? {
        try {
            if (isExternalStorageAvailable) {
                val mediaStorageDir: File =
                    File(getActivity().getExternalFilesDir(Environment.DIRECTORY_PICTURES), "")
                val outputFile = File(mediaStorageDir.path + File.separator + fileName)
                val outputFileUri: Uri = FileProvider.getUriForFile(
                    getActivity(),
                    "com.triassic.avapp.fileprovider", outputFile
                )
                // Create the storage directory if it does not exist
                if (!mediaStorageDir.exists() && !mediaStorageDir.mkdirs()) {
                    Logger.e(
                        Constant.PHOTO_DIRECTORY_NAME.toString() + " ",
                        "failed to create directory"
                    )
                }
                // Return the file target for the photo based on filename
                return outputFileUri
            }
        } catch (e: Exception) {
            e.printStackTrace()
        }
        return null
    }

    companion object {
        fun decodeSampledBitmapFromFile(path: String?, reqWidth: Int, reqHeight: Int): Bitmap? {
            try {
                val options = BitmapFactory.Options()
                options.inJustDecodeBounds = true
                BitmapFactory.decodeFile(path, options)
                val height = options.outHeight
                val width = options.outWidth
                options.inPreferredConfig = Bitmap.Config.RGB_565
                var inSampleSize = 1
                if (height > reqHeight) {
                    inSampleSize = Math.round(height.toFloat() / reqHeight.toFloat())
                }
                val expectedWidth = width / inSampleSize
                if (expectedWidth > reqWidth) {
                    inSampleSize = Math.round(width.toFloat() / reqWidth.toFloat())
                }
                options.inSampleSize = inSampleSize
                options.inJustDecodeBounds = false
                return BitmapFactory.decodeFile(path, options)
            } catch (e: Exception) {
                ExceptionHandler.printStackTrace(e)
            }
            return null
        }

        fun decodeSampledBitmapFromFileURI(
            activity: Activity,
            path: Uri?,
            reqWidth: Int,
            reqHeight: Int
        ): Bitmap? {
            try {
                val options = BitmapFactory.Options()
                options.inJustDecodeBounds = true
                MediaStore.Images.Media.getBitmap(activity.contentResolver, path)
                val height = options.outHeight
                val width = options.outWidth
                options.inPreferredConfig = Bitmap.Config.RGB_565
                var inSampleSize = 1
                if (height > reqHeight) {
                    inSampleSize = Math.round(height.toFloat() / reqHeight.toFloat())
                }
                val expectedWidth = width / inSampleSize
                if (expectedWidth > reqWidth) {
                    inSampleSize = Math.round(width.toFloat() / reqWidth.toFloat())
                }
                options.inSampleSize = inSampleSize
                options.inJustDecodeBounds = false
                return MediaStore.Images.Media.getBitmap(activity.contentResolver, path)
            } catch (e: Exception) {
                ExceptionHandler.printStackTrace(e)
            }
            return null
        }

        fun getTempFileImages(context: Context, bmap: Bitmap, name: String): File {
            val image_file =
                File(context.getExternalFilesDir(Environment.DIRECTORY_PICTURES), "$name.jpeg")
            val outStream: FileOutputStream
            try {
                outStream = FileOutputStream(image_file)
                val isComp = bmap.compress(Bitmap.CompressFormat.JPEG, 100, outStream)
                outStream.flush()
                outStream.close()
            } catch (e: FileNotFoundException) {
                e.printStackTrace()
            } catch (e: IOException) {
                e.printStackTrace()
            } catch (e: Exception) {
                e.printStackTrace()
            }
            return image_file
        }
    }
}

Please try the below way on your existing code may help you, May be update from api 28 Access to data directories on internal storage and Storage updates in Android 11 your are getting problem because you are saying it is working in some device and not in some device,Please go to https://developer.android.com/about/versions/11/privacy/storage
for detail about storage update.

one way you can use android:requestLegacyExternalStorage="true" in manifest for android 10, but it is not solution for above android 10.

Permission and provider in Android Manifest

<!-- permission for media access -->
<uses-permission android:name="android.permission.CAMERA" />
<uses-feature android:name="android.hardware.camera" />
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />


<provider
        android:name="androidx.core.content.FileProvider"
        android:authorities="com.triassic.avapp.fileprovider"
        android:exported="false"
        android:grantUriPermissions="true">
       <meta-data
        android:name="android.support.FILE_PROVIDER_PATHS"
        android:resource="@xml/provider_paths" />
</provider>

provider_paths.xml

<?xml version="1.0" encoding="utf-8"?>
<paths xmlns:android="http://schemas.android.com/apk/res/android">
<external-path name="external_files" path="."/>
</paths>

Your Activity Class Code

class myActivityy:AppCompatActivity {
    private var ImageName: String? = null
    var capturedImageUri: Uri? = null
    fun launchCamer() {
        tv_take_photo.setOnClickListener(View.OnClickListener {
            try {
                ImageName = "Img_cm" + ".jpeg"
                val intent = Intent(MediaStore.ACTION_IMAGE_CAPTURE)
                if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
                    capturedImageUri = getPhotoFileUri(ImageName)
                    val resInfoList: List<ResolveInfo> = getActivity().getPackageManager()
                        .queryIntentActivities(intent, PackageManager.MATCH_DEFAULT_ONLY)
                    for (resolveInfo in resInfoList) {
                        val packageName = resolveInfo.activityInfo.packageName
                        getActivity().grantUriPermission(
                            packageName,
                            capturedImageUri,
                            Intent.FLAG_GRANT_WRITE_URI_PERMISSION or Intent.FLAG_GRANT_READ_URI_PERMISSION
                        )
                    }
                    intent.putExtra(MediaStore.EXTRA_OUTPUT, capturedImageUri)
                    try {
                        intent.putExtra("return-data", true)
                        startActivityForResult(intent, Constant.ACTION_REQUEST_CAMERA)
                    } catch (e: Exception) {
                        e.printStackTrace()
                    }
                } else {
                    val file: File = File(
                        getActivity().getExternalFilesDir(Environment.DIRECTORY_PICTURES)
                            .toString() + File.separator + ImageName
                    )
                    capturedImageUri = Uri.fromFile(file)
                    intent.putExtra(MediaStore.EXTRA_OUTPUT, capturedImageUri)
                    try {
                        intent.putExtra("return-data", true)
                        startActivityForResult(intent, Constant.ACTION_REQUEST_CAMERA)
                    } catch (e: Exception) {
                        e.printStackTrace()
                    }
                }
            } catch (e: Exception) {
                e.printStackTrace()
            }
        })
    }

    fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
        super.onActivityResult(requestCode, resultCode, data)
        try {
            if (resultCode == getActivity().RESULT_OK) {
                if (requestCode == Constant.ACTION_REQUEST_CAMERA) {
                    var thumbnail: Bitmap? = null
                    thumbnail = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
                        val takenPhotoUri = getPhotoFileUri(ImageName)
                        decodeSampledBitmapFromFileURI(getActivity(), takenPhotoUri, 1000, 1000)
                    } else {
                        decodeSampledBitmapFromFile(capturedImageUri!!.path, 1000, 1000)
                    }

                    //here you can get File and perform your next task according to your requirement
                    if (thumbnail != null) {
                        var imageFileEdit: File? = null
                        imageFileEdit = getTempFileImages(getActivity(), thumbnail, "Img_cm")
                    }
                }
            }
        } catch (e: Exception) {
            e.printStackTrace()
        }
    }

    /*Below code you can write in your Util class and then use*/
    private val isExternalStorageAvailable: Boolean
        private get() {
            val state = Environment.getExternalStorageState()
            return state == Environment.MEDIA_MOUNTED
        }

    fun getPhotoFileUri(fileName: String?): Uri? {
        try {
            if (isExternalStorageAvailable) {
                val mediaStorageDir: File =
                    File(getActivity().getExternalFilesDir(Environment.DIRECTORY_PICTURES), "")
                val outputFile = File(mediaStorageDir.path + File.separator + fileName)
                val outputFileUri: Uri = FileProvider.getUriForFile(
                    getActivity(),
                    "com.triassic.avapp.fileprovider", outputFile
                )
                // Create the storage directory if it does not exist
                if (!mediaStorageDir.exists() && !mediaStorageDir.mkdirs()) {
                    Logger.e(
                        Constant.PHOTO_DIRECTORY_NAME.toString() + " ",
                        "failed to create directory"
                    )
                }
                // Return the file target for the photo based on filename
                return outputFileUri
            }
        } catch (e: Exception) {
            e.printStackTrace()
        }
        return null
    }

    companion object {
        fun decodeSampledBitmapFromFile(path: String?, reqWidth: Int, reqHeight: Int): Bitmap? {
            try {
                val options = BitmapFactory.Options()
                options.inJustDecodeBounds = true
                BitmapFactory.decodeFile(path, options)
                val height = options.outHeight
                val width = options.outWidth
                options.inPreferredConfig = Bitmap.Config.RGB_565
                var inSampleSize = 1
                if (height > reqHeight) {
                    inSampleSize = Math.round(height.toFloat() / reqHeight.toFloat())
                }
                val expectedWidth = width / inSampleSize
                if (expectedWidth > reqWidth) {
                    inSampleSize = Math.round(width.toFloat() / reqWidth.toFloat())
                }
                options.inSampleSize = inSampleSize
                options.inJustDecodeBounds = false
                return BitmapFactory.decodeFile(path, options)
            } catch (e: Exception) {
                ExceptionHandler.printStackTrace(e)
            }
            return null
        }

        fun decodeSampledBitmapFromFileURI(
            activity: Activity,
            path: Uri?,
            reqWidth: Int,
            reqHeight: Int
        ): Bitmap? {
            try {
                val options = BitmapFactory.Options()
                options.inJustDecodeBounds = true
                MediaStore.Images.Media.getBitmap(activity.contentResolver, path)
                val height = options.outHeight
                val width = options.outWidth
                options.inPreferredConfig = Bitmap.Config.RGB_565
                var inSampleSize = 1
                if (height > reqHeight) {
                    inSampleSize = Math.round(height.toFloat() / reqHeight.toFloat())
                }
                val expectedWidth = width / inSampleSize
                if (expectedWidth > reqWidth) {
                    inSampleSize = Math.round(width.toFloat() / reqWidth.toFloat())
                }
                options.inSampleSize = inSampleSize
                options.inJustDecodeBounds = false
                return MediaStore.Images.Media.getBitmap(activity.contentResolver, path)
            } catch (e: Exception) {
                ExceptionHandler.printStackTrace(e)
            }
            return null
        }

        fun getTempFileImages(context: Context, bmap: Bitmap, name: String): File {
            val image_file =
                File(context.getExternalFilesDir(Environment.DIRECTORY_PICTURES), "$name.jpeg")
            val outStream: FileOutputStream
            try {
                outStream = FileOutputStream(image_file)
                val isComp = bmap.compress(Bitmap.CompressFormat.JPEG, 100, outStream)
                outStream.flush()
                outStream.close()
            } catch (e: FileNotFoundException) {
                e.printStackTrace()
            } catch (e: IOException) {
                e.printStackTrace()
            } catch (e: Exception) {
                e.printStackTrace()
            }
            return image_file
        }
    }
}
歌枕肩 2025-01-22 17:37:33

对象 capturedBitmap 为 null

下面的代码可能对您有帮助

val uri = //image uri
val options: BitmapFactory.Options = new BitmapFactory.Options()
options.inJustDecodeBounds = true
val bitmap = BitmapFactory.decodeStream(activity?.contentResolver.openInputStream(uri), null, options)

The object capturedBitmap is null

The below code may help you

val uri = //image uri
val options: BitmapFactory.Options = new BitmapFactory.Options()
options.inJustDecodeBounds = true
val bitmap = BitmapFactory.decodeStream(activity?.contentResolver.openInputStream(uri), null, options)
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文