2016-07-19 24 views
0

我仍然是java和android編程方面的新手,我相信在過去的幾周裏我已經走到了盡頭,但現在我有點卡住了,我真的很感激你幫幫我。在佈局/活動更改後,使上傳的圖像保持不變

我想開發一個可以創建用戶配置文件佈局的應用程序。到目前爲止,我已經準備好了,從Web服務中繪製用戶的數據。但現在我必須添加一種方式讓用戶從畫廊或相機上傳他的照片。

public void loadimage (View view) 
{ 
    Intent intent = new Intent(Intent.ACTION_PICK, MediaStore.Images.Media.EXTERNAL_CONTENT_URI); 
    startActivityForResult(intent, 0); 
} 

public void onActivityResult(int requestCode, int resultCode, Intent data) 
{ 
    super.onActivityResult(requestCode, resultCode, data); 

    if (resultCode == RESULT_OK) 
    { 
     Uri targetUri = data.getData(); 
     picture_location = targetUri.toString(); 
     textTargetUri.setText(picture_location); 
     Bitmap bitmap; 
     try 
     { 
      bitmap = BitmapFactory.decodeStream(getContentResolver().openInputStream(targetUri)); 
      targetImage.setImageBitmap(bitmap); 
     } 
     catch (FileNotFoundException e) 
     { 
      e.printStackTrace(); 
     } 
    } 
} 

這真正的作品在繪畫從廚房的形象和在屏幕上顯示的路徑文件(當然,這是不會讓我的最終版本),但是:到目前爲止,我已經與下一個代碼實現了這個,當我輸入另一個佈局/活動時,加載的圖像消失,我不得不再次上載它。我下一個省電方法嘗試:

@Override 
protected void onRestoreInstanceState(Bundle savedInstanceState) 
{ 
    image = savedInstanceState.getParcelable("BitmapImage"); 
    targetImage.setImageBitmap(image); 
    textTargetUri.setText(savedInstanceState.getString("path_to_picture")); 
} 

@Override 
public void onSaveInstanceState (Bundle savedInstanceState) 
{ 
    super.onSaveInstanceState(savedInstanceState); 
    savedInstanceState.putParcelable("BitmapImage", bitmap); 
    savedInstanceState.putString("path_to_picture", picture_location); 
} 

然而,篩網orientarion變化,而不是佈局/活性的變化這僅適用。即使活動發生變化,是否有辦法讓上傳的圖像保持不變?我的服務器在內存方面很小,所以上傳它並不是一個好的選擇,我必須保持它在本地。請幫助:(

+0

爲什麼不只是將圖像存儲在某處,然後從該URI將圖像加載到ImageView? – Eenvincible

回答

1

嘗試這兩種方法:

首先,向他們展示一個對話框,選擇選項:

private void selectImage() { 
    final CharSequence[] items = { getString(R.string.take_photo), getString(R.string.choose_from_gallery), 
      getString(R.string.cancel) }; 

    AlertDialog.Builder builder = new AlertDialog.Builder(MyAccountActivity.this); 
    builder.setTitle(getString(R.string.upload_photo)); 
    builder.setItems(items, new DialogInterface.OnClickListener() { 
     @Override 
     public void onClick(DialogInterface dialog, int item) { 
      if (items[item].equals(getString(R.string.take_photo))) { 
       Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE); 
       startActivityForResult(intent, REQUEST_CAMERA); 
      } else if (items[item].equals(getString(R.string.choose_from_gallery))) { 
       Intent intent = new Intent(
         Intent.ACTION_PICK, 
         android.provider.MediaStore.Images.Media.EXTERNAL_CONTENT_URI); 
       intent.setType("image/*"); 
       startActivityForResult(
         Intent.createChooser(intent, getString(R.string.select_file)), 
         SELECT_FILE); 
      } else if (items[item].equals(getString(R.string.choose_from_gallery))) { 
       dialog.dismiss(); 
      } 
     } 
    }); 
    builder.show(); 
} 

接收實際圖像當用戶拍攝的照片或選擇從畫廊:

​​

下一個是如果你需要處理裁剪 - 這是沒有必要的這段代碼工作,但你可以使用它;

private void onCaptureImageResult(Intent data) { 

    beginCrop(data.getData()); 
} 

@SuppressWarnings("deprecation") 
private void onSelectFromGalleryResult(Intent data) { 
    Uri selectedImageUri = data.getData(); 

    beginCrop(selectedImageUri); 
} 

private void beginCrop(Uri source) { 
    Uri destination = Uri.fromFile(new File(getCacheDir(), "cropped")); 
    Crop.of(source, destination).asSquare().start(this); 
} 

private void handleCrop(int resultCode, Intent result) { 
    if (resultCode == RESULT_OK) { 

     try { 
      Bitmap bitmap = handleSamplingAndRotationBitmap(this, Crop.getOutput(result)); 

      saveToInternalStorage(bitmap); 

      mUserProfilePhoto.setImageBitmap(readFromInternalStorage("profile.png")); 
     }catch (IOException e){ /* do nothing here */} 
    } else if (resultCode == Crop.RESULT_ERROR) { 
     Toast.makeText(this, Crop.getError(result).getMessage(), Toast.LENGTH_SHORT).show(); 
    } 
} 

有時候,你可能要旋轉的圖像,如果它不是正直

private static Bitmap handleSamplingAndRotationBitmap(Context context, Uri selectedImage) throws IOException { 
    int MAX_HEIGHT = 1024; 
    int MAX_WIDTH = 1024; 

    final BitmapFactory.Options options = new BitmapFactory.Options(); 
    options.inJustDecodeBounds = true; 
    InputStream imageStream = context.getContentResolver().openInputStream(selectedImage); 
    BitmapFactory.decodeStream(imageStream, null, options); 
    imageStream.close(); 

    // Calculate inSampleSize 
    options.inSampleSize = calculateInSampleSize(options, MAX_WIDTH, MAX_HEIGHT); 

    // Decode bitmap with inSampleSize set 
    options.inJustDecodeBounds = false; 
    imageStream = context.getContentResolver().openInputStream(selectedImage); 
    Bitmap img = BitmapFactory.decodeStream(imageStream, null, options); 

    img = rotateImageIfRequired(img, selectedImage); 
    return img; 
} 

private static int calculateInSampleSize(BitmapFactory.Options options, 
             int reqWidth, int reqHeight) { 
    // Raw height and width of image 
    final int height = options.outHeight; 
    final int width = options.outWidth; 
    int inSampleSize = 1; 

    if (height > reqHeight || width > reqWidth) { 

     // Calculate ratios of height and width to requested height and width 
     final int heightRatio = Math.round((float) height/(float) reqHeight); 
     final int widthRatio = Math.round((float) width/(float) reqWidth); 

     // Choose the smallest ratio as inSampleSize value, this will guarantee a final image 
     // with both dimensions larger than or equal to the requested height and width. 
     inSampleSize = heightRatio < widthRatio ? heightRatio : widthRatio; 

     // This offers some additional logic in case the image has a strange 
     // aspect ratio. For example, a panorama may have a much larger 
     // width than height. In these cases the total pixels might still 
     // end up being too large to fit comfortably in memory, so we should 
     // be more aggressive with sample down the image (=larger inSampleSize). 

     final float totalPixels = width * height; 

     // Anything more than 2x the requested pixels we'll sample down further 
     final float totalReqPixelsCap = reqWidth * reqHeight * 2; 

     while (totalPixels/(inSampleSize * inSampleSize) > totalReqPixelsCap) { 
      inSampleSize++; 
     } 
    } 
    return inSampleSize; 
} 

private static Bitmap rotateImageIfRequired(Bitmap img, Uri selectedImage) throws IOException { 

    ExifInterface ei = new ExifInterface(selectedImage.getPath()); 
    int orientation = ei.getAttributeInt(ExifInterface.TAG_ORIENTATION, ExifInterface.ORIENTATION_NORMAL); 

    switch (orientation) { 
     case ExifInterface.ORIENTATION_ROTATE_90: 
      return rotateImage(img, 90); 
     case ExifInterface.ORIENTATION_ROTATE_180: 
      return rotateImage(img, 180); 
     case ExifInterface.ORIENTATION_ROTATE_270: 
      return rotateImage(img, 270); 
     default: 
      return img; 
    } 
} 

private static Bitmap rotateImage(Bitmap img, int degree) { 
    Matrix matrix = new Matrix(); 
    matrix.postRotate(degree); 
    Bitmap rotatedImg = Bitmap.createBitmap(img, 0, 0, img.getWidth(), img.getHeight(), matrix, true); 
    img.recycle(); 
    return rotatedImg; 
} 

對於當用戶從畫廊挑選或從相機拍攝儘快存儲:

private boolean saveToInternalStorage(Bitmap image) { 

    try { 
     FileOutputStream fos = this.openFileOutput("profile.png", Context.MODE_PRIVATE); 

     image.compress(Bitmap.CompressFormat.PNG, 100, fos); 
     fos.close(); 

     return true; 
    } catch (Exception e) { 
     return false; 
    } 
} 

現在從存儲中讀取:

private Bitmap readFromInternalStorage(String filename){ 
    try { 
     File filePath = this.getFileStreamPath(filename); 
     FileInputStream fi = new FileInputStream(filePath); 
     return BitmapFactory.decodeStream(fi); 
    } catch (Exception ex) { /* do nothing here */} 

    return null; 
} 

Inside onResume,I ha已經此代碼的圖像設置爲ImageView的:

@Override 
public void onResume(){ 
    super.onResume(); 

    Bitmap savedProfilePhoto = readFromInternalStorage("profile.png"); 

    if (savedProfilePhoto != null){ 
     mUserProfilePhoto.setImageBitmap(savedProfilePhoto); 
    } 
} 

這裏幾乎做到:

添加到您的依賴關係(的build.gradle)

dependencies{ 
    compile 'com.soundcloud.android:android-crop:[email protected]' 
} 

最後,在你的Android清單文件,爲剪裁庫工作,添加此:

<activity android:name="com.soundcloud.android.crop.CropImageActivity"/> 

這就是所有你需要啓用從ga選擇圖像在您的應用程序內使用相機或照相機拍照!

我希望這可以幫助你和其他需要和祝你好運的人!

+0

哇,夥計,這是如此完整,很抱歉回答這個晚,我昨天忙於其他事情。我會立即嘗試你的方法。非常感謝Eenvincible! – mrRSA

+0

如果有幫助,請記住投票並接受它;我在我的項目中實際使用此代碼並且工作得很好 – Eenvincible

+0

還有一件事,您是否使用任何外部庫? – mrRSA