androidでアプリからスクリーンショット撮る方法(超個人的メモ) – PPPNeXus Notes -代表の気まぐれブログ-

androidでアプリからスクリーンショット撮る方法(超個人的メモ)

img

めちゃくちゃ個人的なメモです。

簡単にスクショ撮れるシステム作りたいなぁと思っていろいろやっております。

new Thread(new Runnable() {
@Override
public void run() {
// マルチスレッドにしたい処理 ここから
try {
Process sh = Runtime.getRuntime().exec(“su”, null,null);

OutputStream os = sh.getOutputStream();
os.write((“/system/bin/screencap -p ” + “/sdcard/img.png”).getBytes(“ASCII”));
os.flush();

os.close();
try {
sh.waitFor();
} catch (InterruptedException e) {
e.printStackTrace();
}
} catch (IOException e) {
e.printStackTrace();
}
// マルチスレッドにしたい処理 ここまで
}
}).start();

これでスクショ撮影中の待機時間も別スレッドなので
スクショ中に動きがとまりません!
suいるのかな。。
ちょっと検証してみます。

追記

やはりsuが無いとだめだったみたいなのでいろいろ調べたところ

Android5.0以降なら許可してもらえばrootなしでキャプチャ出来そうです!

Bitmap画像保存

new Thread(new Runnable() {
@Override
public void run() {
Bitmap cap = getScreenshot();
try {
// sdcardフォルダを指定
File root = Environment.getExternalStorageDirectory();

// 日付でファイル名を作成
Date mDate = new Date();
SimpleDateFormat fileName = new SimpleDateFormat(“yyyyMMdd_HHmmss”);

// 保存処理開始
FileOutputStream fos = null;
fos = new FileOutputStream(new File(root + “/screencap/”, fileName.format(mDate) + “.png”));

// pngで保存
cap.compress(CompressFormat.PNG, 100, fos);

// 保存処理終了
fos.close();
} catch (Exception e) {
Log.e(“Error”, “” + e.toString());
}
}
}).start();

これは普通の画像保存処理ですね。
キモは「getScreenshot」です。

実は今回ChatHead式に画面上にボタンを常駐させ

好きな時にぱっとスクショが撮れるシステムを作っております。

そのため少し実装が特殊になっていますのでご注意ください。
スクショを取得

private Bitmap getScreenshot() {
// ImageReaderから画面を取り出す
Image image = MainActivity.mImageReader.acquireLatestImage();
Image.Plane[] planes = image.getPlanes();
ByteBuffer buffer = planes[0].getBuffer();

int pixelStride = planes[0].getPixelStride();
int rowStride = planes[0].getRowStride();
int mWidth = SupportClass.getWidth(getApplicationContext());
int mHeight = SupportClass.getHeight(getApplicationContext());
int rowPadding = rowStride – pixelStride * mWidth;

// バッファからBitmapを生成
Bitmap bitmap = Bitmap.createBitmap(
mWidth + rowPadding / pixelStride, mHeight,
Bitmap.Config.RGB_565);
bitmap.copyPixelsFromBuffer(buffer);
image.close();

return bitmap;
}

途中でMainActivityからstatic参照しています。
許可をもらうための関係でActivityじゃないと許可できないんですよね。。
そのためMainActivityで許可をいただいたうえで画面を保持し
それをstatic参照してServiceで扱えるようにしています。
画面取得の許可取得

static ImageReader mImageReader;

//省略…

requestCapturePermission();

//省略…

public void requestCapturePermission(){
mMediaProjectionManager = (MediaProjectionManager)
getSystemService(Context.MEDIA_PROJECTION_SERVICE);

// MediaProjectionの利用にはパーミッションが必要。
// ユーザーへの問い合わせのため、Intentを発行
Intent permissionIntent = mMediaProjectionManager.createScreenCaptureIntent();
startActivityForResult(permissionIntent, 282);

//なんでもいいので282でべた書きしていますw

}

そしてonActivityResultで許可を受けたらいろいろ準備しちゃいます。
画面状態を保持

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

//ここも282でべた書き
if (282 == requestCode) {
if (resultCode != RESULT_OK) {
//パーミッションなし
Toast.makeText(this, “permission denied”, Toast.LENGTH_LONG).show();
return;
}
// MediaProjectionの取得
mMediaProjection =
mMediaProjectionManager.getMediaProjection(resultCode, intent);

DisplayMetrics metrics = getResources().getDisplayMetrics();
int mWidth = metrics.widthPixels;
int mHeight = metrics.heightPixels;
int density = metrics.densityDpi;

Log.d(“Log”,”setup VirtualDisplay”);
mImageReader = ImageReader
.newInstance(mWidth, mHeight, ImageFormat.RGB_565, 2);
mVirtualDisplay = mMediaProjection
.createVirtualDisplay(“Capturing Display”,
mWidth, mHeight, density,
DisplayManager.VIRTUAL_DISPLAY_FLAG_AUTO_MIRROR,
mImageReader.getSurface(), null, null);
}
}

順番が前後しましたが、これでVirutualDisplayが保持できていれば
先ほどの「getScreenshot()」を実行すればbitmapを取得できます。
ちょっとややこしいですが、参考になれば。。。

ついでに保存した画像のギャラリーへの反映です!
ギャラリーへの反映

public void saveFileDisp(String picturePath){
String[] paths = {picturePath};//保存された画像のパス
String[] mimeTypes = {“image/png”};

MediaScannerConnection.scanFile(
getApplicationContext(), paths, mimeTypes, new OnScanCompletedListener() {

@Override
public void onScanCompleted(String path, Uri uri) {
Log.d(“スキャンしたファイルのパス”, “-> path=” + path);
Log.d(“ContentProviderのURI”, “-> uri=” + uri);
}
});
}

Top