前不久在项目中再次遇到了这个问题,就是从系统相册中选取图片,调用系统的相机拍照并上传的问题。由于之前比较懒没能在做完之后对写的代码进行整理保存,以至于再次遇到的时候还是重新去研究了一下造成了开发过程中的时间浪费。
注意的点:1.调用系统的相机拍摄并取得原图,并对角度进行处理(有的相机拍照出来的图片显示角度不正常)
2.从系统相册中选取图片并上传
3.由于我上传图片用的file文件,涉及到了文件的读写操作也就是耗时操作,所以将其放入了子线程中
4.网络操作用的okhttp
下面是硬货:
package com.buka.sdk.activitys;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import org.json.JSONObject;
import android.content.Intent;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Matrix;
import android.media.ExifInterface;
import android.net.Uri;
import android.os.Bundle;
import android.os.Environment;
import android.provider.MediaStore;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.ImageView;
import android.widget.TextView;
import com.buka.http.OkHttpUtils;
import com.buka.sdk.callbacks.JsonCallback;
import com.buka.sdk.components.BKBaseActivity;
import com.buka.sdk.configs.BKConfigKeys;
import com.buka.sdk.configs.BKUrlConfigs;
import com.buka.sdk.db.TBLUserDBManager;
import com.buka.sdk.models.TBLLoginModel;
import com.buka.sdk.utils.LoadingUtils;
import com.buka.sdk.utils.LogUtils;
import com.buka.sdk.utils.T;
import com.buka.sdk.utils.Tools;
import com.squareup.okhttp.Request;
public class BKUploadPicActivity extends BKBaseActivity implements OnClickListener {
private static final int REQUEST_CODE_IMAGE = 0;
private static final int REQUEST_CODE_CAMRE = 1;
private Uri mUri;
private File mDir;
private TextView tvPhoto;
private TextView tvTakePhoto;
private ImageView imageviewBack;
public static final String UPLOAD_CALLBACK_DATA = "upload_callback_data";
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(getLayoutInflater()
.inflate(mResourceUtils.getLayoutId("activity_bk_photo_send"), null));
initView();
mkTempDir();
}
private void mkTempDir() {
String status=Environment.getExternalStorageState();
if (status.equals(Environment.MEDIA_MOUNTED)) {
mDir=new File(Environment.getExternalStorageDirectory() + File.separator+"bksdk");
}else {
mDir=new File(getCacheDir().getAbsolutePath()+File.separator+"bksdk");
}
if (!mDir.exists()) {
mDir.mkdirs();
}
}
private void initView() {
tvPhoto = (TextView) findViewById(mResourceUtils.getId("tv_bk_photo"));
tvTakePhoto = (TextView) findViewById(mResourceUtils.getId("tv_bk_take_photo"));
imageviewBack = (ImageView) findViewById(mResourceUtils.getId("imageview_back"));
tvPhoto.setOnClickListener(this);
tvTakePhoto.setOnClickListener(this);
imageviewBack.setOnClickListener(this);
}
@Override
public void onClick(View v) {
if(v == imageviewBack) {
finish();
} else if(v == tvPhoto) {
Intent intent = new Intent(Intent.ACTION_PICK);
intent.setType("image/*");// 相片类型
startActivityForResult(intent, REQUEST_CODE_IMAGE);
} else if(v == tvTakePhoto) {
File f=new File(mDir,"camera.jpg");
mUri=Uri.fromFile(f);
try {
Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
intent.putExtra(MediaStore.EXTRA_OUTPUT, mUri);
startActivityForResult(intent,REQUEST_CODE_CAMRE);
} catch (Exception e) {
e.printStackTrace();
T.show(this, "相机出现问题了");
}
}
}
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent intent) {
super.onActivityResult(requestCode, resultCode, intent);
if(resultCode == RESULT_OK) {
LoadingUtils.show(BKUploadPicActivity.this, true, "图片上传中...");
if (requestCode == REQUEST_CODE_IMAGE) {
mUri = intent == null ? null : intent.getData();
if(mUri != null) {
workThread("gallery.jpg");
}
} else if(requestCode == REQUEST_CODE_CAMRE) {
if(mUri != null) {
workThread("camera.jpg");
}
}
}
}
private WorkThread workThread;
private void workThread(final String fileName) {
workThread = new WorkThread(fileName);
workThread.start();
}
//子线程中执行耗时的文件等操作
private class WorkThread extends Thread {
String fileName;
public WorkThread(String fileName) {
this.fileName = fileName;
}
@Override
public void run() {
//根据uri获取指定大小的bitmap
Bitmap bitmap = getCompressBitmap(mUri);
//获取原有的角度
int degree = getBitmapDegree(mUri);
LogUtils.d("图片角度:" + degree);
//获取修改完善角度后的bitmap
bitmap = rotateBitmapByDegree(bitmap, degree);
//转化为file文件
File file = bitmapToFile(bitmap, fileName);
//释放bitmap减少内存占用
bitmap.recycle();
//上传file文件
uploadOnUiThread(file);
}
}
private Bitmap getCompressBitmap(Uri uri) {
InputStream input = null;
Bitmap bitmap = null;
try {
input = getContentResolver().openInputStream(uri);
BitmapFactory.Options opt = new BitmapFactory.Options();
if ((opt.outWidth == -1) || (opt.outHeight == -1))
return null;
opt.inJustDecodeBounds = true;
opt.inDither=true;
opt.inPreferredConfig=Bitmap.Config.RGB_565;
BitmapFactory.decodeStream(input, null, opt);
opt.inSampleSize = calculateInSampleSize(opt);
opt.inJustDecodeBounds = false;
input = getContentResolver().openInputStream(uri);
bitmap = BitmapFactory.decodeStream(input, null, opt);
} catch (FileNotFoundException e) {
e.printStackTrace();
} finally {
try {
if(input != null)
input.close();
} catch (IOException e) {
e.printStackTrace();
}
}
return bitmap;
}
private int calculateInSampleSize(BitmapFactory.Options options) {
int inSampleSize = 1;
if(options.outWidth > 320 || options.outHeight > 480) {
int ws = options.outWidth / 320;
int hs = options.outHeight / 480;
inSampleSize = ws > hs ? ws : hs;
}
LogUtils.d("压缩倍数:" + inSampleSize);
return inSampleSize;
}
private void uploadOnUiThread(final File file){
BKUploadPicActivity.this.runOnUiThread(new Runnable() {
@Override
public void run() {
uploadFile(file);
}
});
}
private File bitmapToFile(Bitmap photo, String fileName){
File f = new File(mDir, fileName);
FileOutputStream fOut = null;
try {
if (f.exists()) {
f.delete();
}
f.createNewFile();
fOut = new FileOutputStream(f);
photo.compress(Bitmap.CompressFormat.JPEG, 100, fOut);
fOut.flush();
} catch (Exception e) {
e.printStackTrace();
} finally {
try {
fOut.close();
} catch (IOException e) {
e.printStackTrace();
}
}
return f;
}
/**
* 获取图片的存储角度
* @param path
* @return
*/
private int getBitmapDegree(Uri uri) {
int degree = 0;
try {
String path = uri.getPath();
// 从指定路径下读取图片,并获取其EXIF信息
ExifInterface exifInterface = new ExifInterface(path);
// 获取图片的旋转信息
int orientation = exifInterface.getAttributeInt(ExifInterface.TAG_ORIENTATION,
ExifInterface.ORIENTATION_NORMAL);
switch (orientation) {
case ExifInterface.ORIENTATION_ROTATE_90:
degree = 90;
break;
case ExifInterface.ORIENTATION_ROTATE_180:
degree = 180;
break;
case ExifInterface.ORIENTATION_ROTATE_270:
degree = 270;
break;
}
} catch (IOException e) {
e.printStackTrace();
}
return degree;
}
/**
* 旋转bitmap
* @param bm
* @param degree
* @return
*/
public Bitmap rotateBitmapByDegree(Bitmap bm, int degree) {
if(degree == 0) {
return bm;
}
Bitmap returnBm = null;
// 根据旋转角度,生成旋转矩阵
Matrix matrix = new Matrix();
matrix.postRotate(degree);
try {
// 将原始图片按照旋转矩阵进行旋转,并得到新的图片
returnBm = Bitmap.createBitmap(bm, 0, 0, bm.getWidth(), bm.getHeight(), matrix, true);
} catch (OutOfMemoryError e) {
}
if (returnBm == null) {
returnBm = bm;
}
if (bm != returnBm) {
bm.recycle();
}
return returnBm;
}
private void uploadFile(File file) {
String gid = Tools.getMetaString(this, BKConfigKeys.META_GAME_ID);
String p = "1";
TBLLoginModel model = TBLUserDBManager.getInstance(this).currentUser();
String mutk = model.mutk;
OkHttpUtils
.postForm()
.url(BKUrlConfigs.SEND_PHOTO_PATH)
.addParams("gid", gid)
.addParams("p", p)
.addParams("mutk", mutk)
.addHeader("cookie", "mutk=" + mutk)
.addFile("file", file.getName(), file)
.tag(this)
.build()
.execute(new JsonCallback() {
@Override
public void onError(Request request, Exception e) {
super.onError(request, e);
LoadingUtils.hide();
sendBackData(null);
}
@Override
public void onResponse(JSONObject response) {
super.onResponse(response);
LoadingUtils.hide();
sendBackData(response.toString());
}
});
}
private void sendBackData(String data) {
Intent intent = getIntent();
intent.putExtra(UPLOAD_CALLBACK_DATA, data);
setResult(RESULT_OK, intent);
finish();
};
@Override
protected void onDestroy() {
super.onDestroy();
workThread.interrupt();
}
}