2016-07-01 6 views
0

AndroidのDream Serviceをスクリーンセーバーとして使用するアプリケーションを開発しました。これは画像のスライドショーを表示します。これらの画像は、データベース内にバイナリ形式で格納され、デコードされる。私はこれが最善の方法ではないことを認識していますが、このアプリケーションの特定の構造と目的を考えると、最も現実的です。さらに、クラスはデータベースへの一定のトリップを行わず、イメージを連続的にデコードしません。リソースを開始して閉じたときにこれを行います。Android/Java - Dream Serviceのメモリ不足

スクリーンセーバーがしばらく実行された後、私はときどきメモリ不足エラーに関連すると思われる「アプリケーションが停止しました」というメッセージを受け取ることがあります。私が知っている限り、ビットマップは一度デコードされるだけです。サービスがウィンドウに添付されているからです。私はImageViewコンテナにビットマップをロードする唯一の反復的なアクションが、多大なリソースを必要とするとは思えないという理由で、メモリに問題があるのはなぜか分かりません。私は自分のコードを見て、問題を見つけることができませんでした。

私は間違っています。これらのエラーの発生を止めるにはどうすればよいですか?

public class screenSaver extends DreamService { 

    XmlPullParser parser; 
    String storeImages = ""; 

    // creates messages 

    public Bitmap drawText(Context c, int resource, String text) { 

     Resources resources = c.getResources(); 
     Bitmap bitmap = BitmapFactory.decodeResource(resources, resource); 
     android.graphics.Bitmap.Config config = bitmap.getConfig(); 
     if (config == null) { 
      config = android.graphics.Bitmap.Config.ARGB_8888; 

     } 
     bitmap = bitmap.copy(config, true); 
     Canvas canvas = new Canvas(bitmap); 
     TextPaint paint = new TextPaint(Paint.ANTI_ALIAS_FLAG); 
     float scale = resources.getDisplayMetrics().density; 
     paint.setColor(Color.BLACK); 
     paint.setTextSize(48 * scale); 

     int textWidth = canvas.getWidth() - (int) (16 * scale); 
     StaticLayout textLayout = new StaticLayout(text, paint, textWidth, Layout.Alignment.ALIGN_CENTER, 1f, 0f, false); 

     int textHeight = textLayout.getHeight(); 
     float x = (bitmap.getWidth() - textWidth)/2; 
     float y = (bitmap.getHeight() - textHeight)/2; 

     canvas.save(); 
     canvas.translate(x, y); 

     textLayout.draw(canvas); 
     canvas.restore(); 

     return bitmap; 
    } 

    ArrayList<Bitmap> imageList = new ArrayList<Bitmap>(); 
    int slideCounter = 0; 
    ImageView slide; 
    Cursor images; 
    Cursor corpImages; 
    final Handler handler = new Handler(Looper.getMainLooper()); 

    private int counter = 0; 

    private Runnable runnable = new Runnable() { 
     @Override 
     public void run() { 

      slide.setImageBitmap(imageList.get(counter)); 
      if (counter == (imageList.size() - 1)) { 
       counter = 0; 

      } else { 
       counter++; 

      } 

     } 
    }; 

    public screenSaver() { 

    } 

    @Override 
    public void onAttachedToWindow() { 
     super.onAttachedToWindow(); 
     setInteractive(false); 
     setFullscreen(true); 
     setContentView(R.layout.screen_saver); 

     databaseHelper dbHelper = new databaseHelper(this); 
     Intent testIntent = new Intent(this, lockActivity.class); 
     testIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK); 
     this.startActivity(testIntent); // unpin screen so screen saver can load 
     SQLiteDatabase db = dbHelper.getReadableDatabase(); 

     SharedPreferences preferences = getSharedPreferences("config", MODE_PRIVATE); 
     final String store = preferences.getString("store", ""); 

     String managerMessageText = ""; 
     String mainMessageText = ""; 
     String districtMessageText = ""; 
     try { 


      FileInputStream input = new FileInputStream(new File(this.getFilesDir(), "stores.xml")); 
      parser = Xml.newPullParser(); 

      parser.setInput(input, null); 

      // begin search for correct 'store' tag 
      boolean elementsRemain = true; 
      while (elementsRemain) { 
       parser.next(); 
       int event = parser.getEventType(); 
       switch (event) { 
        case XmlPullParser.START_TAG: 
         String name = parser.getName(); 

         if (name.equals("store")) { 
          Log.i("Screen Saver", "entering if store"); 
          String number = parser.getAttributeValue(null, "number"); 
          if (number.equals(store)) { 

           // located corresponding store, beginning parsing to find associate images and messages 

           boolean withinStore = true; 
           while (withinStore) { 
            parser.next(); 

            if (parser.getEventType() == XmlPullParser.START_TAG) { 

             String tag = parser.getName(); 
             if (tag.equals("images")) { 
              parser.nextTag(); 

              while (parser.getEventType() == XmlPullParser.START_TAG && parser.getName().equals("image")) { 
               if (parser.getAttributeValue(null, "id") != null && (!parser.getAttributeValue(null, "id").equals(""))) { 
                storeImages += parser.getAttributeValue(null, "id") + ","; 
               } 


               parser.nextTag(); 
               if (parser.getEventType() == XmlPullParser.END_TAG) { 
                parser.nextTag(); 
               } 
              } 
             } 
             parser.next(); 

             if (parser.getEventType() == XmlPullParser.TEXT) { 
              switch (tag) { 

               case "message": 
                managerMessageText += parser.getText(); 
                break; 
               case "district": 
                districtMessageText += parser.getText(); 
                break; 
               case "corporate": 
                mainMessageText += parser.getText(); 
                break; 
               default: 
                break; 
              } 
             } 
            } else if (parser.getEventType() == XmlPullParser.END_TAG && parser.getName().equals("store")) { 
             withinStore = false; 
            } 
           } 
           parser.next(); 
          } 
         } else { 

         } 
         break; 
        case XmlPullParser.END_DOCUMENT: 
         elementsRemain = false; 
         break; 


       } 


      } 

     } catch (Exception e) { 
      Log.e("Error reading XML ", " " + e.getMessage()); 
     } 

/*  LTO images 
    try { 
      File managerFile = new File(this.getFilesDir(), store + ".txt"); 
      File universalFile = new File(this.getFilesDir(), "universal.txt"); 
      File districtFile = new File(this.getFilesDir(), "district.txt"); 

      BufferedReader reader = new BufferedReader(new FileReader(managerFile)); 
      managerMessageText = reader.readLine(); 

      reader = new BufferedReader(new FileReader(universalFile)); 
      mainMessageText = reader.readLine(); 

      reader = new BufferedReader(new FileReader(districtFile)); 
      districtMessageText = reader.readLine(); 

     } catch (Exception e) { 
      Log.e("Error opening file: ", e.getMessage()); 
     }*/ 


     /* images = db.rawQuery("SELECT " + databaseHelper.IMAGE + " FROM " + databaseHelper.TABLE_NAME + " where " + databaseHelper.LTO + " = 1", null); 
     images.moveToFirst(); 

     while(!images.isAfterLast()) { 
      imageList.add(BitmapFactory.decodeByteArray(images.getBlob(images.getColumnIndex(databaseHelper.IMAGE)), 0, images.getBlob(images.getColumnIndex(databaseHelper.IMAGE)).length)); 
      images.moveToNext(); 
     } 
     images.close(); */ 


     if (storeImages.length() > 1) { 
      storeImages = storeImages.substring(0, storeImages.length() - 1); // remove trailing comma 
     } 


     // get all images that are associated with store 

     corpImages = db.rawQuery("SELECT " + databaseHelper.SLIDE_IMAGE + " FROM " + databaseHelper.SLIDE_TABLE + " WHERE " + databaseHelper.SLIDE_ID + " IN (" + storeImages + ")", null); 
     corpImages.moveToFirst(); 
     while (!corpImages.isAfterLast()) { 
      imageList.add(BitmapFactory.decodeByteArray(corpImages.getBlob(corpImages.getColumnIndex(databaseHelper.SLIDE_IMAGE)), 0, corpImages.getBlob(corpImages.getColumnIndex(databaseHelper.SLIDE_IMAGE)).length)); 
      corpImages.moveToNext(); 
     } 
     corpImages.close(); 
     db.close(); 

     // begin drawing message bitmaps 

     if (managerMessageText != "") { 
      imageList.add(drawText(this, R.drawable.message_background, "Manager Message: \n" + managerMessageText)); 
     } 
     if (mainMessageText != "") { 
      imageList.add(drawText(this, R.drawable.message_background, "Corporate Message: \n" + mainMessageText)); 
     } 
     if (districtMessageText != "") { 
      imageList.add(drawText(this, R.drawable.message_background, "District Manager Message: \n" + districtMessageText)); 
     } 


     slide = (ImageView) findViewById(R.id.slider); 
     Timer timer = new Timer(); 
     timer.scheduleAtFixedRate(new TimerTask() { 
      @Override 
      public void run() { 

       updateGUI(); 

      } 
     }, 0, 8000); 

    } 

    ; 

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

     // unpin screen so it can update 
     Intent testIntent = new Intent(this, lockActivity.class); 
     testIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK); 
     this.startActivity(testIntent); // unpin screen so it can update 
    } 


    private void updateGUI() { 
     if (reminder.running || hourlyReminder.running) { 

      this.finish(); 
     } else { 
      handler.post(runnable); 

     } 
    } 


} 

ありがとうございました。

+1

私は、これはビットマップの読み込みに問題があるかなり確信:

現在地全体のチュートリアルを見つけることができます。 [this](https://developer.android.com/training/displaying-bitmaps/load-bitmap.html)を読んでみてください。 –

答えて

0

decodeResource()メソッドを使用すると、構築されたビットマップに直接メモリを割り当てようとすると、&がOutOfMemoryになることがあります。ビットマップを効率的にデコードするには、いくつかのオプションがあります。

BitmapFactory.OptionsのJustDecodeBoundsをtrueに設定すると、復号化ステップでのメモリ割り当てが回避されます。このオプションを使用していないようです。

縮小/縮小版を表示する必要がある場合は、フル画像/ビットマップをメモリに読み込む必要はありません。これを制御するには、BitmapFactory.OptionsのinSampleSizeを設定します。このオプションを使用していないようです。

は、使用してみてください:

options.inJustDecodeBounds = true; 
options.inSampleSize = calculateInSampleSize(options, reqWidth, reqHeight); 

などのオプションメモリを効率的に処理するためにビットマップをデコード中。 https://developer.android.com/training/displaying-bitmaps/load-bitmap.html