Android教程網
  1. 首頁
  2. Android 技術
  3. Android 手機
  4. Android 系統教程
  5. Android 游戲
 Android教程網 >> Android技術 >> 關於Android編程 >> Android開發:獲得相冊圖片、拍照、照片上傳服務器、從服務器讀取照片

Android開發:獲得相冊圖片、拍照、照片上傳服務器、從服務器讀取照片

編輯:關於Android編程

一. 整體功能描述

通過從相冊中選擇圖片或者拍照的方式獲得圖片,然後將這個圖片上傳至服務器,同時實現從服務器上讀取該圖片。

二. 功能實現

1.1 獲得圖片

(1)通常情況下,有以下兩種方式:

從相冊中選擇圖片
這種方式原理比較簡單,就是從SDK中獲得照片,轉成字節再生產Bitmap對象用於顯示即可。

拍照獲得圖片
拍照獲取的圖片原理就是先拍照存儲,然後再讀取,就和從相冊中選擇圖片的原理一樣了。

(2)實現:
下面是實現該功能的代碼,由於某種不知名的原因,拍照獲得圖片的方式一直存在問題:無法加載此圖片。解決解決,始終無法解決,就暫且擱下了。本文的重點還是放在了第二部分,關於上傳到服務器,第一部分還需要進一步完善,關於圖片的選擇和處理。

首先是點擊頭像彈出一個dialog供選擇讀入圖片的方式:
 private    CharSequence []its = {"拍照","從相冊選擇"};
 //上傳頭像
 headImageView.setOnClickListener(new View.OnClickListener() {
 @Override
 public void onClick(View v) {
     new AlertDialog.Builder(ModiUserInfoActivity.this)
                    .setTitle("更換頭像")
                    .setItems(its, new DialogInterface.OnClickListener() {
                    @Override
                    public void onClick(DialogInterface dialog, int which) { 
                    Intent intent = new Intent();
                    switch (which)
                    {
                        case 0://拍照,沒有實現的部分,暫時就不貼代碼了,其實暗想應該不難,但是問題卻一直不能解決。
                            break;
                        case 1://從相冊選擇
                            intent.setAction(Intent.ACTION_GET_CONTENT);//ACTION_OPEN_DOCUMENT
                            intent.addCategory(Intent.CATEGORY_OPENABLE);
                            intent.setType("image/*");
                            //intent.putExtra("return-data", true);//返回數據
                            //intent.putExtra("crop", "true");//裁剪
                            startActivityForResult(intent,SELECT_PIC);//啟動activity,重寫onActivityResult獲取結果
                            break;
                                }
                            }
                        })
                        .create()
                        .show();
            }
        });
    }
然後就是對圖片數據進行處理了
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
   if (resultCode != RESULT_OK)
       return;
       switch (requestCode)
       {
           case SELECT_PIC://相冊

              // ContentResolver resolver = getContentResolver();
              //照片的原始資源地址
              // Uri originalUri = data.getData();
              // Log.i("originalUri",originalUri+"");
              Bitmap photo = null;
              // try
              // {
              photo = data.getParcelableExtra("data");
              //photo = BitmapFactory.decodeStream(resolver.openInputStream(originalUri));
               if(photo!=null)
               {
                   headImage = Common.zoomBitmap(photo, 85, 85);//進行了縮放,可以忽視
                   UserController.updateHeadImage(userId, headImage, handler);//上傳服務器更新,後面貼代碼
                   photo.recycle();//回收
               }
                   //headImageView.setImageBitmap(headImage);
            /*   }catch (IOException e) {
                   e.printStackTrace();
               }*/
               break;
           case SELECT_CAMERA://相機,下面代碼寫了不少,但是一直存在問題~
               try {
                   // 啟動gallery去剪輯這個照片
                   //final Intent intent = Common.getCropImageIntent(Uri.fromFile(photoFile));
                   //startActivityForResult(intent, SELECT_PIC);
                   Intent intent = new Intent("com.android.camera.action.CROP"); //剪裁
                   intent.setDataAndType(photoFile, "image/*");
                   intent.putExtra("scale", true);
                    //設置寬高比例
                   intent.putExtra("aspectX", 1);
                   intent.putExtra("aspectY", 1);
                   intent.putExtra("outputX", 80);
                   intent.putExtra("outputY", 80);
                   intent.putExtra(MediaStore.EXTRA_OUTPUT, photoFile);
                   //Toast.makeText(ModiUserInfoActivity.this, photoFile.toString(), Toast.LENGTH_SHORT).show();
                   //廣播刷新相冊
                    Intent intentBc = new Intent(Intent.ACTION_MEDIA_SCANNER_SCAN_FILE);
                    intentBc.setData(photoFile);
                    this.sendBroadcast(intentBc);
                    startActivityForResult(intent, CROP_PHOTO); //設置裁剪參數顯示圖片至ImageView
               } catch (Exception e) {
                   e.printStackTrace();
               }
               break;
           case CROP_PHOTO:
               try {
                   //圖片解析成Bitmap對象
                   Bitmap bitmap = BitmapFactory.decodeStream(
                           getContentResolver().openInputStream(photoFile));
                   //Toast.makeText(ModiUserInfoActivity.this, imageUri.toString(), Toast.LENGTH_SHORT).show();
                   headImage = Common.zoomBitmap(bitmap, 85, 85);
                   UserController.updateHeadImage(userId, headImage, handler);
               } catch(FileNotFoundException e) {
                   e.printStackTrace();
               }
               break;
           default:
               break;
       }

    }

ok,按照上面的代碼,從相冊選擇照片加裁剪是沒有問題了,至於對圖片的一些處理。

1.2上傳到服務器並保存

查閱了很多資料,使用的方式要麼都是那種上傳文件那類看起來就特別復雜的方式,看的我真的頭大了。後來找了好幾個版本自己都沒能成功實現把1.1中獲取的圖片上傳到服務器。後來回想了一下http請求不就是傳送的字節嘛,那我把圖片轉成字節不就能傳過去了麼,另一個問題又來了,有時候我們並不是單單傳送一張圖片過去,可能還有其他信息,比如一個表單或者一個id之類的,總之要傳送的數據還有不僅僅是圖片。之前傳送數據都是通過json或者map轉成String再轉成byte[]實現的,那麼現在傳送的是圖片+其他數據,思路便是:圖片->String,然後和其他數據一起打包成json->String->byte[]->Bitmap。

客戶端
現在接著寫1.1中代碼使用到的UserController.updateHeadImage(userId, headImage, handler)。
/**
 * 保存頭像
 * @param userId
 * @param handler
 * @param image
 */
 public static void updateHeadImage(final String userId,final Bitmap image, final Handler handler)
 {
     new Thread()
        {
            @Override
            public void run()
            {
                JSONObject jsonObject = new JSONObject();
                try {
                    jsonObject.put("userId",userId);
                    //將Bitmap轉成String,其實這是一個加密過程。後面會有Common.Bitmap2String()的代碼。
                    jsonObject.put("userImageContent", Common.Bitmap2String(image));

                    String content = String.valueOf(jsonObject);
                    /**
                     * 請求地址
                     */
                    String url =  ConfigModel.getServerURL()+"user/updateImage";
                    String result = Common.httpPost(url,content);//post請求服務器:數據content,請求路徑url。這個函數也是自己寫在Common類裡,其實就是稍微封裝了一下post請求的過程,方便復用。
                    Log.i("result",result);
                    /**
                     * 服務器返回結果
                     * 繼續干什麼事情....
                     */
                    Message message = new Message();
                    Bundle bundle = new Bundle();
                    bundle.putString("result",result);
                    message.setData(bundle);
                    message.what = R.id.save_user_image_result;
                    handler.sendMessage(message);

                }catch (Exception e){}
            }
        }.start();
    }
服務器端
客戶端將圖片加密成了String,那麼服務端就需要解碼就可以獲得圖片。
//第一步,將數據流轉String,自己封裝成了一個read函數,方便復用;
String streamIn = ReadStream.read(new BufferedInputStream(request.getInputStream()));
//JSONObject object = JSONObject.fromObject(streamIn).getJSONObject("user");
JSONObject object = JSONObject.fromObject(streamIn);//String轉JSON
String userId = object.getString("userId");
String userImageContent = object.getString("userImageContent");//獲得圖像的數據
//..其他步驟省略
//..比如判斷是否是新圖像,比如生成圖像ID imgId = Tool.getUUID();
//第二步將圖像數據String轉成Bitmap
byte[] bitmapArray= Base64.decode(imageContent);
try
{
    File imageFile = new File(headImagePath);  
    if(!imageFile.exists())
        imageFile.mkdirs();
        //創建輸出流  
    FileOutputStream outStream = new FileOutputStream(imageFile.getPath()+"\\"+imgId+".png");  
        //寫入數據  
    outStream.write(bitmapArray);  
        //關閉輸出流  
    outStream.close();             
}
catch(IOException e)
{
    System.out.println(e);
}

由此就完美的將客戶端的圖像和數據都上傳到服務器上了。下面部分就是從服務器上獲得圖片和數據再返回給客戶端,有了前面部分的思路,那這部分就很容易實現,反其道而行之就可以了。

1.3從服務器中獲得圖片並顯示

服務器端
服務器端要做的事情就是將Bitmap轉成String,然後和其他數據打包成json,返回給客戶端。
//讀取圖片,轉成String
    public static String readImage(String imgId)
    {
        //byte []data = imageContent.getBytes();
        File file = new File(headImagePath+imgId+".png");
        try {
            FileInputStream inputStream = new FileInputStream(file);
            byte[] bitmapArray = new byte[(int) file.length()];
            inputStream.read(bitmapArray);
            inputStream.close();
            return Base64.encode(bitmapArray);
        } catch(Exception e)
        {
            return "";
        }
    }
    //*****************************************
    //代碼片.....和上面的代碼不在同一個java文件中
    //*****************************************
    /**
     * 查詢一個user
     * 
     * @param userId
     *            主鍵
     * @return user
     */
    @RequestMapping(value = "/user/get/{id}")
    @ResponseBody
    public JSONObject get(@PathVariable("id") String userId,
            HttpServletResponse response) {
        response.setHeader("Access-Control-Allow-Origin", "*");
        User user = userDAO.getUser(userId);
        JSONObject jsonObject = new JSONObject();
        jsonObject.put("user", user);
        if(user.getUserImage()!=null&&!"".equals(user.getUserImage()))
        {   
            jsonObject.put("userImageContent", Tool.readImage(user.getUserImage()));
        }
        return jsonObject;
    }
客戶端
這部分我就不貼代碼了,因為自己把很多功能都封裝了,要貼出來有點麻煩,總之此時的圖片數據已經轉成了String,只需要在顯示的時候,再轉成Bitmap。String->Bitmap的實現請參考我的Common類。

1.4Common類中的輔助工具

 /**
     * 圖像轉字節
     * @param bm
     * @return
     */
    public static byte[] Bitmap2Bytes(Bitmap bm) {
        ByteArrayOutputStream baos = new ByteArrayOutputStream();
        bm.compress(Bitmap.CompressFormat.PNG, 100, baos);
        return baos.toByteArray();
    }

    /**
     * 圖像轉String
     * @param bitmap
     * @return
     */
    public static String Bitmap2String(Bitmap bitmap)
    {
        return Base64.encodeToString(Bitmap2Bytes(bitmap), Base64.DEFAULT);
    }
    /**
     * string轉成bitmap
     *
     * @param st
     */
    public static Bitmap String2Bitmap(String st)
    {
        Bitmap bitmap = null;
        try
        {
            byte[] bitmapArray;
            bitmapArray = Base64.decode(st, Base64.DEFAULT);
            bitmap = BitmapFactory.decodeByteArray(bitmapArray, 0, bitmapArray.length);
            return bitmap;
        }
        catch (Exception e)
        {
            return null;
        }
    }

OK,最後大功告成,後面再解決拍照、以及圖片處理的問題!

  1. 上一頁:
  2. 下一頁:
熱門文章
閱讀排行版
Copyright © Android教程網 All Rights Reserved