OSDN Git Service

d251b992dd1e803b6d95d4d05490eaa66ee2ce50
[gokigen/MeMoMa.git] / app / src / main / java / jp / sourceforge / gokigen / memoma / ObjectLayoutCaptureExporter.java
1 package jp.sourceforge.gokigen.memoma;
2
3 import java.io.File;
4 import java.io.FileOutputStream;
5 import java.io.OutputStream;
6 import java.text.SimpleDateFormat;
7 import java.util.Calendar;
8 import java.util.Enumeration;
9
10 import android.app.Activity;
11 import android.app.ProgressDialog;
12 import android.graphics.Bitmap;
13 import android.graphics.Bitmap.CompressFormat;
14 import android.graphics.Canvas;
15 import android.graphics.Rect;
16 import android.os.AsyncTask;
17 import android.util.Log;
18 import android.view.Display;
19
20 /**
21  *  データをファイルに保存するとき用 アクセスラッパ (非同期処理を実行)
22  *  Viewの情報を画像形式(png形式)で保存する。
23  *  どのViewを保存するのかは、ICaptureExporter.getCaptureTargetView()クラスを使って教えてもらう。
24  *  
25  *  AsyncTask
26  *    String       : 実行時に渡すクラス(Param)           : ファイル名をもらう
27  *    Integer    : 途中経過を伝えるクラス(Progress)   : 今回は使っていない
28  *    String      : 処理結果を伝えるクラス(Result)      : 結果を応答する。
29  *    
30  * @author MRSa
31  *
32  */
33 public class ObjectLayoutCaptureExporter extends AsyncTask<String, Integer, String>
34 {
35         private static final int OUTPUT_MARGIN = 8;
36         private static final int OUTPUT_MARGIN_TOP = 50;
37         
38         private static final int MINIMUM_WIDTH = 800;
39         private static final int MINIMUM_HEIGHT = 600;
40         
41         private Activity parent = null;
42         private ICaptureLayoutExporter receiver = null;
43         private ExternalStorageFileUtility fileUtility = null;  
44         private String exportedFileName = null; 
45         private MeMoMaObjectHolder objectHolder = null;
46         private MeMoMaCanvasDrawer canvasDrawer = null;
47         private ProgressDialog savingDialog = null;
48         private float offsetX = 0.0f;
49         private float offsetY = 0.0f;
50
51         /**
52          *   コンストラクタ
53          */
54     public ObjectLayoutCaptureExporter(Activity context, ExternalStorageFileUtility utility,  MeMoMaObjectHolder holder, MeMoMaCanvasDrawer drawer, ICaptureLayoutExporter resultReceiver)
55     {
56         receiver = resultReceiver;
57         fileUtility = utility;
58         objectHolder = holder;
59         canvasDrawer = drawer;
60         parent = context;
61
62         //  プログレスダイアログ(「保存中...」)を表示する。
63         savingDialog = new ProgressDialog(context);
64         savingDialog.setProgressStyle(ProgressDialog.STYLE_SPINNER);
65         savingDialog.setMessage(context.getString(R.string.dataSaving));
66         savingDialog.setIndeterminate(true);
67         savingDialog.setCancelable(false);
68         savingDialog.show();
69
70         /** ファイルをバックアップするディレクトリを作成する **/
71         File dir = new File(fileUtility.getGokigenDirectory() + "/exported");
72         dir.mkdir();
73     }
74         
75     /**
76      *  非同期処理実施前の前処理
77      * 
78      */
79     @Override
80     protected void onPreExecute()
81     {
82         // なにもしない。
83     }
84     
85     /**
86      *    ビットマップデータを(PNG形式で)保管する。
87      * 
88      * @param fileName
89      * @param objectHolder
90      * @return
91      */
92     private String exportToFile(String fileName, Bitmap targetBitmap)
93     {
94         String resultMessage = "";
95         try
96         {
97                 if (targetBitmap == null)
98                 {
99                         // ビットマップが取れないため、ここで折り返す。
100                         return ("SCREEN DATA GET FAILURE...");
101                 }
102                 
103                 // エクスポートするファイル名を決定する
104             Calendar calendar = Calendar.getInstance();
105             SimpleDateFormat outFormat = new SimpleDateFormat("yyyyMMddHHmmss");
106             exportedFileName = fileName + "_" + outFormat.format(calendar.getTime()) + ".png";
107
108             // PNG形式でファイル出力を行う。
109             OutputStream out = new FileOutputStream(exportedFileName);
110             targetBitmap.compress(CompressFormat.PNG, 100, out);
111             out.flush();
112             out.close();            
113         }
114         catch (Exception e)
115         {
116                 resultMessage = " ERR(png)>" + e.toString();
117             Log.v(Main.APP_IDENTIFIER, resultMessage);
118             e.printStackTrace();
119         } 
120         return (resultMessage);
121     }
122     
123     /**
124      *    キャンバスの大きさがどれくらい必要か、チェックする。
125      * 
126      * @return
127      */
128     private Rect checkCanvasSize()
129     {
130         Rect canvasSize = new Rect();
131
132         // オブジェクトの配置位置を探る。
133         Enumeration<Integer> keys = objectHolder.getObjectKeys();
134         while (keys.hasMoreElements())
135         {
136             Integer key = keys.nextElement();
137             MeMoMaObjectHolder.PositionObject pos = objectHolder.getPosition(key);
138             if (canvasSize.left > pos.rect.left)
139             {
140                 canvasSize.left = (int) pos.rect.left;
141             }
142             if (canvasSize.right < pos.rect.right)
143             {
144                 canvasSize.right = (int) pos.rect.right;
145             }
146             if (canvasSize.top > pos.rect.top)
147             {
148                 canvasSize.top = (int) pos.rect.top;
149             }
150             if (canvasSize.bottom < pos.rect.bottom)
151             {
152                 canvasSize.bottom = (int) pos.rect.bottom;
153             }
154         }
155         
156         // 描画領域にちょっと余裕を持たせる
157         canvasSize.left = canvasSize.left - OUTPUT_MARGIN;
158         canvasSize.right = canvasSize.right + OUTPUT_MARGIN;
159         canvasSize.top = canvasSize.top - OUTPUT_MARGIN_TOP;
160         canvasSize.bottom = canvasSize.bottom + OUTPUT_MARGIN;
161         canvasSize.sort();
162
163         // 現在の画面サイズを取得
164         Display display = parent.getWindowManager().getDefaultDisplay();
165         int width = display.getWidth();
166         int height = display.getHeight();
167         if (width < MINIMUM_WIDTH)
168         {
169                 width = MINIMUM_WIDTH;
170         }
171         if (height < MINIMUM_HEIGHT)
172         {
173                 height = MINIMUM_HEIGHT;
174         }        
175
176         // 出力の最小サイズを(表示画面サイズに)設定
177         if (canvasSize.width() < width)
178         {
179                 canvasSize.right = canvasSize.left + width;
180         }
181         if (canvasSize.height() < height)
182         {
183                 canvasSize.bottom = canvasSize.top + height;
184         }
185         
186         
187         // 画像位置(キャンバス位置)の調整。。。
188         offsetX = 0.0f - canvasSize.left - (OUTPUT_MARGIN);
189         offsetY = 0.0f - canvasSize.top - (OUTPUT_MARGIN);
190
191         // 出力する画像データのサイズを表示する
192         Log.v(Main.APP_IDENTIFIER, "ObjectLayoutCaptureExporter::checkCanvasSize() w:" + canvasSize.width() + " , h:" + canvasSize.height() + "  offset :(" + offsetX + "," + offsetY + ")");
193         return (canvasSize);
194     }    
195
196     /**
197      *  非同期処理
198      *  (バックグラウンドで実行する(このメソッドは、UIスレッドと別のところで実行する))
199      * 
200      */
201     @Override
202     protected String doInBackground(String... datas)
203     {
204         Rect canvasSize = checkCanvasSize();
205         Bitmap targetBitmap = Bitmap.createBitmap(canvasSize.width(), canvasSize.height(), Bitmap.Config.RGB_565);
206         Canvas targetCanvas = new Canvas(targetBitmap);
207         
208         // オブジェクトをビットマップの中に書き込む
209         canvasDrawer.drawOnBitmapCanvas(targetCanvas, offsetX, offsetY);
210
211         // ファイル名の設定 ... (拡張子なし)
212         String fileName = fileUtility.getGokigenDirectory() + "/exported/" + datas[0];
213
214         // データを保管する
215         String result = exportToFile(fileName, targetBitmap);
216
217         System.gc();
218
219         return (result);
220     }
221
222     /**
223      *  非同期処理の進捗状況の更新
224      * 
225      */
226         @Override
227         protected void onProgressUpdate(Integer... values)
228         {
229         // 今回は何もしない
230         }
231
232     /**
233      *  非同期処理の後処理
234      *  (結果を応答する)
235      */
236     @Override
237     protected void onPostExecute(String result)
238     {
239         try
240         {
241             if (receiver != null)
242             {
243                 receiver.onCaptureLayoutExportedResult(exportedFileName, result);
244             }
245         }
246         catch (Exception ex)
247         {
248                 Log.v(Main.APP_IDENTIFIER, "ViewCaptureExporter::onPostExecute() : " + ex.toString());
249         }
250         // プログレスダイアログを消す
251         if (savingDialog != null)
252         {
253             savingDialog.dismiss();
254         }
255         return;
256     }     
257  
258     /**
259      *    結果報告用のインタフェース
260      *    
261      * @author MRSa
262      *
263      */
264     public interface ICaptureLayoutExporter
265     {
266         /**  保存結果の報告 **/
267         public abstract void onCaptureLayoutExportedResult(String exportedFileName, String detail);
268     }
269 }