獲取本地拍照和相簿顯示到ImageView
阿新 • • 發佈:2018-12-12
先來看看效果
xml佈局程式碼
<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" tools:context=".MainActivity" android:gravity="center" android:orientation="vertical"> <ImageView android:layout_width="200dp" android:layout_height="200dp" android:scaleType="fitXY" android:src="@mipmap/ic_launcher" android:id="@+id/iv_img"/> <Button android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="相機" android:id="@+id/bt_camera"/> <Button android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="相簿" android:id="@+id/bt_xiangce"/> </LinearLayout>
MainActivity程式碼(註釋)
package com.example.xiangji; import android.content.Context; import android.content.Intent; import android.content.SharedPreferences; import android.graphics.Bitmap; import android.graphics.BitmapFactory; import android.net.Uri; import android.os.Environment; import android.provider.MediaStore; import android.support.v7.app.AppCompatActivity; import android.os.Bundle; import android.util.Base64; import android.util.Log; import android.view.View; import android.widget.Button; import android.widget.ImageView; import android.widget.Toast; import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; import java.io.File; import java.io.IOException; import java.util.HashMap; import java.util.Map; import okhttp3.Request; public class MainActivity extends AppCompatActivity implements View.OnClickListener { private ImageView iv_img; private Button bt_camera; private Button bt_xiangce; private static final int PHOTO_REQUEST_CAREMA = 1;// 拍照 private static final int PHOTO_REQUEST_GALLERY = 2;// 從相簿中選擇 private static final int PHOTO_REQUEST_CUT = 3;// 結果 /* 頭像名稱 */ private static final String PHOTO_FILE_NAME = "temp_photo.jpg"; private File tempFile; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); initView(); } private void initView() { iv_img = (ImageView) findViewById(R.id.iv_img); bt_camera = (Button) findViewById(R.id.bt_camera); bt_xiangce = (Button) findViewById(R.id.bt_xiangce); //從SharedPreferences獲取圖片 getBitmapFromSharedPreferences(); bt_camera.setOnClickListener(this); bt_xiangce.setOnClickListener(this); } @Override public void onClick(View v) { switch (v.getId()) { case R.id.bt_camera: // 啟用相機 Intent intent = new Intent("android.media.action.IMAGE_CAPTURE"); // 判斷儲存卡是否可以用,可用進行儲存 if (hasSdcard()) { tempFile = new File(Environment.getExternalStorageDirectory(), PHOTO_FILE_NAME); // 從檔案中建立uri Uri uri = Uri.fromFile(tempFile); intent.putExtra(MediaStore.EXTRA_OUTPUT, uri); } // 開啟一個帶有返回值的Activity,請求碼為PHOTO_REQUEST_CAREMA startActivityForResult(intent, PHOTO_REQUEST_CAREMA); break; case R.id.bt_xiangce: // 啟用系統圖庫,選擇一張圖片 Intent intent1 = new Intent(Intent.ACTION_PICK); intent1.setType("image/*"); // 開啟一個帶有返回值的Activity,請求碼為PHOTO_REQUEST_GALLERY startActivityForResult(intent1, PHOTO_REQUEST_GALLERY); break; } } /* * 判斷sdcard是否被掛載 */ private boolean hasSdcard() { //判斷SD卡手否是安裝好的 media_mounted if (Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED)) { return true; } else { return false; } } /* * 剪下圖片 */ private void crop(Uri uri) { // 裁剪圖片意圖 Intent intent = new Intent("com.android.camera.action.CROP"); intent.setDataAndType(uri, "image/*"); intent.putExtra("crop", "true"); // 裁剪框的比例,1:1 intent.putExtra("aspectX", 1); intent.putExtra("aspectY", 1); // 裁剪後輸出圖片的尺寸大小 intent.putExtra("outputX", 250); intent.putExtra("outputY", 250); intent.putExtra("outputFormat", "JPEG");// 圖片格式 intent.putExtra("noFaceDetection", true);// 取消人臉識別 intent.putExtra("return-data", true); // 開啟一個帶有返回值的Activity,請求碼為PHOTO_REQUEST_CUT startActivityForResult(intent, PHOTO_REQUEST_CUT); } /** * * @param requestCode * @param resultCode * @param data */ @Override protected void onActivityResult(int requestCode, int resultCode, Intent data) { if (requestCode == PHOTO_REQUEST_GALLERY) { // 從相簿返回的資料 if (data != null) { // 得到圖片的全路徑 Uri uri = data.getData(); crop(uri); } } else if (requestCode == PHOTO_REQUEST_CAREMA) { // 從相機返回的資料 if (hasSdcard()) { crop(Uri.fromFile(tempFile)); } else { Toast.makeText(MainActivity.this, "未找到儲存卡,無法儲存照片!", Toast.LENGTH_SHORT).show(); } } else if (requestCode == PHOTO_REQUEST_CUT) { // 從剪下圖片返回的資料 if (data != null) { Bitmap bitmap = data.getParcelableExtra("data"); /** * 獲得圖片 */ iv_img.setImageBitmap(bitmap); //儲存到SharedPreferences saveBitmapToSharedPreferences(bitmap); } try { // 將臨時檔案刪除 tempFile.delete(); } catch (Exception e) { e.printStackTrace(); } } super.onActivityResult(requestCode, resultCode, data); } //儲存圖片到SharedPreferences private void saveBitmapToSharedPreferences(Bitmap bitmap) { // Bitmap bitmap=BitmapFactory.decodeResource(getResources(), R.drawable.ic_launcher); //第一步:將Bitmap壓縮至位元組陣列輸出流ByteArrayOutputStream ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream(); bitmap.compress(Bitmap.CompressFormat.PNG, 80, byteArrayOutputStream); //第二步:利用Base64將位元組陣列輸出流中的資料轉換成字串String byte[] byteArray = byteArrayOutputStream.toByteArray(); String imageString = new String(Base64.encodeToString(byteArray, Base64.DEFAULT)); //第三步:將String保持至SharedPreferences SharedPreferences sharedPreferences = getSharedPreferences("testSP", Context.MODE_PRIVATE); SharedPreferences.Editor editor = sharedPreferences.edit(); editor.putString("image", imageString); editor.commit(); //上傳頭像 setImgByStr(imageString,""); } /** * 上傳頭像 * @param imgStr * @param imgName */ public void setImgByStr(String imgStr, String imgName) { String url = "http://appserver.1035.mobi/MobiSoft/User_upLogo"; Map<String, String> params = new HashMap<String, String>(); params.put("id", "11460047");// 11459832 params.put("data", imgStr); OkHttp.postAsync(url, params, new OkHttp.DataCallBack() { @Override public void requestFailure(Request request, IOException e) { Log.i("上傳失敗", "失敗" + request.toString() + e.toString()); } @Override public void requestSuccess(String result) throws Exception { Log.i("上傳成功", result); } }); } //從SharedPreferences獲取圖片 private void getBitmapFromSharedPreferences(){ SharedPreferences sharedPreferences=getSharedPreferences("testSP", Context.MODE_PRIVATE); //第一步:取出字串形式的Bitmap String imageString=sharedPreferences.getString("image", ""); //第二步:利用Base64將字串轉換為ByteArrayInputStream byte[] byteArray=Base64.decode(imageString, Base64.DEFAULT); if(byteArray.length==0){ iv_img.setImageResource(R.mipmap.ic_launcher); }else{ ByteArrayInputStream byteArrayInputStream=new ByteArrayInputStream(byteArray); //第三步:利用ByteArrayInputStream生成Bitmap Bitmap bitmap= BitmapFactory.decodeStream(byteArrayInputStream); iv_img.setImageBitmap(bitmap); } } }
使用okhttp請求網路(註釋)
package com.example.xiangji; import android.os.Handler; import android.os.Looper; import java.io.File; import java.io.FileOutputStream; import java.io.IOException; import java.io.InputStream; import java.util.HashMap; import java.util.Map; import java.util.concurrent.TimeUnit; import okhttp3.Call; import okhttp3.Callback; import okhttp3.FormBody; import okhttp3.OkHttpClient; import okhttp3.Request; import okhttp3.RequestBody; import okhttp3.Response; import okhttp3.logging.HttpLoggingInterceptor; public class OkHttp { private static OkHttp sOkHttpManager; /** * okhttpclient例項 */ private OkHttpClient mClient; /** * 因為我們請求資料一般都是子執行緒中請求,在這裡我們使用了handler */ private Handler mHandler; /** * 構造方法 */ private OkHttp() { // // 可以通過實現 Logger 介面更改日誌儲存位置 HttpLoggingInterceptor loggingInterceptor = new HttpLoggingInterceptor(); loggingInterceptor.setLevel(HttpLoggingInterceptor.Level.BODY); // mClient = new OkHttpClient.Builder().addInterceptor(loggingInterceptor).build(); mClient = new OkHttpClient(); /** * 在這裡直接設定連線超時.讀取超時,寫入超時 */ OkHttpClient.Builder builder = mClient.newBuilder(); builder.connectTimeout(10, TimeUnit.SECONDS); builder.readTimeout(10, TimeUnit.SECONDS); builder.writeTimeout(10, TimeUnit.SECONDS); builder.addInterceptor(loggingInterceptor); mClient = builder.build(); /** * 如果是用的3.0之前的版本 使用以下直接設定連線超時.讀取超時,寫入超時 */ //client.setConnectTimeout(10, TimeUnit.SECONDS); //client.setWriteTimeout(10, TimeUnit.SECONDS); //client.setReadTimeout(30, TimeUnit.SECONDS); /** * 初始化handler */ mHandler = new Handler(Looper.getMainLooper()); } /** * 單例模式 獲取OkHttp例項 * * @return */ public static OkHttp getInstance() { if (sOkHttpManager == null) { sOkHttpManager = new OkHttp(); } return sOkHttpManager; } //-------------------------同步的方式請求資料-------------------------- /** * 對外提供的get方法,同步的方式 * * @param url 傳入的地址 * @return */ public static Response getSync(String url) { //通過獲取到的例項來呼叫內部方法 return sOkHttpManager.inner_getSync(url); } /** * GET方式請求的內部邏輯處理方式,同步的方式 * * @param url * @return */ private Response inner_getSync(String url) { Request request = new Request.Builder().url(url).build(); Response response = null; try { //同步請求返回的是response物件 response = mClient.newCall(request).execute(); } catch (IOException e) { e.printStackTrace(); } return response; } /** * 對外提供的同步獲取String的方法 * * @param url * @return */ public static String getSyncString(String url) { return sOkHttpManager.inner_getSyncString(url); } /** * 同步方法 */ private String inner_getSyncString(String url) { String result = null; try { /** * 把取得到的結果轉為字串,這裡最好用string() */ result = inner_getSync(url).body().string(); } catch (IOException e) { e.printStackTrace(); } return result; } //-------------------------非同步的方式請求資料-------------------------- public static void getAsync(String url, DataCallBack callBack) { getInstance().inner_getAsync(url, callBack); } /** * 內部邏輯請求的方法 * * @param url * @param callBack * @return */ private void inner_getAsync(String url, final DataCallBack callBack) { final Request request = new Request.Builder().url(url).build(); mClient.newCall(request).enqueue(new Callback() { @Override public void onFailure(Call call, IOException e) { deliverDataFailure(request, e, callBack); } @Override public void onResponse(Call call, Response response) throws IOException { String result = null; try { result = response.body().string(); } catch (IOException e) { deliverDataFailure(request, e, callBack); } deliverDataSuccess(result, callBack); } }); } /** * 分發失敗的時候呼叫 * * @param request * @param e * @param callBack */ private void deliverDataFailure(final Request request, final IOException e, final DataCallBack callBack) { /** * 在這裡使用非同步處理 */ mHandler.post(new Runnable() { @Override public void run() { if (callBack != null) { callBack.requestFailure(request, e); } } }); } /** * 分發成功的時候呼叫 * * @param result * @param callBack */ private void deliverDataSuccess(final String result, final DataCallBack callBack) { /** * 在這裡使用非同步執行緒處理 */ mHandler.post(new Runnable() { @Override public void run() { if (callBack != null) { try { callBack.requestSuccess(result); } catch (Exception e) { e.printStackTrace(); } } } }); } /** * 資料回撥介面 */ public interface DataCallBack { void requestFailure(Request request, IOException e); void requestSuccess(String result) throws Exception; } //-------------------------提交表單-------------------------- public static void postAsync(String url, Map<String, String> params, DataCallBack callBack) { getInstance().inner_postAsync(url, params, callBack); } private void inner_postAsync(String url, Map<String, String> params, final DataCallBack callBack) { RequestBody requestBody = null; if (params == null) { params = new HashMap<>(); } /** * 如果是3.0之前版本的,構建表單資料是下面的一句 */ //FormEncodingBuilder builder = new FormEncodingBuilder(); /** * 3.0之後版本 */ FormBody.Builder builder = new FormBody.Builder(); /** * 在這對新增的引數進行遍歷,map遍歷有四種方式,如果想要了解的可以網上查詢 */ for (Map.Entry<String, String> map : params.entrySet()) { String key = map.getKey().toString(); String value = null; /** * 判斷值是否是空的 */ if (map.getValue() == null) { value = ""; } else { value = map.getValue(); } /** * 把key和value新增到formbody中 */ builder.add(key, value); } requestBody = builder.build(); //結果返回 // 請求物件 final Request request = new Request.Builder().url(url).post(requestBody).build(); mClient.newCall(request).enqueue(new Callback() { @Override public void onFailure(Call call, IOException e) { deliverDataFailure(request, e, callBack); } @Override public void onResponse(Call call, Response response) throws IOException { String result = response.body().string(); deliverDataSuccess(result, callBack); } }); } //-------------------------檔案下載-------------------------- public static void downloadAsync(String url, String desDir, DataCallBack callBack) { getInstance().inner_downloadAsync(url, desDir, callBack); } /** * 下載檔案的內部邏輯處理類 * * @param url 下載地址 * @param desDir 目標地址 * @param callBack */ private void inner_downloadAsync(final String url, final String desDir, final DataCallBack callBack) { final Request request = new Request.Builder().url(url).build(); mClient.newCall(request).enqueue(new Callback() { @Override public void onFailure(Call call, IOException e) { deliverDataFailure(request, e, callBack); } @Override public void onResponse(Call call, Response response) throws IOException { /** * 在這裡進行檔案的下載處理 */ InputStream inputStream = null; FileOutputStream fileOutputStream = null; try { //檔名和目標地址 File file = new File(desDir, getFileName(url)); //把請求回來的response物件裝換為位元組流 inputStream = response.body().byteStream(); fileOutputStream = new FileOutputStream(file); int len = 0; byte[] bytes = new byte[2048]; //迴圈讀取資料 while ((len = inputStream.read(bytes)) != -1) { fileOutputStream.write(bytes, 0, len); } //關閉檔案輸出流 fileOutputStream.flush(); //呼叫分發資料成功的方法 deliverDataSuccess(file.getAbsolutePath(), callBack); } catch (IOException e) { //如果失敗,呼叫此方法 deliverDataFailure(request, e, callBack); e.printStackTrace(); } finally { if (inputStream != null) { inputStream.close(); } if (fileOutputStream != null) { fileOutputStream.close(); } } } }); } /** * 根據檔案url獲取檔案的路徑名字 * * @param url * @return */ private String getFileName(String url) { int separatorIndex = url.lastIndexOf("/"); String path = (separatorIndex < 0) ? url : url.substring(separatorIndex + 1, url.length()); return path; } }