Android選擇頭像(從相機-相冊-截圖獲取),以及閃退的解決

最近在做類似註冊的模塊用到了上傳頭像
找了好幾個demo效果都不太好,最後找了一個不會在Neux6 上crush掉的,代碼也很簡單:
項目叫ChangeHead


manifest文件內容:
-------------

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.example.changhead"
    android:versionCode="1"
    android:versionName="1.0" >

    <uses-sdk
        android:minSdkVersion="8"
        android:targetSdkVersion="17" />

    <application
        android:allowBackup="true"
        android:icon="@drawable/ic_launcher"
        android:label="@string/app_name"
        android:theme="@style/AppTheme" >
        <activity
            android:name="com.example.changhead.MainActivity"
            android:label="@string/app_name" >
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />

                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
    </application>
    <uses-permission android:name="android.permission.CAMERA"/>
    <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
    <uses-permission android:name="android.permission.MOUNT_UNMOUNT_FILESYSTEMS"/>  
</manifest>
MainActivity.java
package com.example.changhead;

import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;


import android.net.Uri;
import android.os.Bundle;
import android.os.Environment;
import android.provider.MediaStore;
import android.annotation.SuppressLint;
import android.app.Activity;
import android.content.Intent;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.drawable.BitmapDrawable;
import android.graphics.drawable.Drawable;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.ImageView;

@SuppressLint("SdCardPath")
public class MainActivity extends Activity implements OnClickListener {
    private ImageView ivHead;//頭像顯示
    private Button btnTakephoto;//拍照
    private Button btnPhotos;//相冊
    private Bitmap head;//頭像Bitmap
    private static String path="/sdcard/myHead/";//sd路徑

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        initView();
    }

    private void initView() {
        //初始化控件
        btnPhotos = (Button) findViewById(R.id.btn_photos);
        btnTakephoto = (Button) findViewById(R.id.btn_takephoto);
        btnPhotos.setOnClickListener(this);
        btnTakephoto.setOnClickListener(this);
        ivHead = (ImageView) findViewById(R.id.iv_head);
    Bitmap bt = BitmapFactory.decodeFile(path + "head.jpg");//從Sd中找頭像,轉換成Bitmap
        if(bt!=null){
            @SuppressWarnings("deprecation")
            Drawable drawable = new BitmapDrawable(bt);//轉換成drawable
            ivHead.setImageDrawable(drawable);
        }else{
            /**
             *  如果SD裏面沒有則需要從服務器取頭像,取回來的頭像再保存在SD中
             * 
             */
        }

    }

    @Override
    public void onClick(View v) {
        switch (v.getId()) {
        case R.id.btn_photos://從相冊裏面取照片     
            Intent intent1 = new Intent(Intent.ACTION_PICK, null);
            intent1.setDataAndType(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, "image/*");
            startActivityForResult(intent1, 1);
            break;

        case R.id.btn_takephoto://調用相機拍照

            Intent intent2 = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
            intent2.putExtra(MediaStore.EXTRA_OUTPUT, Uri.fromFile(new File(Environment.getExternalStorageDirectory(),
                            "head.jpg")));
            startActivityForResult(intent2, 2);//採用ForResult打開

            break;
        default:
            break;
        }
    }
    protected void onActivityResult(int requestCode, int resultCode, Intent data) {
        switch (requestCode) {
        case 1: 
            if (resultCode == RESULT_OK) {
                cropPhoto(data.getData());//裁剪圖片
            }
            break;
        case 2:
            if (resultCode == RESULT_OK) {
                File temp = new File(Environment.getExternalStorageDirectory()
                        + "/head.jpg");
                cropPhoto(Uri.fromFile(temp));//裁剪圖片
            }

            break;

        case 3:

            if (data != null) {
                Bundle extras = data.getExtras();
                head = extras.getParcelable("data");
                if(head!=null){
                    /**
                     * 上傳服務器代碼
                     */
                    setPicToView(head);//保存在SD卡中
                    ivHead.setImageBitmap(head);//用ImageView顯示出來
                }
            }
            break;

        default:
            break;

        }
        super.onActivityResult(requestCode, resultCode, data);
    };




    /**
     * 調用系統的裁剪
     * @param uri
     */
    public void cropPhoto(Uri uri) {
        Intent intent = new Intent("com.android.camera.action.CROP");
        intent.setDataAndType(uri, "image/*");
        intent.putExtra("crop", "true");
         // aspectX aspectY 是寬高的比例
        intent.putExtra("aspectX", 1);
        intent.putExtra("aspectY", 1);
        // outputX outputY 是裁剪圖片寬高
        intent.putExtra("outputX", 150);
        intent.putExtra("outputY", 150);
        intent.putExtra("return-data", true);
        startActivityForResult(intent, 3);
    }

    private void setPicToView(Bitmap mBitmap) {
         String sdStatus = Environment.getExternalStorageState();  
        if (!sdStatus.equals(Environment.MEDIA_MOUNTED)) { // 檢測sd是否可用  
               return;  
           }  
        FileOutputStream b = null;
        File file = new File(path);
        file.mkdirs();// 創建文件夾
        String fileName =path + "head.jpg";//圖片名字
        try {
            b = new FileOutputStream(fileName);
            mBitmap.compress(Bitmap.CompressFormat.JPEG, 100, b);// 把數據寫入文件

        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } finally {
            try {
                //關閉流
                b.flush();
                b.close();
            } catch (IOException e) {
                e.printStackTrace();
            }

        }
}

}

佈局長這樣…這個就不貼了,大家一看就明白.
這裏寫圖片描述

然後我就改了一下存儲的路徑在自己項目下
+++++++++++++++++++++++++++++++++++++++

手機適配

測試的時候出了一個bug —當然是手機適配的問題;
在測試的手機中IUNI U3出現閃退

我迷茫了

找了很多網上的解決方案,然後我就請了一天的假,好好的在外面吃了一頓,第二天 我在github上找到一個 crop(截圖)項目
CropMaster將上一個項目調用系統自帶的截圖部分替換成這個就OK了.

PS:注意爲了能夠重複的選擇圖片請加上項目給的Expample裏的

++++++++++++++++++++++++++++++++++++++++++
++  resultView.setImageDrawable(null);  ++
++++++++++++++++++++++++++++++++++++++++++
            Crop.pickImage(this);

這個項目是在另外一個項目上加工而成的cropimage如果要有白色框的效果請看theme裏的配置.

恩,然後就解決了:-D

附:
由相機或圖庫中的圖片bitmap與uri互相轉換

1、bitmap to uri

Uri uri = Uri.parse(MediaStore.Images.Media.insertImage(getContentResolver(), bitmap, null,null));

2、uri to bitmap

Bitmap bitmap = MediaStore.Images.Media.getBitmap(this.getContentResolver(), uri);

然而這並沒有結束
跟很多人一樣一樣的,我又遇到了某些三星手機圖片倒轉的問題……

主要用到了三個方法

  /**
     * Compress image by size, this will modify image width/height.
     * Used to get thumbnail
     *
     * @param image
     * @param pixelW target pixel of width
     * @param pixelH target pixel of height
     * @return
     */
    public Bitmap ratio(Bitmap image, float pixelW, float pixelH) {
        Bitmap bitmap = null;
        try {
            ByteArrayOutputStream os = new ByteArrayOutputStream();
            image.compress(Bitmap.CompressFormat.JPEG, 100, os);
            if (os.toByteArray().length / 1024 > 1024) {//判斷如果圖片大於1M,進行壓縮避免在生成圖片(BitmapFactory.decodeStream)時溢出
                os.reset();//重置baos即清空baos
                image.compress(Bitmap.CompressFormat.JPEG, 50, os);//這裏壓縮50%,把壓縮後的數據存放到baos中
            }
            ByteArrayInputStream is = new ByteArrayInputStream(os.toByteArray());
            BitmapFactory.Options newOpts = new BitmapFactory.Options();
            //開始讀入圖片,此時把options.inJustDecodeBounds 設回true了
            newOpts.inJustDecodeBounds = true;
            newOpts.inPreferredConfig = Bitmap.Config.RGB_565;
            bitmap = BitmapFactory.decodeStream(is, null, newOpts);
            newOpts.inJustDecodeBounds = false;
            int w = newOpts.outWidth;
            int h = newOpts.outHeight;
            float hh = pixelH;// 設置高度爲240f時,可以明顯看到圖片縮小了
            float ww = pixelW;// 設置寬度爲120f,可以明顯看到圖片縮小了
            //縮放比。由於是固定比例縮放,只用高或者寬其中一個數據進行計算即可
            int be = 1;//be=1表示不縮放
            if (w > h && w > ww) {//如果寬度大的話根據寬度固定大小縮放
                be = (int) (newOpts.outWidth / ww);
            } else if (w < h && h > hh) {//如果高度高的話根據寬度固定大小縮放
                be = (int) (newOpts.outHeight / hh);
            }
            if (be <= 0) be = 1;
            newOpts.inSampleSize = be;//設置縮放比例
            //重新讀入圖片,注意此時已經把options.inJustDecodeBounds 設回false了
            is = new ByteArrayInputStream(os.toByteArray());
            bitmap = BitmapFactory.decodeStream(is, null, newOpts);
            //壓縮好比例大小後再進行質量壓縮
            //return compress(bitmap, maxSize); // 這裏再進行質量壓縮的意義不大,反而耗資源,刪除
            LogUtil.Debug("保存圖片");
            FileOutputStream out = new FileOutputStream(temp);
            os.writeTo(out);
            LogUtil.Debug("已經保存");
        } catch (Exception e) {
// TODO: handle exception
            e.printStackTrace();
            Log.e("--ImageFactory.ratio--", e.toString());
        }
        return bitmap;
    }


    /**
     * 讀取圖片的旋轉的角度
     *
     * @param path 圖片絕對路徑
     * @return 圖片的旋轉角度
     */
    private int getBitmapDegree(String path) {
        int degree = 0;
        try {
            // 從指定路徑下讀取圖片,並獲取其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;
    }


    /**
     * 將圖片按照某個角度進行旋轉
     *
     * @param bm     需要旋轉的圖片
     * @param degree 旋轉角度
     * @return 旋轉後的圖片
     */
    public static Bitmap rotateBitmapByDegree(Bitmap bm, int degree) {
        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;
    }
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章