2012-01-16 2 views
2

У меня есть приложение, которое создает отчет в TableLayout с переменным числом TableRows.Растровые изображения и захват Android

Я использую следующий код, чтобы захватить таблицу в растровое изображение:

TableLayout tl = (TableLayout)findViewById(R.id.CSRTableLayout); 
Bitmap csr = Bitmap.createBitmap(tl.getWidth(), tl.getHeight(), Bitmap.Config.ARGB_8888); 
Canvas canvas = new Canvas(csr); 
tl.draw(canvas); 

После того как я захвата экрана как растровое изображение, я прикрепить его к электронной почте с помощью:

//folder already exists 
File file = new File(folder.getAbsolutePath()+"/CSR"+csrnum+".jpg"); 
BufferedOutputStream bos = null; 
FileOutputStream fos = null; 
try { 
    fos=new FileOutputStream(file); 
    bos=new BufferedOutputStream(fos); 
    if(bos!=null) { 
     try { 
      csr.compress(Bitmap.CompressFormat.JPEG, 60, bos); 
     } catch (OutOfMemoryError e) { 
      Toast.makeText(CustomerReportActivity.this, "Out of Memory!", Toast.LENGTH_SHORT).show(); 
     } finally { 
      fos.flush(); 
      fos.close(); 
      bos.flush(); 
      bos.close(); 
     } 
    } 
} catch (Exception e) { 
    e.printStackTrace(); 
} 
if(file.exists()) { 
    Intent i = new Intent(Intent.ACTION_SEND); 
    i.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK); 
    i.setType("message/rfc822"); 
    String emailTo[] = {"***@****.***"}; 
    i.putExtra(Intent.EXTRA_EMAIL,emailTo); 
    i.putExtra(Intent.EXTRA_SUBJECT,"..."); 
    i.putExtra(Intent.EXTRA_TEXT, "..."); 
    i.putExtra(Intent.EXTRA_STREAM,Uri.parse("file://"+file.getAbsolutePath())); 
    startActivity(i); 
} else { 
    Toast.makeText(CustomerReportActivity.this, "Error attaching report to email!", Toast.LENGTH_SHORT).show(); 
} 

Проблема заключается в том, что иногда таблица может стать довольно большой, например, 1600x2400dp. Я получил OutOfMemoryError в строке «Bitmap.createBitmap (...)» Есть ли альтернативный метод захвата экрана, не переполняя кучу VM? Если я правильно понимаю, вызов Bitmap.createBitmap (...) создает растровое изображение полного размера, который является просто белым. Возможно ли создать его без NO пиксельных данных и заполнить его только после того, как я позвонил csr.compress (...), чтобы он оставался маленьким? Любые идеи/предложения приветствуются! Заранее спасибо!

+0

Я думаю, что это ваш друг http: // stackoverflow.com/questions/5663671/create-a-empty-bitmap-and-drawing-but-canvas-in-android, и я бы рекомендовал использовать Bitmap.Config.ARGB_8 при запуске, а затем обновить его. –

+0

Подробнее об этом http://stackoverflow.com/questions/477572/android-strange-out-of-memory-issue –

+0

попробуйте добавить в файл манифеста asenovm

ответ

0

К сожалению, не было возможности избежать моей проблемы. Мне просто пришлось использовать более низкую настройку качества и надеяться, что размер не станет слишком большим. Попытка масштабирования растрового изображения не работала должным образом и заканчивалась искаженным изображением.

0

За несколько дней до того, как у меня будет такая же задача. Если вы хотите, чтобы захватить экран, и что изображение должно быть сообщение по электронной почте, пожалуйста, изучить ниже код, который я использовал, чтобы сделать это:

saveImageInLandscapFunction(); // function to save the Image 

          Intent picMessageIntent = new Intent(android.content.Intent.ACTION_SEND); 
          picMessageIntent.setType("image/jpeg"); 
          File f = new File(APP_FILE_PATH + "/"+filename+".jpg"); 
          picMessageIntent.putExtra(Intent.EXTRA_STREAM, Uri.fromFile(f)); 
          startActivity(picMessageIntent); 

функции, которые принимают скриншоте и и сохранить в SDCard

protected void saveImageInLandscapFunction() { 
    View root = findViewById(android.R.id.content); 
    root.setDrawingCacheEnabled(true); 
    Bitmap bm = Bitmap.createBitmap(root.getDrawingCache()); 
    //Bitmap bm = Bitmap.createBitmap(root.getDrawingCache(), 0, 0, display.getWidth(), display.getHeight()); 
    root.setDrawingCacheEnabled(false); 

    // Bitmap overlayBitmap = overlay(photoBitmap, mBitmap); // overlay the Bitmap 

    new ExportBitmapToFile(DrawMainActivity.this, bm).execute(); 
    sendBroadcast(new Intent(Intent.ACTION_MEDIA_MOUNTED, Uri.parse("file://"+ Environment.getExternalStorageDirectory()))); 

} 

класса, которые обрабатывают основной процесс сохранения изображения и показать ProgressBar до изображения сохраняются:

// for to saw progressBar 
public static class ExportBitmapToFile extends AsyncTask<Intent,Void,Boolean> { 
    private Context mContext; 
    private Handler mHandler; 
    private Bitmap nBitmap; 
    private ProgressDialog m_progressDialog = null; 
    @Override  
    protected void onPreExecute(){   
     m_progressDialog = new ProgressDialog(mContext); 
     m_progressDialog.setTitle("Draw"); 
     m_progressDialog.setMessage("Please wait..."); 
     m_progressDialog.setCancelable(false);   
     m_progressDialog.show();  
    } 

    public ExportBitmapToFile(Context context,Bitmap bitmap) { 
     mContext = context; 
     nBitmap = bitmap; 

    } 

    @Override 
    protected Boolean doInBackground(Intent... arg0) { 
     try { 
      if (!APP_FILE_PATH.exists()) { 
       APP_FILE_PATH.mkdirs(); 
      } 
      final FileOutputStream out = new FileOutputStream(new File(APP_FILE_PATH + "/"+filename+".jpg")); 
      nBitmap.compress(Bitmap.CompressFormat.JPEG, 100, out); 
      out.flush(); 
      out.close(); 
      return true; 
     }catch (Exception e) { 
      e.printStackTrace(); 
     } 
     //mHandler.post(completeRunnable); 
     return false; 
    } 

    @Override 
    protected void onPostExecute(Boolean bool) { 
     super.onPostExecute(bool); 
     if (bool){ 
      //mHandler.sendEmptyMessage(1); 
     } 
     if (m_progressDialog.isShowing()) {    
      m_progressDialog.dismiss();   
     } 
    } 
} 

Надеется, что это будет угрюмым помочь вам.

Сообщите мне, если вы хотите получить другую помощь.

Наслаждайтесь. :)

+0

Ваша проблема решена? –

+0

Ваше решение не решает проблемы с памятью. Он очень важен так же, как и то, что я сейчас делаю –

+0

@ D.R .: Ok Это работает для меня, поэтому я стараюсь вас. –

0

Почему бы вам не разбить изображения на несколько небольших регионов и отправить ... вы можете затем их сшить ... или если у вас есть терпение и умение ... вы можете сшивать изображения прочитав файлы меньшего размера, сохраненные на диске, и отправьте сшитое изображение ... Вы можете использовать перевод и клип холста перед отправкой методу draw(), чтобы получить требуемые регионы

+0

Не могли бы вы привести пример или образец кода? К сожалению, все это нужно сделать в приложении и не может быть выполнено сервером в другом месте. Мое понимание вашего ответа - захватить экран на несколько растровых изображений, затем объединить их и прикрепить к электронной почте. Это верно? Будут ли у меня проблемы с памятью в приложении, когда я рекомбинирую, а затем передаю его в намерение электронной почты? –

+0

У меня нет примера/источника для этого ... просто была идея об этом ... и я не думаю, что вы столкнулись с проблемой памяти, так как вы будете работать с файлами после того, как вы сохраните изображения деталей на диск ... и вы можете использовать буферизованный поток файлов для работы с ним .... снова все это теоретическое ... вы можете столкнуться с некоторыми другими проблемами при разработке, которые я не могу гарантировать ... –

0

При создании растрового изображения, почему вы не используете хардкор - ширина и высота.

Bitmap result = Bitmap.createScaledBitmap(bitmapPicture, 
         640, 480, false); 

Попробуйте это, сообщите мне, если это поможет.

0

Попробуйте объединить ваше решение и iDroid Explorer. Проверьте, можете ли вы записать файл прямо из кэша чертежа. You код будет выглядеть следующим образом:

try { 
    BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream(file)); 
    if(bos!=null) { 
     try { 
      TableLayout tl = (TableLayout)findViewById(R.id.CSRTableLayout); 
      tl.setDrawingCacheEnabled(true); 
      Bitmap csr = tl.getDrawingCache(); 
      csr.compress(Bitmap.CompressFormat.JPEG, 60, bos); 
      tl.setDrawingCacheEnabled(false); 
     } catch (OutOfMemoryError e) { 
      Toast.makeText(CustomerReportActivity.this, "Out of Memory!", Toast.LENGTH_SHORT).show(); 
     } finally { 
      bos.close(); 
     } 
    } 
} catch (Exception e) { 
    e.printStackTrace(); 
} 

Может быть, вам нужно переработать csr после выключения рисования кэша.

+0

Я буду завтра это проверим. Видимо, вы не можете поймать и OutOfMemoryError, так что это боль в тестировании! Я отвечу назад и отвечу, как только я закончу! –

Смежные вопросы