読者です 読者をやめる 読者になる 読者になる

WonderPlanet DEVELOPER BLOG

ワンダープラネットの開発者ブログです。モバイルゲーム開発情報を発信。

AndroidでViewのキャプチャを撮る

Android

今回のエンジニアブログを担当させていただきます、佐藤です。

今回はAndroidで、Viewのキャプチャを撮る→保存→メールに添付ということをやって行こうと思います!

・まずはキャプチャを撮る部分

/**  
 * キャプチャを撮る  
 * @param 撮りたいview  
 * @return 撮ったキャプチャ(Bitmap)  
 */  
public Bitmap getViewCapture(View view) {  
    view.setDrawingCacheEnabled(true);  
  
    // Viewのキャッシュを取得  
    Bitmap cache = view.getDrawingCache();  
    Bitmap screenShot = Bitmap.createBitmap(cache);  
    view.setDrawingCacheEnabled(false);  
    return screenShot;  
}  

撮りたいViewのキャッシュを有効にして、キャッシュからBitmapを作成しています。

・撮ったキャプチャの保存

/**  
 * 撮ったキャプチャを保存  
 * @param view  
 * @param 書き込み先ファイルfile  
 */  
public void saveCapture(View view, File file) {  
    // キャプチャを撮る  
    Bitmap capture = getViewCapture(view);  
    FileOutputStream fos = null;  
    try {  
        fos = new FileOutputStream(file, false);  
        // 画像のフォーマットと画質と出力先を指定して保存  
        capture.compress(CompressFormat.JPEG, 100, fos);  
        fos.flush();  
    } catch (Exception e) {  
        e.printStackTrace();  
    } finally {  
        if (fos != null) {  
            try {  
                fos.close();  
            } catch (IOException ie) {  
                fos = null;  
            }  
        }  
    }  
}  

先ほど作成したのメソッドでViewのキャプチャを取得して、保存をしています。

FileOutputStreamのコンストラクタ第2引数でappendの指定ができます。
今回は上書きモードですが、trueにすることで追記モードにもできます。
また、保存する画像の形式はCompressFormat.JPEG,CompressFormat.PNG,CompressFormat.WEBPといった指定の仕方をします。

・保存したキャプチャをメールに添付する

// パスを指定してファイルを読み込む  
File file = new File(Environment.getExternalStorageDirectory() + "/capture.jpeg");  
  
// メールアプリを起動  
Intent intent = new Intent();  
intent.setAction(Intent.ACTION_SEND);  
intent.putExtra(Intent.EXTRA_EMAIL, new String[] {"example@mail.com"});  
intent.setType("message/rfc822");  
// 添付ファイルを指定  
intent.putExtra(Intent.EXTRA_STREAM, Uri.fromFile(file));  
startActivity(intent);  

今回、添付する画像はストレージからじゃないと添付できないようなので、Environment.getExternalStorageDirectory()でストレージのパスを指定しています。

ストレージにアクセスするのでパーミッションの設定も忘れずにします。

AndroidManifest.xml

     <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>  

これで画像のキャプチャ → 保存 → メールに添付ができました!

SendScreenShotActivity.java

import java.io.File;  
import java.io.FileOutputStream;  
  
import android.app.Activity;  
import android.content.Intent;  
import android.graphics.Bitmap;  
import android.graphics.Bitmap.CompressFormat;  
import android.net.Uri;  
import android.os.Bundle;  
import android.os.Environment;  
import android.view.View;  
import android.view.View.OnClickListener;  
import android.widget.Button;  
  
public class SendScreenShotActivity extends Activity implements OnClickListener {  
  
    @Override  
    protected void onCreate(Bundle savedInstanceState) {  
        super.onCreate(savedInstanceState);  
        setContentView(R.layout.activity_main);  
        // 全体キャプチャ  
        Button captureAll = (Button)findViewById(R.id.capture_all);  
        captureAll.setOnClickListener(this);  
  
        // アイコン画像のみキャプチャ  
        Button captureIcon = (Button)findViewById(R.id.capture_icon);  
        captureIcon.setOnClickListener(this);  
  
        // キャプチャした画像を添付してメールを送る  
        Button sendMail = (Button)findViewById(R.id.send_mail);  
        sendMail.setOnClickListener(this);  
  
    }  
  
    @Override  
    public void onClick(View v) {  
        // 読み書きするファイル名を指定  
        File file = new File(Environment.getExternalStorageDirectory() + "/capture.jpeg");  
        // 指定したファイル名が無ければ作成する。  
        file.getParentFile().mkdir();  
  
        switch(v.getId()) {  
        case R.id.capture_all:  
            // 全体を撮る  
            saveCapture(findViewById(android.R.id.content),file);  
            break;  
        case R.id.capture_icon:  
            // View1を撮る  
            saveCapture(findViewById(R.id.icon),file);  
            break;  
        case R.id.send_mail:  
            Intent intent = new Intent();  
            intent.setAction(Intent.ACTION_SEND);  
            intent.putExtra(Intent.EXTRA_EMAIL, new String[] {"hoge@mail.com"});  
            intent.setType("message/rfc822");  
            intent.putExtra(Intent.EXTRA_STREAM, Uri.fromFile(file));  
            startActivity(intent);  
  
            break;  
        }  
    }  
  
    /**  
    * 撮ったキャプチャを保存  
    * @param view  
    * @param 書き込み先ファイルfile  
    */  
    public void saveCapture(View view, File file) {  
        // キャプチャを撮る  
        Bitmap capture = getViewCapture(view);  
        FileOutputStream fos = null;  
        try {  
            fos = new FileOutputStream(file, false);  
            // 画像のフォーマットと画質と出力先を指定して保存  
            capture.compress(CompressFormat.JPEG, 100, fos);  
            fos.flush();  
        } catch (Exception e) {  
            e.printStackTrace();  
        } finally {  
            if (fos != null) {  
                try {  
                    fos.close();  
                } catch (IOException ie) {  
                    fos = null;  
                }  
            }  
        }  
    }  
  
    /**  
    * キャプチャを撮る  
    * @param 撮りたいview  
    * @return 撮ったキャプチャ(Bitmap)  
    */  
    public Bitmap getViewCapture(View view) {  
        view.setDrawingCacheEnabled(true);  
  
        // Viewのキャプチャを取得  
        Bitmap cache = view.getDrawingCache();  
        if(cache == null){  
            return null;  
        }  
        Bitmap screenShot = Bitmap.createBitmap(cache);  
        view.setDrawingCacheEnabled(false);  
        return screenShot;  
    }  
}  

activity_main.xml

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"  
    xmlns:tools="http://schemas.android.com/tools"  
    android:layout_width="match_parent"  
    android:layout_height="match_parent"  
    android:background="#ffffff"  
    android:gravity="center_horizontal"  
    android:orientation="vertical">  
  
    <Button  
        android:id="@+id/capture_all"  
        android:layout_width="wrap_content"  
        android:layout_height="wrap_content"  
        android:text="@string/capture_all"   
        android:padding="@dimen/activity_vertical_margin"/>  
  
    <Button  
       android:id="@+id/capture_icon"  
       android:layout_width="wrap_content"  
       android:layout_height="wrap_content"  
       android:text="@string/capture_icon"  
       android:padding="@dimen/activity_vertical_margin" />  
  
    <ImageView  
       android:id="@+id/icon"  
       android:layout_width="wrap_content"  
       android:layout_height="wrap_content"  
       android:src="@drawable/ic_launcher"  
       android:padding="@dimen/activity_vertical_margin"/>  
  
    <Button  
       android:id="@+id/send_mail"  
       android:layout_width="wrap_content"  
       android:layout_height="wrap_content"  
       android:text="@string/send_mail"  
       android:padding="@dimen/activity_vertical_margin" />  
  
</LinearLayout>  
  

< 画面全体を撮ったときのキャプチャ >
capture
< アイコンのみ撮ったときのキャプチャ >
icon_capture

キャプチャを撮るViewにandroid.R.id.contentを指定すると表示されている全体のViewを取得することができます。
各Viewを指定すれば指定したView単体のキャプチャを取得できます。

Fileの読み書きが少しややこしく感じましたが、画面キャプチャが撮れるようになったので検証やシェア機能等に利用できそうだなと思いました!