Android Development--photo, crop and save as avatar Error: Crop picture cannot be saved

Source: Internet
Author: User

 

In the development of an Android project, you need to get pictures or photos from the album, and then crop them as avatars. Because I was the first time to develop Android, but also to Android now more and more restrictions on permissions do not understand, the debug process is really abnormal heart plug ah.

Gossip does not say (Wen at the end of slow words, I began to find some code on the Internet to try to use the project, but even a photo or photos from the album to select frequently error (should still be due to the SD card permissions and so on), tossing a night did not solve, the next day or honestly look at the first line of code, learn to write Here I simply comb the process (for the explanation of the problem that the picture cannot be saved after cropping, jump directly to the horizontal line):

    •  Call the phone camera to take a photo:

 

 //create a file to store the photo taken by the camera, here I named My_head_image.jpg, and put it in//the mobile SD card is applied in the associated cache.              /* File Outputimage = new file (Getexternalcachedir (), "my_head_image.jpg");                    try {if (outputimage.exists ()) {outputimage.delete ();                } outputimage.createnewfile ();                } catch (IOException e) {e.printstacktrace (); }//The file object is converted to a URI object, and the system version is determined first, Android7.0 later versions and previous versions do not//too the same              if (Build.VERSION.SDK_INT >=) {Imageuri = Fileprovider.geturiforfile (changemydetails.this, "com.                Example.write.fileprovider ", outputimage); } else {Imageuri = Uri.fromfile (outputimage); */
File Outputimage = new file (Environment.getexternalstoragedirectory (), "my_head_image.jpg");
String path = Outputimage.getabsolutepath ();
LOG.I ("Changemydetails", "Outputimage path is" +path);
try {
if (outputimage.exists ()) {
Outputimage.delete ();
}
Outputimage.createnewfile ();
} catch (IOException e) {
     E.printstacktrace ();
}

Imageuri = Uri.fromfile (outputimage);
  Start the camera program
Intent Intent = new Intent ("Android.media.action.IMAGE_CAPTURE");
Intent.putextra (Mediastore.extra_output, Imageuri);
Startactivityforresult (Intent, Take_photo);

 The orange part of the code is "the first line of code", if the picture after the image is not cropped directly as a picture, this paragraph is no problem, but you know, and then collapsed . Here first create the Ffile object, for storing the captured photos, and save it in the SD card application associated cache directory, call Getcachedir () to get this directory, the specific path is/sdcard/android/data/< your package name >/cache. Why do you put it here? since the Android6.0 system starts, the read-write SD card is considered a dangerous privilege, how to put it in other directories, to do permission processing at runtime, and to use the app associated directory to skip this step. Note: In this case I planted a hidden danger that cannot be saved after cropping. ( orange The following correction code is something, because also involves the permission problem, I will say later, so you see here happy paste into your project will still error )

  Then the system version is judged, and the Fileprovider Geturiforfile () method encapsulates the file object as a URI object. The Geturiforfile () method receives 3 parameters, the first being the context object that is required to be passed in, and the second can be any unique string (registered in the following manifest.xml <procider> android:authority), and the third is the file object to be encapsulated. This step is added because the Android7.0 system starts by using a local URI that is considered unsafe and throws a Fileuriexposedexception exception. Fileprovider is a special content provider that can selectively share encapsulated URIs to the outside and be more secure.

For content providers, also register in Manifest,xml:

<providerAndroid:name= "Android.support.v4.content.FileProvider"android:authorities= "Com.example.write.fileprovider"android:exported= "false"android:granturipermissions= "true">            <Meta-dataAndroid:name= "Android.support.FILE_PROVIDER_PATHS"Android:resource= "@xml/provider_paths"/>        </provider>

Where theAndroid:authorities property value must be the same as the second parameter in the Fileprovider.geturiforfile () method , in addition, use <meta-data> to specify the URI's shared path, and referencing @xml/provider_paths resources, this resource needs to be created by itself.

Right-click the Res directory →new→directory, create an XML directory, and right-click the XML directory →new→file to create a provider_paths.xml file:

<? XML version= "1.0" encoding= "Utf-8" ?> <  xmlns:android= "http://schemas.android.com/apk/res/android">     <name= "my_images"  path= "." /> </ Paths >

Where External-path is used to specify URI sharing, the Name property value is customized, and the path property is null to share the entire SD card.

    •  Crop photos:

when taking pictures, use     Startactivityforresult (Intent, Take_photo) to initiate the activity, so the note has the result returned to the Onactivityresult () method, and the subsequent cropping is performed after the photo is successful. The Onactivityresult () method also has the option to select a picture from the album, and then return to execute after the successful cropping, and I post it together.

@Override
protected voidOnactivityresult (intRequestcode,intResultCode, Intent data) {        //The user does not perform a valid operation and returns        if(Requestcode = =result_canceled) {Toast.maketext (Getapplication (),Cancel, Toast.length_long). Show (); return; }        Switch(requestcode) { CaseFrom_gallery:if(ResultCode = =RESULT_OK) {                    if(Build.VERSION.SDK_INT >= 19) {                        //4.4 above system useHandleimageonkitkat (data); } Else{handleimagebeforekitkat (data); }                }                 Break;  CaseTake_photo://Crop PhotosCroprawphoto (Imageuri);  Break;  CaseResult_request_code:if(Cropimguri! =NULL) {                    Try {Bitmap headimage=Bitmapfactory.decodestream (Getcontentresolver (). Openinputstream (Cropimguri));                    Headimagebutton.setimagebitmap (Headimage); } Catch(Exception e) {e.printstacktrace (); }                }Else{Toast.maketext ( This, "Cropimguri is empty! ", Toast.length_short). Show (); }                 Break; }    }

public void Croprawphoto (Uri uri) {
//Create file files to store cropped photos
File Cropimage = new file (Environment.getexternalstoragedirectory (), "crop_image.jpg");
String path = Cropimage.getabsolutepath ();
try {
if (cropimage.exists ()) {
Cropimage.delete ();
}
Cropimage.createnewfile ();
} catch (IOException e) {
E.printstacktrace ();
}
Cropimguri = Uri.fromfile (cropimage);
Intent Intent = new Intent ("Com.android.camera.action.CROP");
//Set Source address URI
Intent.setdataandtype (Imageuri, "image/*");
Intent.putextra ("Crop", "true");
Intent.putextra ("Aspectx", 1);
Intent.putextra ("Aspecty", 1);
Intent.putextra ("Outputx", 200);
Intent.putextra ("Outputy", 200);
Intent.putextra ("scale", true);
//Set destination address URI
Intent.putextra (Mediastore.extra_output, Cropimguri);
Format Picture
Intent.putextra ("OutputFormat", Bitmap.CompressFormat.JPEG.toString ());
Intent.putextra ("Return-data", false);
Intent.putextra ("Nofacedetection", true); No Face Detection
Startactivityforresult (Intent, Result_request_code);
}

Startactivityforresult (Intent, result_request_code); After execution, jump to Onactivityresult () to execute case Result_request_code: section, the code has been posted. is to call the Bitmapfactory.decodestream () method to resolve the Cropimage to the bitmap object.

Then, start running.

  So, here's the problem (guess: Because the cropped image is a lot of memory to save to the cache, Android doesn't allow you to do this):

Here's a blog post explaining:   http://www.cnblogs.com/tianzhijiexian/p/4059006.html

  at first, I was the photo taken by the camera and cropped photos are in the associated application cache, is the front orange part of the operation of the code ( posted code is i later corrected the code of No Problem ). It is normal to start the camera program to take pictures and save the pictures. However, after the cropped picture cannot be saved to the cache directory, I followed/sdcard/android/data/< your package Name>/cache path opened to look at, is 0kb.

Originally I suspected that the cache storage may be problematic, but also want to take photos can be well preserved why not save after cropping it? It's not fair! So, I started to change the other areas I suspect, searching the internet for a long time or not solve the answer. Finally, I decided to verify the last conjecture: The cropped image could not be saved to the cache in some strange way . Just do what you say:

step1 : Change the file path to normal, that is, file outputimage = new File (Getexternalcachedir ()," my_head_image.jpg ") Replace with file outputimage = new File (Environment.getexternalstoragedirectory ()," my_head_image.jpg "); Similarly change file cropimage = New File ( Environment.getexternalstoragedirectory (), "crop_image.jpg");

  step2: Registering Permissions in manifest.xml:<uses-permission android: name=" Android.permission.WRITE_EXTERNAL_STORAGE "/>

step3: To get here, I ran it once, or an exception, or the permissions issue was not finished, and I added this in the OnCreate () method:

New StrictMode.VmPolicy.Builder ();        Strictmode.setvmpolicy (Builder.build ());         if (Build.VERSION.SDK_INT >= build.version_codes. JELLY_BEAN_MR2) {            builder.detectfileuriexposure ();        }

Re-run, It works!

End of text nagging

  I will not speak about Strictmode (heart tired + lazy).

You know, in the Internet to find solutions to solve the problem requires skills, luck, time, a large circle, for me, I find solution on the internet probably will spend a lot of time, many problems that are other people encountered trouble and solution, not necessarily applicable to themselves, but they still have to die to more try, Then toss an afternoon or a night, thinking that it is better to waste life in a different way at this time, such as watching a play, sleeping , chatting with friends, and eating ...

For Android, too long ago the solution may not be suitable for now, such as the increasingly stringent authority issues.

Sometimes, in the online blind, it is better to read a book, figuring out exactly how a process, where will be wrong, but will be faster to solve problems, but also more rewarding.

All in all, to be efficient in solving problems, you have to understand the entire code process.

Well, now I'm going to waste my life in a different way ...

 

Android Development--photo, crop and save as avatar Error: Crop picture cannot be saved

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.