どのプログラムではなくコードから電話スクリーンの選択された領域のスクリーンショットを撮るにはどうすればいいですか?
これが私のスクリーンショットをSDカードに保存し、後であなたの必要性が何であれ使用することを可能にするコードです:
まず、ファイルを保存するための適切な権限を追加する必要があります。
<uses-permission Android:name="Android.permission.WRITE_EXTERNAL_STORAGE"/>
そしてこれが(Activityで実行されている)コードです:
private void takeScreenshot() {
Date now = new Date();
Android.text.format.DateFormat.format("yyyy-MM-dd_hh:mm:ss", now);
try {
// image naming and path to include sd card appending name you choose for file
String mPath = Environment.getExternalStorageDirectory().toString() + "/" + now + ".jpg";
// create bitmap screen capture
View v1 = getWindow().getDecorView().getRootView();
v1.setDrawingCacheEnabled(true);
Bitmap bitmap = Bitmap.createBitmap(v1.getDrawingCache());
v1.setDrawingCacheEnabled(false);
File imageFile = new File(mPath);
FileOutputStream outputStream = new FileOutputStream(imageFile);
int quality = 100;
bitmap.compress(Bitmap.CompressFormat.JPEG, quality, outputStream);
outputStream.flush();
outputStream.close();
openScreenshot(imageFile);
} catch (Throwable e) {
// Several error may come out with file handling or DOM
e.printStackTrace();
}
}
そして、これは最近生成された画像を開く方法です:
private void openScreenshot(File imageFile) {
Intent intent = new Intent();
intent.setAction(Intent.ACTION_VIEW);
Uri uri = Uri.fromFile(imageFile);
intent.setDataAndType(uri, "image/*");
startActivity(intent);
}
これをフラグメントビューで使用したい場合は、次のように使用します。
View v1 = getActivity().getWindow().getDecorView().getRootView();
の代わりに
View v1 = getWindow().getDecorView().getRootView();
on takeScreenshot() function
注 :
ダイアログにサーフェスビューが含まれている場合、この解決策は機能しません。詳細については、次の質問に対する回答を確認してください。
このメソッドを呼び出して、スクリーンショットが必要な最も外側のViewGroupを渡します。
public Bitmap screenShot(View view) {
Bitmap bitmap = Bitmap.createBitmap(view.getWidth(),
view.getHeight(), Config.ARGB_8888);
Canvas canvas = new Canvas(bitmap);
view.draw(canvas);
return bitmap;
}
注:根ざした電話でのみ動作します
プログラム的には、以下のようにadb Shell /system/bin/screencap -p /sdcard/img.png
を実行できます。
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();
sh.waitFor();
それならimg.png
をBitmap
として読み、あなたの願いとして使ってください。
編集:マイナス投票との慈悲を持っています。私が質問に答えたとき、それは2010年に本当でした。
スクリーンショットを許可するすべてのプログラムは、根ざした電話でのみ動作します。
ルート権限なし または 大きなコーディングなし はこのメソッドに必要です。
下記のコマンドを使ってadbシェルでスクリーンショットを撮ることができます。
input keyevent 120
このコマンドはroot権限を必要としないので、AndroidアプリケーションのJavaコードからも実行できます。
Process process;
process = Runtime.getRuntime().exec("input keyevent 120");
Androidのキーイベントコードの詳細については、 http://developer.Android.com/reference/Android/view/KeyEvent.html を参照してください。
ここで私たちは使ってきました。 KEYCODE_SYSRQ その値は120で、System Request/Print Screenキーに使用されます。
CJBSが言ったように、出力画像は /sdcard/Pictures/Screenshots に保存されます。
Mualigの答えはとても良いのですが、私はEwoksが述べているのと同じ問題を抱えていました、私は背景を得ていません。だから時々十分に良いですそして時々私は黒いテーマの上に黒いテキストを得ます(テーマによって異なります)。
この解決策は、Mualigコードと私がRobotiumで見つけたコードに大きく基づいています。 drawメソッドを直接呼び出すことによって描画キャッシュの使用を破棄しています。その前に、まず現在のアクティビティから背景を描画可能にして、最初にそれを描画します。
// Some constants
final static String SCREENSHOTS_LOCATIONS = Environment.getExternalStorageDirectory().toString() + "/screenshots/";
// Get device dimmensions
Display display = getWindowManager().getDefaultDisplay();
Point size = new Point();
display.getSize(size);
// Get root view
View view = mCurrentUrlMask.getRootView();
// Create the bitmap to use to draw the screenshot
final Bitmap bitmap = Bitmap.createBitmap(size.x, size.y, Bitmap.Config.ARGB_4444);
final Canvas canvas = new Canvas(bitmap);
// Get current theme to know which background to use
final Activity activity = getCurrentActivity();
final Theme theme = activity.getTheme();
final TypedArray ta = theme
.obtainStyledAttributes(new int[] { Android.R.attr.windowBackground });
final int res = ta.getResourceId(0, 0);
final Drawable background = activity.getResources().getDrawable(res);
// Draw background
background.draw(canvas);
// Draw views
view.draw(canvas);
// Save the screenshot to the file system
FileOutputStream fos = null;
try {
final File sddir = new File(SCREENSHOTS_LOCATIONS);
if (!sddir.exists()) {
sddir.mkdirs();
}
fos = new FileOutputStream(SCREENSHOTS_LOCATIONS
+ System.currentTimeMillis() + ".jpg");
if (fos != null) {
if (!bitmap.compress(Bitmap.CompressFormat.JPEG, 90, fos)) {
Log.d(LOGTAG, "Compress/Write failed");
}
fos.flush();
fos.close();
}
} catch (FileNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
private void captureScreen() {
View v = getWindow().getDecorView().getRootView();
v.setDrawingCacheEnabled(true);
Bitmap bmp = Bitmap.createBitmap(v.getDrawingCache());
v.setDrawingCacheEnabled(false);
try {
FileOutputStream fos = new FileOutputStream(new File(Environment
.getExternalStorageDirectory().toString(), "SCREEN"
+ System.currentTimeMillis() + ".png"));
bmp.compress(CompressFormat.PNG, 100, fos);
fos.flush();
fos.close();
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
マニフェストに権限を追加します
<uses-permission Android:name="Android.permission.WRITE_EXTERNAL_STORAGE"/>
Supporting Marshmallow または上記のバージョンの場合は、アクティビティのonCreateメソッドに次のコードを追加してください。
ActivityCompat.requestPermissions(this,new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE},00);
参考として、画面をキャプチャする方法の1つとして(アプリのアクティビティだけではありません)、 framebuffer (device/dev/graphics/fb0)をキャプチャします。これを行うには、root権限を持っているか、または signature権限 ( "要求しているアプリケーションがその権限を宣言したアプリケーションと同じ証明書で署名されている場合にのみ許可される権限"のどちらかです) ) - あなた自身のROMをコンパイルしない限り、これは非常にありそうもないです。
私がテストしたいくつかのデバイスからのそれぞれのフレームバッファキャプチャは、 正確に 1つのスクリーンショットを含みました。人々はそれがもっと含まれていると報告しました、私はそれがフレーム/ディスプレイサイズに依存すると思います。
フレームバッファを連続して読み込もうとしましたが、一定量のバイトが読み取られたようです。私の場合、それは(3 410 432)バイトで、854 * 480 RGBA(3 279 360バイト)の表示フレームを格納するのに十分です。はい、fb0から出力されるバイナリのフレームは、私のデバイスでは _ rgba _ です。これはおそらくデバイスによって異なります。これはあなたがそれをデコードするために重要になるでしょう=)
私のデバイスでは /dev/graphics/fb0 パーミッションはrootとグループgraphicsのユーザーだけがfb0を読み込めるようになっています。
graphics は制限されたグループなので、あなたはおそらくsuコマンドを使って根ざした電話でのみfb0にアクセスするでしょう。
Androidアプリには、 ユーザーID(uid)= app _ ## および グループID(guid)= app _ ## があります。
adb Shell has uid = Shell および guid = Shell 。これはアプリよりもはるかに多くの権限を持ちます。実際に/system/permissions/platform.xmlでそれらの許可を確認できます。
これはあなたがrootなしでadbシェルのfb0を読むことができるでしょうがあなたはrootなしでアプリの中でそれを読むことができないことを意味します。
また、AndroidManifest.xmlでREAD_FRAME_BUFFERまたはACCESS_SURFACE_FLINGERのアクセス許可を与えても、通常のアプリケーションでは何もしません。これらは ' signature 'アプリケーションに対してのみ機能するためです。
詳しくはクローズドスレッドもご覧ください。
私の解決策は:
public static Bitmap loadBitmapFromView(Context context, View v) {
DisplayMetrics dm = context.getResources().getDisplayMetrics();
v.measure(MeasureSpec.makeMeasureSpec(dm.widthPixels, MeasureSpec.EXACTLY),
MeasureSpec.makeMeasureSpec(dm.heightPixels, MeasureSpec.EXACTLY));
v.layout(0, 0, v.getMeasuredWidth(), v.getMeasuredHeight());
Bitmap returnedBitmap = Bitmap.createBitmap(v.getMeasuredWidth(),
v.getMeasuredHeight(), Bitmap.Config.ARGB_8888);
Canvas c = new Canvas(returnedBitmap);
v.draw(c);
return returnedBitmap;
}
そして
public void takeScreen() {
Bitmap bitmap = ImageUtils.loadBitmapFromView(this, view); //get Bitmap from the view
String mPath = Environment.getExternalStorageDirectory() + File.separator + "screen_" + System.currentTimeMillis() + ".jpeg";
File imageFile = new File(mPath);
OutputStream fout = null;
try {
fout = new FileOutputStream(imageFile);
bitmap.compress(Bitmap.CompressFormat.JPEG, 90, fout);
fout.flush();
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} finally {
fout.close();
}
}
画像は外部保存フォルダに保存されます。
次のライブラリを試すことができます。 http://code.google.com/p/Android-screenshot-library/ Androidスクリーンショットライブラリ(ASL)は、rootアクセス権限を必要とせずにAndroidデバイスからスクリーンショットをプログラムでキャプチャすることを可能にします。 。代わりに、ASLは、デバイスの起動ごとに1回、Android Debug Bridge(ADB)を介して起動される、バックグラウンドで実行されているネイティブサービスを利用します。
public class ScreenShotActivity extends Activity{
private RelativeLayout relativeLayout;
private Bitmap myBitmap;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
relativeLayout = (RelativeLayout)findViewById(R.id.relative1);
relativeLayout.post(new Runnable() {
public void run() {
//take screenshot
myBitmap = captureScreen(relativeLayout);
Toast.makeText(getApplicationContext(), "Screenshot captured..!", Toast.LENGTH_LONG).show();
try {
if(myBitmap!=null){
//save image to SD card
saveImage(myBitmap);
}
Toast.makeText(getApplicationContext(), "Screenshot saved..!", Toast.LENGTH_LONG).show();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
});
}
public static Bitmap captureScreen(View v) {
Bitmap screenshot = null;
try {
if(v!=null) {
screenshot = Bitmap.createBitmap(v.getMeasuredWidth(),v.getMeasuredHeight(), Config.ARGB_8888);
Canvas canvas = new Canvas(screenshot);
v.draw(canvas);
}
}catch (Exception e){
Log.d("ScreenShotActivity", "Failed to capture screenshot because:" + e.getMessage());
}
return screenshot;
}
public static void saveImage(Bitmap bitmap) throws IOException{
ByteArrayOutputStream bytes = new ByteArrayOutputStream();
bitmap.compress(Bitmap.CompressFormat.PNG, 40, bytes);
File f = new File(Environment.getExternalStorageDirectory() + File.separator + "test.png");
f.createNewFile();
FileOutputStream fo = new FileOutputStream(f);
fo.write(bytes.toByteArray());
fo.close();
}
}
追加権限
<uses-permission Android:name="Android.permission.WRITE_EXTERNAL_STORAGE"/>
上の@JustinMorrisとここの@NiravDangiの答えに基づいて https://stackoverflow.com/a/8504958/2232148 私たちはビューの背景と前景を取り、このように組み立てる必要があります。
public static Bitmap takeScreenshot(View view, Bitmap.Config quality) {
Bitmap bitmap = Bitmap.createBitmap(view.getWidth(), view.getHeight(), quality);
Canvas canvas = new Canvas(bitmap);
Drawable backgroundDrawable = view.getBackground();
if (backgroundDrawable != null) {
backgroundDrawable.draw(canvas);
} else {
canvas.drawColor(Color.WHITE);
}
view.draw(canvas);
return bitmap;
}
QualityパラメータはBitmap.Configの定数を取り、通常はBitmap.Config.RGB_565
またはBitmap.Config.ARGB_8888
のいずれかです。
GLSurfaceViewをキャプチャしたい人にとっては、getDrawingCacheやキャンバスへの描画メソッドは機能しません。
あなたはフレームがレンダリングされた後にOpenGLフレームバッファの内容を読まなければなりません。良い答えがあります ここ
あなたはこのようなことをやろうとすることができます、
まずレイアウトやビューからビットマップキャッシュを取得するには、まずレイアウトにsetDrawingCacheEnabled
を付けます(linearlayout、relativelayout、またはビュー)。
それから
Bitmap bm = layout.getDrawingCache()
それからあなたはあなたがビットマップを使ってあなたが望む何でもします。画像ファイルに変換するか、ビットマップのURIを別の場所に送信してください。
簡単な方法は
FrameLayout layDraw = (FrameLayout) findViewById(R.id.layDraw); /*Your root view to be part of screenshot*/
layDraw.buildDrawingCache();
Bitmap bmp = layDraw.getDrawingCache();
私はView
からスクリーンショットを取り、あなたにBitmapオブジェクトを与えるか、あなたが望む任意のパスに直接保存する単純なライブラリを作成しました
あなたがfragment
からスクリーンショットを撮りたいなら、これに従ってください:
onCreateView()
をオーバーライドします。
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
// Inflate the layout for this fragment
View view = inflater.inflate(R.layout.fragment_one, container, false);
mView = view;
}
スクリーンショットを撮るためのロジック:
button.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
View view = mView.findViewById(R.id.scrollView1);
shareScreenShotM(view, (NestedScrollView) view);
}
メソッドshareScreenShotM)()
:
public void shareScreenShotM(View view, NestedScrollView scrollView){
bm = takeScreenShot(view,scrollView); //method to take screenshot
File file = savePic(bm); // method to save screenshot in phone.
}
メソッドtakeScreenShot():
public Bitmap takeScreenShot(View u, NestedScrollView z){
u.setDrawingCacheEnabled(true);
int totalHeight = z.getChildAt(0).getHeight();
int totalWidth = z.getChildAt(0).getWidth();
Log.d("yoheight",""+ totalHeight);
Log.d("yowidth",""+ totalWidth);
u.layout(0, 0, totalWidth, totalHeight);
u.buildDrawingCache();
Bitmap b = Bitmap.createBitmap(u.getDrawingCache());
u.setDrawingCacheEnabled(false);
u.destroyDrawingCache();
return b;
}
メソッドsavePic():
public static File savePic(Bitmap bm){
ByteArrayOutputStream bytes = new ByteArrayOutputStream();
bm.compress(Bitmap.CompressFormat.JPEG, 100, bytes);
File sdCardDirectory = new File(Environment.getExternalStorageDirectory() + "/Foldername");
if (!sdCardDirectory.exists()) {
sdCardDirectory.mkdirs();
}
// File file = new File(dir, fileName);
try {
file = new File(sdCardDirectory, Calendar.getInstance()
.getTimeInMillis() + ".jpg");
file.createNewFile();
new FileOutputStream(file).write(bytes.toByteArray());
Log.d("Fabsolute", "File Saved::--->" + file.getAbsolutePath());
Log.d("Sabsolute", "File Saved::--->" + sdCardDirectory.getAbsolutePath());
} catch (IOException e) {
e.printStackTrace();
}
return file;
}
アクティビティにはmView
の代わりにView v1 = getWindow().getDecorView().getRootView();
を使うことができます。
Taralocaの答えを拡張するだけです。それを機能させるには次の行を追加しなければなりません。 画像名を静的にしました。動的な画像名が必要な場合は、必ずtaralocaのタイムスタンプ変数を使用してください。
// Storage Permissions
private static final int REQUEST_EXTERNAL_STORAGE = 1;
private static String[] PERMISSIONS_STORAGE = {
Manifest.permission.READ_EXTERNAL_STORAGE,
Manifest.permission.WRITE_EXTERNAL_STORAGE
};
private void verifyStoragePermissions() {
// Check if we have write permission
int permission = ActivityCompat.checkSelfPermission(this, Manifest.permission.WRITE_EXTERNAL_STORAGE);
if (permission != PackageManager.PERMISSION_GRANTED) {
// We don't have permission so Prompt the user
ActivityCompat.requestPermissions(this, PERMISSIONS_STORAGE, REQUEST_EXTERNAL_STORAGE);
}else{
takeScreenshot();
}
}
@Override
public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
super.onRequestPermissionsResult(requestCode, permissions, grantResults);
if (grantResults[0] == PackageManager.PERMISSION_GRANTED) {
if (requestCode == REQUEST_EXTERNAL_STORAGE) {
takeScreenshot();
}
}
}
そして、AndroidManifest.xmlファイルでは、以下のエントリは必須です。
<uses-permission Android:name="Android.permission.READ_EXTERNAL_STORAGE" /> <uses-permission Android:name="Android.permission.WRITE_EXTERNAL_STORAGE" />
スクリーンショットのキャプチャとともに、トーンも再生したい場合は、次のコードを使用できます。
MediaPlayer _shootMP = null;
AudioManager manager = (AudioManager)
getActivity().getSystemService(Context.AUDIO_SERVICE);
manager.setStreamVolume(AudioManager.STREAM_NOTIFICATION,
manager.getStreamMaxVolume(AudioManager.STREAM_MUSIC), 0);
if (_shootMP == null)
_shootMP = MediaPlayer
.create(getActivity(),
Uri.parse("file:///system/media/audio/ui/camera_click.ogg"));
if (_shootMP != null) {
try {
_shootMP.start();
_shootMP.setOnCompletionListener(new OnCompletionListener() {
@Override
public void onCompletion(MediaPlayer arg0) {
// release the media
_shootMP.stop();
_shootMP.reset();
_shootMP.release();
_shootMP = null;
}
});
} catch (IllegalStateException e) {
Log.w(TAG, "Exception takeScreenShot" + e.getMessage());
}
}
パラメータviewはルートレイアウトオブジェクトです。
public static Bitmap screenShot(View view) {
Bitmap bitmap = null;
if (view.getWidth() > 0 && view.getHeight() > 0) {
bitmap = Bitmap.createBitmap(view.getWidth(),
view.getHeight(), Bitmap.Config.ARGB_8888);
Canvas canvas = new Canvas(bitmap);
view.draw(canvas);
}
return bitmap;
}
この質問に対する回答のほとんどは、Canvas
描画メソッドまたは描画キャッシュメソッドを使用しています。ただし、 View.setDrawingCache()
メソッドはAPI 28 で非推奨です。現在スクリーンショットを作成するために推奨されるAPIは、API 24から利用可能な PixelCopy
クラスです(ただし、Window
パラメータを受け入れるメソッドは、API 26 == Android 8.0 Oreoから利用可能です)。これはBitmap
を取得するためのサンプルKotlinコードです:
@RequiresApi(Build.VERSION_CODES.O)
fun saveScreenshot(view: View) {
val window = (view.context as Activity).window
if (window != null) {
val bitmap = Bitmap.createBitmap(view.width, view.height, Bitmap.Config.ARGB_8888)
val locationOfViewInWindow = IntArray(2)
view.getLocationInWindow(locationOfViewInWindow)
try {
PixelCopy.request(window, Rect(locationOfViewInWindow[0], locationOfViewInWindow[1], locationOfViewInWindow[0] + view.width, locationOfViewInWindow[1] + view.height), bitmap, { copyResult ->
if (copyResult == PixelCopy.SUCCESS) {
saveBitmap(bitmap)
}
// possible to handle other result codes ...
}, Handler())
} catch (e: IllegalArgumentException) {
// PixelCopy may throw IllegalArgumentException, make sure to handle it
}
}
}
システムアプリケーション専用です。
Process process;
process = Runtime.getRuntime().exec("screencap -p " + outputPath);
process.waitFor();
注:システムアプリケーションは、このコマンドを実行するために "su"を実行する必要はありません。
全ページスクロールのスクリーンショットの場合
フルスクリーンショット(スクロールビューなどを含む)をキャプチャしたい場合は、このライブラリをチェックしてください。
GradelをインポートしてBigScreenshotのオブジェクトを作成するだけです。
BigScreenshot longScreenshot = new BigScreenshot(this, x, y);
スクリーンビューグループを自動的にスクロールしながら、スクリーンショットのビットマップを撮影したコールバックが受信され、最後に一緒に組み立てられます。
@Override public void getScreenshot(Bitmap bitmap) {}
ギャラリーに保存することができますか、またはそれらの後に使用が必要な場合は何でも
Androidでビューのスクリーンショットを撮ります。
public static Bitmap getViewBitmap(View v) {
v.clearFocus();
v.setPressed(false);
boolean willNotCache = v.willNotCacheDrawing();
v.setWillNotCacheDrawing(false);
int color = v.getDrawingCacheBackgroundColor();
v.setDrawingCacheBackgroundColor(0);
if (color != 0) {
v.destroyDrawingCache();
}
v.buildDrawingCache();
Bitmap cacheBitmap = v.getDrawingCache();
if (cacheBitmap == null) {
return null;
}
Bitmap bitmap = Bitmap.createBitmap(cacheBitmap);
v.destroyDrawingCache();
v.setWillNotCacheDrawing(willNotCache);
v.setDrawingCacheBackgroundColor(color);
return bitmap;
}