2014年7月29日 星期二

【Android】開啟相機-照相功能與相簿-相片集並讀取相片匯入至程式

infor from : http://dean-android.blogspot.tw/2013/05/android.html


各位Android安卓開發者大家好 ^^
小黑人今天要跟大家分享的是如何"開啟相機"與"開啟相簿"並且將"圖片讀取匯入至程式內",如果各位開發者有接觸到拍照及相簿功能的話,那今天這個主題就會非常的息息相關囉,而且照相這個功能其實可以運用在很多地方,像Google Play上也有許許多多的拍照APP或者是圖片編輯APP,而這些APP都是跟開啟相機進行照相或者是從SD卡讀取相片圖片有關係,今天小黑人就與大家分享如何簡單的將照片匯入至程式內。
1.首先,要開啟相機功能與拍照後將相片存入SD卡內,則需要在AndroidManifest.xml開啟權限,所以我們先在AndroidManifest加入開啟相機權限與寫入SD卡權限 :

<uses-permission android:name="android.permission.CAMERA"/>
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>


2.Layout版面配置,小黑人自己先大概排個版面,畫面上有開啟相機Button、開啟相簿Button及顯示匯入照片的ImageView :<LinearLayout 
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
>

    <ImageView 
    android:id="@+id/img"
    android:layout_width="match_parent"
    android:layout_height="300dip"    
    />

    <Button
    android:id="@+id/camera"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:text="開啟相機"
    android:layout_weight="1"
    android:layout_gravity="center_vertical" 
    />
    
    <Button
    android:id="@+id/photo"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:text="開啟相簿"
    android:layout_weight="1"
    android:layout_gravity="center_vertical" 
    />

</LinearLayout>
3.最後就是開啟程式(.java)將各功能寫入啦 :public class MainActivity extends Activity 
{
   //宣告
   private ImageView mImg;
   private DisplayMetrics mPhone;
   private final static int CAMERA = 66 ;
   private final static int PHOTO = 99 ;
        
   @Override
   protected void onCreate(Bundle savedInstanceState) 
   {
      super.onCreate(savedInstanceState);
      setContentView(R.layout.main);
                
      //讀取手機解析度
      mPhone = new DisplayMetrics();
      getWindowManager().getDefaultDisplay().getMetrics(mPhone);
            
      mImg = (ImageView) findViewById(R.id.img);
      Button mCamera = (Button) findViewById(R.id.camera);
      Button mPhoto = (Button) findViewById(R.id.photo);
                
      mCamera.setOnClickListener(new OnClickListener()
      {
         @Override
         public void onClick(View v) 
         {
         //開啟相機功能,並將拍照後的圖片存入SD卡相片集內,須由startActivityForResult且
         帶入
         requestCode進行呼叫,原因為拍照完畢後返回程式後則呼叫onActivityResult
         ContentValues value = new ContentValues();
         value.put(Media.MIME_TYPE, "image/jpeg");                                      
         Uri uri= getContentResolver().insert(Media.EXTERNAL_CONTENT_URI,
                                              value); 
         Intent intent = new Intent("android.media.action.IMAGE_CAPTURE");
         intent.putExtra(MediaStore.EXTRA_OUTPUT, uri.getPath());  
         startActivityForResult(intent, CAMERA);      
         }
      });
                
      mPhoto.setOnClickListener(new OnClickListener()
      {
         @Override
         public void onClick(View v) 
         {
         //開啟相簿相片集,須由startActivityForResult且帶入requestCode進行呼叫,原因
         為點選相片後返回程式呼叫onActivityResult
         Intent intent = new Intent();
         intent.setType("image/*");
         intent.setAction(Intent.ACTION_GET_CONTENT);
         startActivityForResult(intent, PHOTO);
         }
      });
   }
        
   //拍照完畢或選取圖片後呼叫此函式
   @Override 
   protected void onActivityResult(int requestCode, int resultCode,Intent data)
   {
      //藉由requestCode判斷是否為開啟相機或開啟相簿而呼叫的,且data不為null
      if ((requestCode == CAMERA || requestCode == PHOTO ) && data != null)
      {
         //取得照片路徑uri
         Uri uri = data.getData();
         ContentResolver cr = this.getContentResolver();
                      
         try
         {
         //讀取照片,型態為Bitmap
         Bitmap bitmap = BitmapFactory.decodeStream(cr.openInputStream(uri));

         //判斷照片為橫向或者為直向,並進入ScalePic判斷圖片是否要進行縮放
         if(bitmap.getWidth()>bitmap.getHeight())ScalePic(bitmap,
                                                          mPhone.heightPixels);
         else ScalePic(bitmap,mPhone.widthPixels);
         } 
         catch (FileNotFoundException e)
         {
         }
      }
                
      super.onActivityResult(requestCode, resultCode, data);
   }
        
   private void ScalePic(Bitmap bitmap,int phone)
   {
      //縮放比例預設為1
      float mScale = 1 ;
                
      //如果圖片寬度大於手機寬度則進行縮放,否則直接將圖片放入ImageView內
      if(bitmap.getWidth() > phone )
      {
         //判斷縮放比例
         mScale = (float)phone/(float)bitmap.getWidth();
                      
         Matrix mMat = new Matrix() ;
         mMat.setScale(mScale, mScale);
                          
         Bitmap mScaleBitmap = Bitmap.createBitmap(bitmap,
                                                   0,
                                                   0,
                                                   bitmap.getWidth(),
                                                   bitmap.getHeight(),
                                                   mMat,
                                                   false);
         mImg.setImageBitmap(mScaleBitmap);
      }
   else mImg.setImageBitmap(bitmap);
   }
}
畫面預覽 :
以上就是今天小黑人跟大家分享的內容,照相與相簿的匯入運用,希望大家可以試試看~ ^^
如有任何問題可以跟小黑人討論交流唷!謝謝大家 XDD

Get/pick an image from Android's built-in Gallery

[Android] Activity之間如何透過Intent傳遞複雜結構的data


http://jimmy319.blogspot.tw/2011/12/android-activityintentdata-structure.html



Get/pick an image from Android's built-in Gallery app programmatically

http://stackoverflow.com/questions/2169649/get-pick-an-image-from-androids-built-in-gallery-app-programmatically

This is a complete solution. I've just updated this example code with the information provided in the answer below by @mad. Also check the solution below from @Khobaib explaining how to deal with picasa images.

Single Picture Selection

With support for images from file explorers thanks to user mad.
public class BrowsePictureActivity extends Activity {

    // this is the action code we use in our intent, 
    // this way we know we're looking at the response from our own action
    private static final int SELECT_PICTURE = 1;

    private String selectedImagePath;

    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);

        ((Button) findViewById(R.id.Button01))
                .setOnClickListener(new OnClickListener() {

                    public void onClick(View arg0) {

                        // in onCreate or any event where your want the user to
                        // select a file
                        Intent intent = new Intent();
                        intent.setType("image/*");
                        intent.setAction(Intent.ACTION_GET_CONTENT);
                        startActivityForResult(Intent.createChooser(intent,
                                "Select Picture"), SELECT_PICTURE);
                    }
                });
    }

    public void onActivityResult(int requestCode, int resultCode, Intent data) {
        if (resultCode == RESULT_OK) {
            if (requestCode == SELECT_PICTURE) {
                Uri selectedImageUri = data.getData();
                selectedImagePath = getPath(selectedImageUri);
            }
        }
    }

    /**
     * helper to retrieve the path of an image URI
     */
    public String getPath(Uri uri) {
            // just some safety built in 
            if( uri == null ) {
                // TODO perform some logging or show user feedback
                return null;
            }
            // try to retrieve the image from the media store first
            // this will only work for images selected from gallery
            String[] projection = { MediaStore.Images.Media.DATA };
            Cursor cursor = managedQuery(uri, projection, null, null, null);
            if( cursor != null ){
                int column_index = cursor
                .getColumnIndexOrThrow(MediaStore.Images.Media.DATA);
                cursor.moveToFirst();
                return cursor.getString(column_index);
            }
            // this is our fallback here
            return uri.getPath();
    }

}

Selecting Multiple Pictures

Since someone requested that information in a comment and it's better to have information gathered.
Set an extra parameter EXTRA_ALLOW_MULTIPLE on the intent:
intent.putExtra(Intent.EXTRA_ALLOW_MULTIPLE, true);
And in the Result handling check for that parameter:
if (Intent.ACTION_SEND_MULTIPLE.equals(action))
        && Intent.hasExtra(Intent.EXTRA_STREAM)) {
    // retrieve a collection of selected images
    ArrayList<Parcelable> list = intent.getParcelableArrayListExtra(Intent.EXTRA_STREAM);
    // iterate over these images
    for (Parcelable parcel : list) {
       Uri uri = (Uri) parcel;
       // handle the images one by one here
   }
} 
Note that this is only supported by API level 18+.