你的位置:首页 > 操作系统

[操作系统]android头像上传(获取头像加剪切)

因为项目中需要用到头像上传的功能,所以就下个Ddmo先来实现下。

demo我是类似仿微信的,在一个GridView中展示所有的图片,其中第一个item可以去照相;获取到图片后再进行剪切。

图片的剪切是从网上找的感觉不错就用,暂时也没有测试。

获取图片可以用:https://github.com/lovetuzitong/MultiImageSelector来实现

这里的圆形图像是用https://github.com/hdodenhof/CircleImageView来实现的

Demo写的比较粗糙,效果只是在4.4的手机和7.0的模拟器跑了一遍,所以可能会出现问题的。

如下是demo的效果图:

如下是选择图片中的代码

通过LoaderManager来获取到所有的图片,然后第一个进行拍照的处理

 1 package com.item.demo.photo.activity; 2  3 import android.Manifest; 4 import android.app.LoaderManager; 5 import android.content.ContentResolver; 6 import android.content.Context; 7 import android.content.CursorLoader; 8 import android.content.Intent; 9 import android.content.Loader; 10 import android.content.pm.PackageManager; 11 import android.database.Cursor; 12 import android.net.Uri; 13 import android.os.Build; 14 import android.os.Environment; 15 import android.provider.MediaStore; 16 import android.support.annotation.NonNull; 17 import android.support.v4.content.ContextCompat; 18 import android.support.v4.content.FileProvider; 19 import android.support.v7.app.AppCompatActivity; 20 import android.os.Bundle; 21 import android.text.TextUtils; 22 import android.util.Log; 23 import android.view.View; 24 import android.widget.AdapterView; 25 import android.widget.GridView; 26 import android.widget.ImageView; 27  28 import com.item.demo.photo.BuildConfig; 29 import com.item.demo.photo.R; 30 import com.item.demo.photo.adapter.MyPhotoAdapter; 31 import com.item.demo.photo.uilts.Image; 32 import java.io.File; 33 import java.util.ArrayList; 34 import java.util.List; 35  36 /** 37  * 图片选择界面 38 */ 39 public class MyPhotoActivity extends AppCompatActivity { 40  41  private static final int REQUEST_CAPTURE = 100; 42  //private static final int REQUEST_PICK = 101; 43  private static final int REQUEST_CROP_PHOTO = 102; 44  45  public static final int FINSH_RESULT = 104;//截图后的返回 46  47  private static final int LOADER_ID = 0x0100; 48  private LoadCallBack mLoad = new LoadCallBack(); 49  50  private MyPhotoAdapter mAdapter; 51  private List<Image> images = new ArrayList<>(); 52  //调用照相机返回图片文件 53  private File tempFile; 54  private static final int MIN_IMAGE_FILE_SIZE = 10 * 1024; // 最小的图片大小 55  56  @Override 57  protected void onCreate(Bundle savedInstanceState) { 58   super.onCreate(savedInstanceState); 59   setContentView(R.layout.activity_my_photo); 60  61   GridView gv_photo = (GridView)findViewById(R.id.gv_photo); 62   ImageView img_back = (ImageView)findViewById(R.id.iv_back); 63   images.add(new Image()); 64   mAdapter = new MyPhotoAdapter(this,images); 65   gv_photo.setAdapter(mAdapter); 66   gv_photo.setOnItemClickListener(new AdapterView.OnItemClickListener() { 67    @Override 68    public void onItemClick(AdapterView<?> adapterView, View view, int i, long l) { 69     if(i == 0){ 70      //第一个就去照相 71     if(hasPermission(new String[]{Manifest.permission.CAMERA,Manifest.permission.WRITE_EXTERNAL_STORAGE})){ 72       gotoCamera(); 73     }else { 74      requestPermission(0x02,new String[]{Manifest.permission.CAMERA,Manifest.permission.WRITE_EXTERNAL_STORAGE}); 75      } 76     }else { 77      //这里点击获取到图片地址然后裁剪 78      gotoClipActivity(Uri.parse(images.get(i).getPath())); 79     } 80    } 81   }); 82   img_back.setOnClickListener(new View.OnClickListener() { 83    @Override 84    public void onClick(View view) { 85     finish(); 86    } 87   }); 88  } 89  90  @Override 91  protected void onStart() { 92   super.onStart(); 93  94   if(hasPermission(new String[]{Manifest.permission.READ_EXTERNAL_STORAGE})){ 95    getLoaderManager().initLoader(LOADER_ID,null,mLoad); 96   }else { 97    requestPermission(0x01,new String[]{Manifest.permission.READ_EXTERNAL_STORAGE}); 98   } 99  }100 101  private class LoadCallBack implements LoaderManager.LoaderCallbacks<Cursor>{102   private final String[] IMAGE_PROJECTION = new String[]{103     MediaStore.Images.Media._ID,//Id104     MediaStore.Images.Media.DATA,//图片路径105     MediaStore.Images.Media.DATE_ADDED//图片的创建时间106   };107 108   @Override109   public Loader<Cursor> onCreateLoader(int id, Bundle args) {110    //创建一个Loader111    if(id == LOADER_ID){112     //如果是我们的ID则进行初始化113     return new CursorLoader(getBaseContext(),114       MediaStore.Images.Media.EXTERNAL_CONTENT_URI,115       IMAGE_PROJECTION,116       null,117       null,118       IMAGE_PROJECTION[2] + " DESC");119    }120    return null;121   }122 123   @Override124   public void onLoadFinished(Loader<Cursor> loader, Cursor data) {125    //当Loader加载完成时126    List<Image> images = new ArrayList<>();127    //判断是否有数据128    if(data != null){129     int count = data.getCount();130     if(count > 0){131      data.moveToFirst();132      // 得到对应的列的Index坐标133      int indexId = data.getColumnIndexOrThrow(IMAGE_PROJECTION[0]);134      int indexPath = data.getColumnIndexOrThrow(IMAGE_PROJECTION[1]);135      int indexDate = data.getColumnIndexOrThrow(IMAGE_PROJECTION[2]);136      do {137       // 循环读取,直到没有下一条数据138       int id = data.getInt(indexId);139       String path = data.getString(indexPath);140       long dateTime = data.getLong(indexDate);141 142       File file = new File(path);143       if (!file.exists() || file.length() < MIN_IMAGE_FILE_SIZE) {144        // 如果没有图片,或者图片大小太小,则跳过145        continue;146       }147       // 添加一条新的数据148       Image image = new Image();149       image.setId(id);150       image.setPath(path);151       image.setDate(dateTime);152       images.add(image);153 154      } while (data.moveToNext());155     }156    }157    updateSource(images);158   }159 160   @Override161   public void onLoaderReset(Loader<Cursor> loader) {162    updateSource(null);163   }164  }165 166  /**167   * 通知Adapter数据更改的方法168   * @param images 新的数据169  */170  private void updateSource(List<Image> images){171   this.images.clear();172   this.images.add(new Image());173   if(images == null || images.size() == 0) return;174   this.images.addAll(images);175   mAdapter.notifyDataSetChanged();176  }177 178  /**179   *权限的返回180  */181  @Override182  public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {183   super.onRequestPermissionsResult(requestCode, permissions, grantResults);184   switch(requestCode){185    case 0x02:186     if(grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED){187      gotoCamera();188     }189     break;190    case 0x01:191     if(grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED){192      getLoaderManager().initLoader(LOADER_ID,null,mLoad);193     }194   }195  }196 197  @Override198  protected void onActivityResult(int requestCode, int resultCode, Intent data) {199   super.onActivityResult(requestCode, resultCode, data);200   switch (requestCode){201    case REQUEST_CAPTURE://系统相机返回202     if(resultCode == RESULT_OK){203      Log.d("jiejie","--------相机---------" + Uri.fromFile(tempFile).toString());204      Log.d("jiejie","--------path----------" + getRealFilePathFromUri(MyPhotoActivity.this,Uri.fromFile(tempFile)));205      gotoClipActivity(Uri.fromFile(tempFile));206     }207 208     break;209    case REQUEST_CROP_PHOTO:210     if(resultCode == RESULT_OK){211      if(data != null){212       Uri uri = data.getData();213       Log.d("jiejie","-------------" + data.getData().getPath());214       String cropImagePath = getRealFilePathFromUri(MyPhotoActivity.this,uri);215       Log.d("jiejie","------crop--------" + cropImagePath);216       Intent intent = new Intent();217       intent.putExtra("image",cropImagePath);218       setResult(FINSH_RESULT,intent);219       MyPhotoActivity.this.finish();220      }221 222     }223     break;224   }225  }226 227  /**228   * 跳转到系统照相机229  */230  private void gotoCamera(){231   String SDState = Environment.getExternalStorageState();232   //判断SD卡是否存在233   if(SDState.equals(Environment.MEDIA_MOUNTED)){234    tempFile = new File(checkDirPath(Environment.getExternalStorageDirectory().getPath()+ "/image/"), System.currentTimeMillis() + ".jpg");235    //隐式的打开调用系统相册236    Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);237    if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.N){238     intent.setFlags(Intent.FLAG_GRANT_WRITE_URI_PERMISSION);239     //如果是7.0及以上的系统使用FileProvider的方式创建一个Uri240     Uri contentUri = FileProvider.getUriForFile(MyPhotoActivity.this, BuildConfig.APPLICATION_ID + ".fileProvider", tempFile);241     intent.putExtra(MediaStore.EXTRA_OUTPUT, contentUri);242    }else {243     intent.putExtra(MediaStore.EXTRA_OUTPUT, Uri.fromFile(tempFile));244    }245    startActivityForResult(intent,REQUEST_CAPTURE);246   }247  }248 249  /**250   * 打开截图的界面251   * @param uri252  */253  private void gotoClipActivity(Uri uri){254   if(uri == null){255    return;256   }257   Intent intent = new Intent(this,ClipImageActivity.class);258   intent.putExtra("type",1);259   intent.setData(uri);260   startActivityForResult(intent,REQUEST_CROP_PHOTO);261  }262 263  /**264   * 检查文件是否存在265  */266  private static String checkDirPath(String dirPath) {267   if (TextUtils.isEmpty(dirPath)) {268    return "";269   }270   File dir = new File(dirPath);271   if (!dir.exists()) {272    dir.mkdirs();273   }274   return dirPath;275  }276  /**277   * 判断是否有指定的权限278  */279  public boolean hasPermission(String... permissions) {280 281   for (String permisson : permissions) {282    if (ContextCompat.checkSelfPermission(this, permisson)283      != PackageManager.PERMISSION_GRANTED) {284     return false;285    }286   }287   return true;288  }289  /**290   * 申请指定的权限.291  */292  public void requestPermission(int code, String... permissions) {293 294   if (Build.VERSION.SDK_INT >= 23) {295    requestPermissions(permissions, code);296   }297  }298 299  /**300   * 根据Uri返回文件绝对路径301   * 兼容了file:///开头的 和 content://开头的情况302  */303  public static String getRealFilePathFromUri(final Context context, final Uri uri) {304   if (null == uri) return null;305   final String scheme = uri.getScheme();306   String data = null;307   if (scheme == null)308    data = uri.getPath();309   else if (ContentResolver.SCHEME_FILE.equals(scheme)) {310    data = uri.getPath();311   } else if (ContentResolver.SCHEME_CONTENT.equals(scheme)) {312    Cursor cursor = context.getContentResolver().query(uri, new String[]{MediaStore.Images.ImageColumns.DATA}, null, null, null);313    if (null != cursor) {314     if (cursor.moveToFirst()) {315      int index = cursor.getColumnIndex(MediaStore.Images.ImageColumns.DATA);316      if (index > -1) {317       data = cursor.getString(index);318      }319     }320     cursor.close();321    }322   }323   return data;324  }325 }

其中处理动态的权限还需要添加7.0的照相处理

在清单文件中加如下配置:

  <provider   android:name="android.support.v4.content.FileProvider"   android:authorities="com.item.demo.photo.fileProvider"   android:grantUriPermissions="true"   android:exported="false">   <meta-data    android:name="android.support.FILE_PROVIDER_PATHS"    android:resource="@ />  </provider>

 

图片的剪切

package com.item.demo.photo.activity;import android.content.Intent;import android.graphics.Bitmap;import android.net.Uri;import android.support.v7.app.AppCompatActivity;import android.os.Bundle;import android.util.Log;import android.view.View;import android.widget.ImageView;import android.widget.TextView;import com.item.demo.photo.R;import com.item.demo.photo.view.ClipViewLayout;import java.io.File;import java.io.IOException;import java.io.OutputStream;/** * 图片剪切 */public class ClipImageActivity extends AppCompatActivity implements View.OnClickListener { private ClipViewLayout clipViewLayout1; private ClipViewLayout clipViewLayout2; private ImageView back; private TextView tv_ok; //类别 1:圆形 2:方形 private int type; @Override protected void onCreate(Bundle savedInstanceState) {  super.onCreate(savedInstanceState);  setContentView(R.layout.activity_clip_image);  type = getIntent().getIntExtra("type",1);  initView(); } private void initView() {  clipViewLayout1 = (ClipViewLayout)findViewById(R.id.clipViewLayout1);  clipViewLayout2 = (ClipViewLayout)findViewById(R.id.clipViewLayout2);  back = (ImageView)findViewById(R.id.iv_back);  tv_ok = (TextView)findViewById(R.id.tv_ok);  back.setOnClickListener(this);  tv_ok.setOnClickListener(this); } @Override protected void onResume() {  super.onResume();  if(type == 1){   clipViewLayout1.setVisibility(View.VISIBLE);   clipViewLayout2.setVisibility(View.GONE);   //设置图片资源   clipViewLayout1.setImageSrc(getIntent().getData());  }else {   clipViewLayout2.setVisibility(View.VISIBLE);   clipViewLayout1.setVisibility(View.GONE);   clipViewLayout2.setImageSrc(getIntent().getData());  } } @Override public void onClick(View view) {  switch (view.getId()){   case R.id.iv_back:    finish();    break;   case R.id.tv_ok:    generateUriAndReturn();    break;  } } /**  * 生成Uri并且通过setResult返回给打开的Activity  */ private void generateUriAndReturn() {  //调用返回剪切图  Bitmap zoomedCropBitmap;  if (type == 1) {   zoomedCropBitmap = clipViewLayout1.clip();  } else {   zoomedCropBitmap = clipViewLayout2.clip();  }  if (zoomedCropBitmap == null) {   Log.e("android", "zoomedCropBitmap == null");   return;  }  Uri mSaveUri = Uri.fromFile(new File(getCacheDir(), "cropped_" + System.currentTimeMillis() + ".jpg"));  if (mSaveUri != null) {   OutputStream outputStream = null;   try {    outputStream = getContentResolver().openOutputStream(mSaveUri);    if (outputStream != null) {     zoomedCropBitmap.compress(Bitmap.CompressFormat.JPEG, 90, outputStream);    }   } catch (IOException ex) {    Log.e("android", "Cannot open file: " + mSaveUri, ex);   } finally {    if (outputStream != null) {     try {      outputStream.close();     } catch (IOException e) {      e.printStackTrace();     }    }   }   Intent intent = new Intent();   intent.setData(mSaveUri);   setResult(RESULT_OK, intent);   finish();  } }}