Android uploads images by calling the system to take photos and select images from the album

Source: Internet
Author: User

Android uploads images by calling the system to take photos and select images from the album
Android uploads images by calling the system to take photos and select images from the album

Preface:
The high-rise buildings are flat, and everything starts at the bottom. It is almost four months away from the previous blog. The first blog post was published on the afternoon of June 1, December 17, 2015. It is now July 1, April 6, 2016. The time interval is too long. I can't see it myself. Why? Of course it is my own reason. In fact, there is a lot of time for blog posts, but these times have been spent on DOTA (too young ). Forgive me for my mistakes .......
I. Overview:
Currently, almost all applications use the image upload function. to upload images, you must first select images. This article does not address how to upload images to the server (the interaction between each project and the server is different, therefore, you do not need to write the code for uploading images to the server. This is just a brief introduction to the image selection, and does not involve processing and cropping the rounded corners of the image. This article mainly involves the following simple knowledge points:

Simple call system photo taking and system photo album Selection Use the GridView to dynamically add images Tips for using Adapter In Fragment, how does one obtain data by calling the system to take a photo (interface callback)

II. Implementation:
Let's first look at the project directory:

One Adapter and two activities, one Fragment and one tool class. Some people have doubts here. Why are there two activities? Aren't there three? That's right. TheoreticallyChooseActivity,ChooseFragmentActivity,BaseActivityHere, BaseActivity simulates the actual project to extract the public code from the Activity. It is not used as a view, so BaseActivity is not included.
ChooseActivity is a simulated Activity that calls the system to take photos and select images from the system album, put the ChooseFragmentActivity into the ChooseFragment simulation Fragment and call the system photo and system album to select the image. (here I have fixed the actual situation of a Fragment simulation project. In reality, one Activity has multiple Fragment ), imageUtils performs some simple image processing. SelectPicPopupWindow is a simple PopupWindow. UploadImageAdapter dynamically selects the Image Upload adapter.
Come First:


Effect shown in the figure: Click the default image to bring up the PopupWindow to allow the user to choose to take a photo or select an image from the album. (It is inconvenient to use the photo function in the simulator. I have tried it on several mobile phones, please go to the real machine to test). After you have selected an image, you can press and delete it. Here, you can select up to 6 images.

Simple call system photo taking and system photo album Selection
Let's first look at how to call the system to take photos and select images from the album:
Declare components and variables:

/*** Select the image return code */public final static int SELECT_IMAGE_RESULT_CODE = 200;/*** path of the currently selected image */public String mImagePath; /*** custom PopupWindow */private SelectPicPopupWindow menuWindow;

PopupWindow is displayed:

/*** Take a photo or select an image from the image library (in the form of PopupWindow) */public void showPicturePopupWindow () {menuWindow = new SelectPicPopupWindow (this, new OnClickListener () {@ Override public void onClick (View v) {// hide the pop-up window menuWindow. dismiss (); switch (v. getId () {case R. id. takePhotoBtn: // take a photo of takePhoto (); break; case R. id. pickPhotoBtn: // select the image pickPhoto (); break; case R. id. cancelBtn: // cancel break; default: break ;}}); menuWindow. showAtLocation (findViewById (R. id. choose_layout), Gravity. BOTTOM | Gravity. CENTER_HORIZONTAL, 0, 0 );}

The most important method is the takephoto method related to the photo. Some models do not return data after the photo is taken. You can only specify the storage path for the image after the photo is taken to solve this problem. The annotations are detailed. I will not explain them more here. However, when you specify a path, you may not be able to click OK to return the response after the photo is taken. Some mobile phones may even click and drop it. In this case, an error indicating a valid path is reported. I encountered an error in creating a file/xxxx after the obtained path associated with the application. I do not know why.

Private void takePhoto () {// before taking the photo, you should first determine whether the SD card has String SDState = Environment. getExternalStorageState (); if (SDState. equals (Environment. MEDIA_MOUNTED) {/*** specifies the image storage path, solve the problem where the data returned by the onActivityResult callback of some models is null * // obtain the path String imageFilePath = getExternalFilesDir (Environment. DIRECTORY_PICTURES ). getAbsolutePath (); SimpleDateFormat formatter = new SimpleDateFormat ("yyyyMMddHHmmss", Locale. CHIN A); // generate the image name String timestamp = "/" + formatter based on the current time. format (new Date () + ". jpg "; File imageFile = new File (imageFilePath, timestamp); // create and save the File mImagePath = imageFile by path. getAbsolutePath (); Uri imageFileUri = Uri. fromFile (imageFile); // retrieve the Uri Intent intent = new Intent (MediaStore. ACTION_IMAGE_CAPTURE); intent. putExtra (MediaStore. EXTRA_OUTPUT, imageFileUri); // tells the camera to output the image to the specified Uri startActivityForResu after shooting. Lt (intent, SELECT_IMAGE_RESULT_CODE);} else {Toast. makeText (this, "memory card does not exist! ", Toast. LENGTH_LONG). show ();}}

Use the GridView to dynamically add images
In fact, you are more concerned about the dynamic addition of items, item deletion, and other effects in the GridView:

Declare components and variables:

/*** Use the upload list */private upload list to control the path of the image to be uploaded.
  
   
DataList = new catalog list
   
    
();/*** Upload the image to the GridView */private GridView uploadGridView;/*** upload the image Adapter */private UploadImageAdapter adapter;
   
  

Initialize the GridView and Adapter:

UploadGridView = (GridView) findViewById (R. id. grid_upload_pictures); dataList. addLast (null); // initialize the first Add button data adapter = new UploadImageAdapter (this, dataList); uploadGridView. setAdapter (adapter); uploadGridView. setOnItemClickListener (mItemClick); uploadGridView. setOnItemLongClickListener (mItemLongClick );

Click monitoring and long-press monitoring of items in the GridView:

/*** Upload an image GridView Item click to listen */private OnItemClickListener mItemClick = new OnItemClickListener () {@ Override public void onItemClick (AdapterView
  Parent, View view, int position, long id) {if (parent. getItemAtPosition (position) = null) {// Add an image // showPictureDailog (); // showPicturePopupWindow () in Dialog format; // PopupWindow format }}}; /*** upload an image GridView Item long-pressed listener */private OnItemLongClickListener mItemLongClick = new OnItemLongClickListener () {@ Override public boolean onItemLongClick (AdapterView
  Parent, View view, int position, long id) {if (parent. getItemAtPosition (position )! = Null) {// long press to delete dataList. remove (parent. getItemAtPosition (position); adapter. update (dataList); // refresh the image} return true ;}};

The onActivityResult callback is as follows:

@ Override protected void onActivityResult (int requestCode, int resultCode, Intent data) {super. onActivityResult (requestCode, resultCode, data); if (requestCode = SELECT_IMAGE_RESULT_CODE & resultCode = RESULT_ OK) {String imagePath = ""; if (data! = Null & data. getData ()! = Null) {// if data is returned, use the returned image address imagePath = ImageUtils. getFilePathByFileUri (this, data. getData ();} else {// No data use the specified image path imagePath = mImagePath;} dataList. addFirst (imagePath); // put data in the first adapter each time. update (dataList); // refresh the image }}

Tips for using Adapter
We can see that the GirdView click listener and long-press listener are used.

If (parent. getItemAtPosition (position )! = Null) {// related logic}

Judge the statement. Why does it use parent. getItemAtPosition (position) instead of dataList. get (position? I personally think that it is best to isolate the data source by using the Adapter, that is, in addition to transmitting data in the Adapter or updating data by the Adapter, the data source is no longer used in other cases, to avoid some problems caused by data synchronization. Let's take a look at the Adapter code:

/*** Upload multiple images and dynamically Add the image adapter */public class UploadImageAdapter extends BaseAdapter {private upload list
  
   
ImagePathList; private Context context; private boolean isAddData = true;/*** controls the maximum number of uploaded images */private int imageNumber = 6; public UploadImageAdapter (Context context, shortlist
   
    
ImagePath) {this. context = context; this. imagePathList = imagePath;} public void update (shortlist
    
     
ImagePathList) {this. imagePathList = imagePathList; // place the selected image to the front and the default image to the end. if (isAddData) {// The total number in the set is equal to the number of uploaded images plus the default number of images cannot be greater than imageNumber + 1 if (imagePathList. size () = imageNumber + 1) {// remove the default image imagePathList. removeLast (); isAddData = false ;}} else {// Add the default image imagePathList. addLast (null); isAddData = true;} notifyDataSetChanged () ;}@ Override public int getCount () {return imagePathList = null? 0: imagePathList. size () ;}@ Override public Object getItem (int position) {return imagePathList = null? Null: imagePathList. get (position) ;}@ Override public long getItemId (int position) {return position ;}@ Override public View getView (int position, View convertView, ViewGroup parent) {ImageView iv_image; if (convertView = null) {// create an ImageView iv_image = new ImageView (context); iv_image.setLayoutParams (new AbsListView. layoutParams (ImageUtils. getWidth (context)/3-5, ImageUtils. getWidth (context)/3-5); iv_image.setScaleType (ImageButton. scaleType. CENTER_CROP); convertView = iv_image;} else {iv_image = (ImageView) convertView;} if (getItem (position) = null) {// set the default image iv_image.setImageResource (R. drawable. upload);} else {// obtain image thumbnails to avoid OOM Bitmap = ImageUtils. getImageThumbnail (String) getItem (position), ImageUtils. getWidth (context)/3-5, ImageUtils. getWidth (context)/3-5); iv_image.setImageBitmap (bitmap);} return convertView ;}
    
   
  

Here I have made a non-null judgment on the getCount () and getItem () methods. I personally think it is necessary to avoid NULL pointer exceptions, of course, this is also done to directly use the getItem (position) method in getView, rather than using dataList. get (position) gets the corresponding data of the current item, as mentioned in the GridView click and long press events. The logic is relatively simple, so we will not introduce it too much.

Fragment and Activity transmit data through interfaces
I think the most important thing is how to transmit data between Fragment and Activity. Here I use an interface callback to implement data transmission.
First, define an interface in BaseActivity:

/*** Select the image return code */public final static int SELECT_IMAGE_RESULT_CODE = 200;/*** path of the currently selected image */public String mImagePath; /*** custom PopupWindow */private partial menuWindow;/*** Fragment callback interface */public partial mOnFragmentResult; public void partial (OnFragmentResult) {mOnFragmentResult = onFragmentResult ;} /*** call back the data to the Fragment interface */public interface OnFragmentResult {void onResult (String mImagePath );}

Then let's see how it is used:
Because ChooseFragmentActivity inherits from BaseActivity, mOnFragmentResult

@Override    protected void onActivityResult(int requestCode, int resultCode, Intent data) {        super.onActivityResult(requestCode, resultCode, data);        String imagePath = "";        if(requestCode == SELECT_IMAGE_RESULT_CODE && resultCode== RESULT_OK){            if(data != null && data.getData() != null){                imagePath = ImageUtils.getFilePathByFileUri(this, data.getData());            }else{                imagePath = mImagePath;            }            mOnFragmentResult.onResult(imagePath);        }    }

Fragment:

// Set the listener (BaseActivity) getActivity ()). setOnFragmentResult (mOnFragmentResult); private OnFragmentResult mOnFragmentResult = new OnFragmentResult () {@ Override public void onResult (String mImagePath) {dataList. addFirst (mImagePath); adapter. update (dataList); // refresh the image }};

In Fragment, the row-by-row and row-by-row operations on the GridView are similar to those on the Activity, mainly obtaining Context.

/*** Upload an image GridView Item click to listen */private OnItemClickListener mItemClick = new OnItemClickListener () {@ Override public void onItemClick (AdapterView
  Parent, View view, int position, long id) {if (parent. getItemAtPosition (position) = null) {// Add an image // (BaseActivity) getActivity ()). showPictureDailog (); // Dialog form (BaseActivity) getActivity ()). showPicturePopupWindow (); // PopupWindow format }}};

The most important thing is the step (BaseActivity) getActivity (). This way, the methods and attributes in BaseActivity can be obtained in Fragment. This operation will bring great convenience in many scenarios.

Okay, this article is coming to an end ......

Think great thoughts and you will be great.

I just tried it. I cannot upload resources. I will try again when I can upload the resources ~

Related Article

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.