0

私のウィジェットには、ユーザー ギャラリーから画像を収集し、その画像を別のアクティビティの背景として設定する imageView があります。正常に動作しますが、大きすぎる画像ファイル (カメラからの画像など) を追加したり、多くの画像ファイルをアップロードしようとすると、「メモリ不足」エラーが発生します。しばらくスタックオーバーフローを見回した後、誰もが次の基本的な方法をほとんど使用していることに気付きました。

public static Bitmap decodeSampleImage(File f, int width, int height) {
try {
    System.gc(); // First of all free some memory

    // Decode image size

    BitmapFactory.Options o = new BitmapFactory.Options();
    o.inJustDecodeBounds = true;
    BitmapFactory.decodeStream(new FileInputStream(f), null, o);

    // The new size we want to scale to

    final int requiredWidth = width;
    final int requiredHeight = height;

    // Find the scale value (as a power of 2)

    int sampleScaleSize = 1;

    while (o.outWidth / sampleScaleSize / 2 >= requiredWidth && o.outHeight / sampleScaleSize / 2 >= requiredHeight)
        sampleScaleSize *= 2;

    // Decode with inSampleSize

    BitmapFactory.Options o2 = new BitmapFactory.Options();
    o2.inSampleSize = sampleScaleSize;

    return BitmapFactory.decodeStream(new FileInputStream(f), null, o2);
} catch (Exception e) {
    Log.d(TAG, e.getMessage()); // We don't want the application to just throw an exception
}

return null;
}

また、使用されていないビットマップもリサイクルされていることに気付きました。これがどのように機能するかは理解していますが、コーディングのどこに配置すればよいかわかりません。

これが私の2つのクラスです(背景を収集するimageViewがあるPersonalize.java。imageViewと2つのボタンがあります(1つはギャラリーから画像を選択し、その画像をimageViewに表示し、もう1つはそれを設定します)画像を背景として)。

まず、Personalize.java を次に示します。

package com.example.awesomefilebuilderwidget;

IMPORTS

public class Personalize extends Activity implements View.OnClickListener {
Button button;
ImageView image; //the imageview for setting the background
ImageView image2; //the imageview for setting the icon (not focusing on)
Button btnChangeImage;
Button btnChangeImageForIcon;
Button btnSetBackground;
private static final int SELECT_PICTURE = 1;
private static final int SELECT_PICTURE_2 = 2;
private String  selectedImagePath;
Bitmap background;

@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.personalize);

image = (ImageView) findViewById(R.id.imageView1);
image2 = (ImageView) findViewById(R.id.imageView2Icon);

Button btnChangeImage = (Button) findViewById(R.id.btnChangeImage);    
btnChangeImage.setOnClickListener(this);
Button btnChangeImageForIcon = (Button) findViewById(R.id.btnChangeImageForIcon); 
btnChangeImageForIcon.setOnClickListener(this);
Button btnSetBackground = (Button) findViewById(R.id.btnSetBackground);
btnSetBackground.setOnClickListener(this);

}

@Override 
public void onClick(View v) { 
switch (v.getId()) { 
case R.id.btnChangeImage: 
launchImageChooser(); 
break; 
case R.id.btnChangeImageForIcon: 
launchImageChooser(); 
break; 
case R.id.btnSetBackground: 
setBackgroundImageInDragAndDrop(); 
break; 
} 
} 

private void setBackgroundImageInDragAndDrop() {
Log.d("Personalize", "setBackgroundImageInDragAndDrop() called");
Intent i = getIntent();
//Convert bitmap to byte array to send back to activity
// See: http://stackoverflow.com/questions/11010386/send-bitmap-using-intent-android
ByteArrayOutputStream stream = new ByteArrayOutputStream();
background.compress(Bitmap.CompressFormat.PNG, 100, stream);
byte[]byteArray = stream.toByteArray();

i.putExtra("myBackgroundBitmap", byteArray);
setResult(RESULT_OK, i);
finish();
}

private void launchImageChooser() {
Intent intent = new Intent();
intent.setType("image/*");
intent.setAction(Intent.ACTION_GET_CONTENT);
intent.addCategory(Intent.CATEGORY_OPENABLE);
startActivityForResult(intent, SELECT_PICTURE);
}

public String getPath(Uri uri) {
String[] projection = { MediaStore.Images.Media.DATA };
Cursor cursor = getContentResolver().query(uri, projection, null, null, null);
int column_index = cursor
        .getColumnIndexOrThrow(MediaStore.Images.Media.DATA);
cursor.moveToFirst();
String imagePath = cursor.getString(column_index);
if(cursor != null) {
cursor.close();
}
return imagePath;
}

@Override
public void onActivityResult(int requestCode, int resultCode, Intent data)
{

if (resultCode == RESULT_OK) {
if (requestCode == SELECT_PICTURE)
{
    Uri selectedImageUri = data.getData();
    selectedImagePath = getPath(selectedImageUri);
    background = getAndDecodeImage(selectedImagePath);
    if(background != null){
        image.setImageBitmap(background); 
    }           
} else if (requestCode == SELECT_PICTURE_2)
{
    Uri selectedImageUri = data.getData();
    selectedImagePath = getPath(selectedImageUri);
    Bitmap b2 = getAndDecodeImage(selectedImagePath);
    if(b2 != null){
        image2.setImageBitmap(b2);
    }
}    
}
}

private Bitmap getAndDecodeImage(String  selectedImagePath){
try {
    Log.d("Personalize", "selectedImagePath: " + selectedImagePath);
    FileInputStream fileis=new FileInputStream(selectedImagePath);
    BufferedInputStream bufferedstream=new BufferedInputStream(fileis);
    byte[] bMapArray= new byte[bufferedstream.available()];
    bufferedstream.read(bMapArray);
    Bitmap bMap = BitmapFactory.decodeByteArray(bMapArray, 0, bMapArray.length);

    if (fileis != null) 
    {
        fileis.close();
    }
    if (bufferedstream != null) 
    {
        bufferedstream.close();
    }
    return bMap;
} catch (FileNotFoundException e) {                 
    e.printStackTrace();
} catch (IOException e) {                   
    e.printStackTrace();
}   
return null;
}


public boolean saveImageToInternalStorage(Bitmap image) {
   try {
      FileOutputStream fos = this.openFileOutput("desiredFilename.png",     Context.MODE_PRIVATE);
      image.compress(Bitmap.CompressFormat.PNG, 100, fos);
      fos.close();   
      return true;
   } catch (Exception e) {
   return false;
   }
}

}

次に、ここに私の Drag_and_Drop_App.java があります (重要な部分のスニペット -- ビットマップを収集し、背景として設定します):

package com.example.awesomefilebuilderwidget;

IMPORTS

public class Drag_and_Drop_App extends Activity {
private static final int SET_BACKGROUND = 10;

private ListView mListAppInfo;
// Search EditText
EditText inputSearch;
public AppInfoAdapter adapter;

@Override
public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);

    // set layout for the main screen
    setContentView(R.layout.drag_and_drop_app);

    // import buttons
    Button btnLinkToFeedback = (Button) findViewById(R.id.btnLinkToFeedback);
    Button btnLinkToPersonalize = (Button) findViewById(R.id.btnLinkToPersonalize);


    // Link to Personalize Screen
    btnLinkToPersonalize.setOnClickListener(new View.OnClickListener() {

        public void onClick(View view) {
            Intent i = new Intent(getApplicationContext(),
                    Personalize.class);
            startActivityForResult(i, SET_BACKGROUND);

        }
    });

}
public Bitmap getThumbnail(String filename) { 
     Bitmap thumbnail = null; 
     try { 
     File filePath = this.getFileStreamPath(filename); 
     FileInputStream fi = new FileInputStream(filePath); 
     thumbnail = BitmapFactory.decodeStream(fi); 
     } catch (Exception ex) { 
     Log.e("getThumbnail() on internal storage", ex.getMessage()); 
     } 
     return thumbnail; 
     } 

     @Override 
     protected void onActivityResult(int requestCode, int resultCode, Intent data) { 
     super.onActivityResult(requestCode, resultCode, data); 
     Log.i("Drag_and_Drop_App", "requestCode: " + requestCode + ", resultCode: " + resultCode); 
     if(requestCode == SET_BACKGROUND && resultCode == RESULT_OK){ 
     byte[] byteArray = data.getByteArrayExtra("myBackgroundBitmap"); 
     Bitmap myBackground = BitmapFactory.decodeByteArray(byteArray, 0, byteArray.length); 
     setBackgroundImage(myBackground); 
     } 
     } 

     @SuppressLint("NewApi") 
     private void setBackgroundImage(Bitmap bitmap) { 
     RelativeLayout yourBackgroundView = (RelativeLayout) findViewById(R.id.rl_drag_and_drop_app); 

     Drawable d = new BitmapDrawable(getResources(), bitmap); 

     if (Build.VERSION.SDK_INT < Build.VERSION_CODES.JELLY_BEAN) { 
     yourBackgroundView.setBackgroundDrawable(d); 
     } else { 
     yourBackgroundView.setBackground(d); 
     } 
     } 

     }

では、そのコーディングをどこに実装し、メモリ内の他の未使用のビットマップをどこで取り除くことができるでしょうか? (リサイクル?)

4

0 に答える 0