프로그래밍 방식으로 Android에서 스크린 샷을 찍는 방법은 무엇입니까?


495

프로그램에서가 아니라 코드에서 선택한 전화 화면 영역의 스크린 샷을 어떻게 찍을 수 있습니까?


4
에뮬레이터가 아닙니다. 내 프로그램의 일부 스크린 샷을 만들고 동일한 프로그램에서 smth로 수행해야합니다.
korovaisdead


답변:


448

다음은 내 스크린 샷을 SD 카드에 저장하고 나중에 필요에 따라 사용할 수있는 코드입니다.

먼저 파일을 저장할 수있는 적절한 권한을 추가해야합니다.

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

그리고 이것은 (활동에서 실행되는) 코드입니다.

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();

takeScreenshot () 함수

참고 :

대화 상자에 표면 뷰가 포함되어 있으면이 솔루션이 작동하지 않습니다. 자세한 내용은 다음 질문에 대한 답변을 확인하십시오.

Surface View의 Android 스크린 샷에 검은 색 화면 표시


23
안녕하세요, mCurrentUrlMask 란 무엇입니까? 이 코드를 시도했지만 항상 Bitmap.createBitmap (v1.getDrawingCache ())에서 NullPointerException이 발생합니다. 누군가 내가 뭘 잘못했는지 말할 수 있습니까? 도움을 주시면 감사하겠습니다. 감사.
Mitesh Sardhara

4
@MiteshSardhara mCurrentUrlMaskViewAndroid API에서 getRootView()메소드 가있는 고유 한 클래스 여야합니다 . 아마도 UI의 관점 일 것입니다.
gipi

6
mCurrentUrlMask 란 무엇입니까?
Jayeshkumar Sojitra

37
의 Insted View v1 = mCurrentUrlMask.getRootView();내가 사용하고 View v1 = getWindow().getDecorView().getRootView();그것은 나를 위해 작동합니다.
enadun

9
이 답변은 질문에 표시된 "전화 화면"이 아닌 응용 프로그램의 스크린 샷을 찍거나 잘못된 일을하고 있습니까?
AlikElzin-kilaka

126

이 메소드를 호출하여 스크린 샷을 원하는 가장 많은 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;
}

9
이것은 허용 된 답변보다 깨끗한 코드 인 것 같습니다. 성능도 좋아?
jophde

2
몇 가지 다른 앱에서 한동안 사용했지만 아무런 문제가 없었습니다.
JustinMorris

3
앱이 백그라운드에있는 전화의 스크린 샷을 얻고 싶은 경우에, 당신은으로 무엇을 전달하지 view`?
AlikElzin-kilaka

2
getWindow().getDecorView().getRootView()보기로 전달 하면 화면이 아닌 앱의 스크린 샷이 생성됩니다.
AlikElzin-kilaka

이 답변은 질문에 표시된 "전화 화면"이 아닌 응용 프로그램의 스크린 샷을 찍거나 잘못된 일을하고 있습니까?
AlikElzin-kilaka

42

참고 : 루팅 된 전화에 대해서만 작동

프로그래밍 방식 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.pngBitmap하고 당신의 소원으로 사용합니다.


루트 액세스가 필요합니까?
확대

3
예, 루트 액세스 권한이 필요합니다. 제목에서 메모를 확인하십시오
Viswanath Lekshmanan

안녕, 나는 System.err : java.io.IOException: Error running exec(). Command: [su] Working Directory: null Environment: null 내 장치는 안드로이드 5.0입니다
Eddy

@Eddy 기기에 따라 다릅니다.
Demian

결과를 파일로 저장 한 다음 다시 읽지 않고 출력을 직접 읽는 방법이 있습니까? stackoverflow.com/questions/43914035
Yazan W Yusuf

35

편집 : downvotes에 자비를 베푸십시오. 내가 질문에 대답했을 때 2010 년에 사실이었습니다.

스크린 샷을 허용하는 모든 프로그램은 루팅 된 휴대 전화에서만 작동합니다.


요즘 Tegra 기반 칩셋을 사용하는 Android에서 가능할 것으로 보입니다.
GDR

4.0.3-그렇다면 아마도이 새로운 테그 라 태블릿 중 하나 일 것입니다
GDR

AFAIK 기기에 스크린 샷을 캡처 할 스톡 앱이있는 경우 프레임 버퍼 (스크린 픽셀이 포함 된 버퍼)를 캡처 할 수있는 특별한 서명 권한이있는 앱입니다. 따라서 ROM에 그러한 앱이있는 경우 루팅 할 필요는 없지만 해당 앱만 캡처 할 수 있지만 캡처 할 수는 없습니다.
Rui Marques

2
엄밀히 말하면 루트 ADB의 "쉘"사용자 계정과 함께 의도 된 사용 사례이므로 항상이 작업을 수행 할 권한이 있습니다. 역사적으로 사용할 수 없었던 것은 (실수로 실수로 빌드 한 경우는 제외하고) 응용 프로그램 사용자 ID의 방법이었습니다 .
Chris Stratton

26

이 방법 에는 루트 권한 이나 큰 코딩 이 필요 하지 않습니다 .


아래 명령을 사용하여 adb shell에서 스크린 샷을 찍을 수 있습니다.

input keyevent 120

이 명령은 루트 권한이 필요하지 않으므로 Android 애플리케이션의 Java 코드에서도 수행 할 수 있습니다.

Process process;
process = Runtime.getRuntime().exec("input keyevent 120");

안드로이드의 주요 이벤트 코드에 대한 자세한 내용은 http://developer.android.com/reference/android/view/KeyEvent.html을 참조 하십시오.

여기에 우리가 사용했습니다. KEYCODE_SYSRQ 값은 120이며 시스템 요청 / 인쇄 화면 키에 사용됩니다.


CJBS가 말했듯이 출력 사진은 / sdcard / Pictures / Screenshots에 저장됩니다


출력 사진이 여기에 저장됩니다 :/sdcard/Pictures/Screenshots
CJBS

루트 권한이 필요합니까 ??
Taranmeet Singh 5

1
마시멜로에서 작동합니까? 아니면 서비스 배경에서 작동합니까 @JeegarPatel
karanatwal.github.io

2
프로그래밍 방식으로 작동하지 않지만 쉘에서 작동합니다. 누가와 함께 시도했다.
mehmet6parmak

1
su -c "input keyevent 120"괜찮아 !!
ipcjs

17

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();
}

내 활동에 android : cacheColorHint = "# 00000000"이있는 목록보기가 있고이 코드를 스크린 샷에 사용합니다. 테마에서 가져온 배경이 검은 색이라는 것을 알았으므로 여전히 검은 색 배경을 얻었습니다. 목록보기?
Wangchao0721

활동 활동 = getCurrentActivity는 Eroor에 정의되지 않은 메소드를 제공합니다.
Shabbir Dhangot

17
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"/>

Marshmallow 이상 버전을 지원 하려면 onCreate 메소드 활동에 아래 코드를 추가하십시오.

ActivityCompat.requestPermissions(this,new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE},00);

요구 사항 : <uses-permission android : name = "android.permission.WRITE_EXTERNAL_STORAGE"/>
AndroidGuy

4
이 답변은 질문에 표시된 "전화 화면"이 아닌 응용 프로그램의 스크린 샷을 찍습니다. 또는 잘못된 일이 있습니까?
AlikElzin-kilaka

listview 항목의 스크린 샷이 필요한 경우 어떻게해야합니까?
Anshul Tyagi

어댑터에서 캡처하고 싶습니다. 어떻게 할 수 있습니까?
Deep Dave

16

참고로 앱 활동이 아닌 화면을 캡처하는 한 가지 방법은 프레임 버퍼 (장치 / dev / graphics / fb0) 를 캡처하는 것 입니다. 이렇게하려면 루트 권한이 있거나 앱에 서명 권한 이있는 앱이어야합니다 ( "요청한 응용 프로그램이 권한을 선언 한 응용 프로그램과 동일한 인증서로 서명 한 경우에만 시스템이 부여하는 권한")- 자신의 ROM을 컴파일하지 않는 한 매우 가능성이 낮습니다.

내가 테스트 한 몇 가지 장치의 각 프레임 버퍼 캡처에는 정확히 하나의 스크린 샷이 포함되어 있습니다. 사람들은 더 많이 포함한다고보고했습니다. 프레임 / 디스플레이 크기에 달려 있다고 생각합니다.

프레임 버퍼를 계속 읽으려고했지만 고정 된 양의 바이트를 읽은 것으로 반환됩니다. 제 경우에는 (3 410 432) 바이트로 854 * 480 RGBA (3 279360 바이트)의 디스플레이 프레임을 저장하기에 충분합니다. 예, fb0에서 출력되는 이진 단위의 프레임 은 내 장치의 RGBA 입니다. 이것은 대부분 장치마다 다릅니다. 이것을 해독하는 것이 중요합니다 =)

내 장치에서 / dev / graphics / fb0 권한은 그룹 그래픽의 루트 및 사용자 만 fb0을 읽을 수 있도록합니다.

제도법 는 제한된 그룹이므로 su 명령을 사용하여 루팅 된 전화로만 fb0에 액세스 할 수 있습니다.

Android 앱의 사용자 ID (uid) = app _ ## 그룹 ID (guid) = app _ ## 입니다.

adb 쉘 에는 uid = shell이 있으며 guid = shell이 있으며 이는 앱보다 훨씬 많은 권한을 가지고 있습니다. /system/permissions/platform.xml에서 실제로 해당 권한을 확인할 수 있습니다.

이것은 루트없이 adb 쉘에서 fb0을 읽을 수 있지만 루트가없는 앱에서는 읽을 수 없다는 것을 의미합니다.

또한 AndroidManifest.xml에 대한 READ_FRAME_BUFFER 및 / 또는 ACCESS_SURFACE_FLINGER 권한을 부여하면 일반 앱에는 아무런 영향을 미치지 않습니다. 서명 '앱 .

자세한 내용은 이 스레드 를 확인하십시오.


2
일부 전화에서는 작동하지만 작동하지만 GPU 기반 전화는 반드시 응용 프로그램 프로세서에 선형 프레임 버퍼를 제공하지는 않습니다.
Chris Stratton

15

내 해결책은 다음과 같습니다.

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();
    }
}

이미지는 외부 저장 폴더에 저장됩니다.


1
finally 블록에서 FileOutputStream을 닫아야합니다. 예외가 발생하면 스트림이 닫히지 않습니다.
Wotuu

view당신은 무엇을 전달하고 ImageUtils.loadBitmapFromView(this, view)있습니까?
AlikElzin-kilaka

1
왜 v.layout (0, 0, v.getMeasuredWidth (), v.getMeasuredHeight ())를 사용합니까? ? 뷰가 바뀌지 않습니까 (v)?
serj

11

다음 라이브러리를 사용해 볼 수 있습니다. http://code.google.com/p/android-screenshot-library/ ASL (Android Screenshot Library)을 사용하면 루트 액세스 권한이 없어도 Android 기기에서 스크린 샷을 프로그래밍 방식으로 캡처 할 수 있습니다. 대신 ASL은 백그라운드에서 실행되는 기본 서비스를 사용하며 장치 부팅마다 한 번씩 Android 디버그 브리지 (ADB)를 통해 시작됩니다.


1
나는 이것을 시도했지만 실행중인 응용 프로그램의 스크린 샷을 찍습니다. 홈 화면의 스크린 샷을 찍고 싶을 때 도움이되지 않습니다. 해당 코드로 홈 화면의 스크린 샷을 만드는 방법은 무엇입니까?
Jana

1
@ Janardhanan. S : 이것이 질문하는 것입니다. 별도의 질문을하는 대신 새로운 답변을 구사할 수 있습니까?
trgraglia

3
저도 같은 문제입니다. "기본 서비스가 실행되지 않습니다 !!"
Yogesh Maheshwari

1
저와 동일하게 "Native Service Not Running !!".... 여기에 도움말 텍스트를 추가 할 수 있습니까?
Pankaj Kumar

1
여기 동일! "기본 서비스가 실행되지 않습니다 !!" 최신 버전 1.2에서는 예를 들어 Socket과 같은 API LEVEL 19 클래스를 사용합니다.
user347187

10

위의 @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합니다.


배경이 null 인 경우 흰색으로 캔버스를 그리는 것은 속임수입니다. 감사합니다 올리버
Shaleen

8
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"/>

이 답변은 질문에 표시된 "전화 화면"이 아닌 응용 프로그램의 스크린 샷을 찍습니다. 또는 잘못된 일이 있습니까?
AlikElzin-kilaka

7

이런 식으로 할 수 있습니다

레이아웃이나 뷰에서 비트 맵 캐시 가져 오기 setDrawingCacheEnabled 레이아웃 (linearlayout 또는 relativelayout 또는 view)으로 이동 합니다

그때

Bitmap bm = layout.getDrawingCache()

그런 다음 비트 맵으로 원하는 것을 수행하십시오. 이미지 파일로 바꾸거나 비트 맵의 ​​URI를 다른 곳으로 보내십시오.


1
비트 맵에 쓰고있는 앱인 경우이 방법이 가장 좋습니다. 또한 캐시를 가져 오기 전에 지연되는 메소드를주의하십시오. 목록보기의 경우 Notify ... ()와 같습니다.
trgraglia

뿐만 아니라. 레이아웃은 먼저 화면에 표시되어야합니다. 결국 "캐시"입니다. 뷰를 숨기고 백그라운드에서 스크린 샷을 찍으려고했지만 이론적으로 작동하지 않았습니다.
케빈 탄

다른 솔루션보다 훨씬 효율적
sivi

6

GLSurfaceView를 캡처하려는 경우 getDrawingCache 또는 캔버스로 그리기 메소드가 작동하지 않습니다.

프레임이 렌더링 된 후 OpenGL 프레임 버퍼의 내용을 읽어야합니다. 여기에 좋은 대답이 있습니다


6

스크린 샷을 가져 와서 View비트 맵 객체를 제공하거나 원하는 경로에 직접 저장 하는 간단한 라이브러리를 만들었습니다.

https://github.com/abdallahalaraby/Blink


루팅 된 전화가 필요합니까?
Nilesh Agrawal

1
응원 필요 없음 :)
Abdallah Alaraby

사용법 Screenshot.takeScreenshot(view, mPath); imageView.setImageBitmap(Screenshot.getBitmapScreenshot(view, mPath)); 에서 현재 활동을 보는 방법을 언급했습니다 . XML의 ID를 사용하고 싶지 않습니다.
Nilesh Agrawal

사용하는 takeScreenshotForScreen()대신.
Abdallah Alaraby

6

짧은 방법은

FrameLayout layDraw = (FrameLayout) findViewById(R.id.layDraw); /*Your root view to be part of screenshot*/
layDraw.buildDrawingCache();
Bitmap bmp = layDraw.getDrawingCache();

5

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" />

4

fragment 다음보다 스크린 샷을 찍으려면 다음을 수행하십시오.

  1. 무시 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;
            }
  2. 스크린 샷 찍기위한 논리 :

     button.setOnClickListener(new View.OnClickListener() {
     @Override
     public void onClick(View v) {
         View view =  mView.findViewById(R.id.scrollView1);
          shareScreenShotM(view, (NestedScrollView) view); 
     }
  3. 방법 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.
        }
  4. 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;
            }
  5. 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;
       }

활동을 위해 View v1 = getWindow().getDecorView().getRootView();대신 대신 사용할 수 있습니다mView


3

이 질문에 대한 대부분의 답변은 Canvas그리기 방법 또는 그리기 캐시 방법을 사용합니다. 그러나이 View.setDrawingCache()메소드는 API 28에서 더 이상 사용되지 않습니다 . 현재 스크린 샷을 만드는 데 권장되는 API PixelCopy는 API 24에서 사용할 수 있는 클래스이지만 Window매개 변수 를 허용하는 메서드 는 API 26 == Android 8.0 Oreo에서 사용할 수 있습니다. 다음은 다음을 검색하기위한 Kotlin 코드 샘플입니다 Bitmap.

@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
        }
    }
}

drawingCache 솔루션의 PixelCopy 문제는 보이는 픽셀 만 캡처하는 것 같습니다. 나머지는 나를 위해 검은 색입니다. 따라서 스크롤 가능하고 부분적으로 벗어난 내용은 공유 할 수 없습니다. 이에 대한 해결책이 있습니까?
Henning

네 말이 맞아 마찬가지로 스크린 샷을 보려는보기 위에 다른보기가 표시되면 (예 : 서랍을 열 때) 문제가 발생할 수 있습니다. 이러한 경우에는 그냥 오래된 캔버스 방법 :( 사용
밀로스 Černilovský

1
PixelCopy를 사용하여 실행중인 앱에서 스크린 샷을 찍을 수 있습니까?
Amir Rezaei 님이

2

시스템 응용 프로그램 전용!

Process process;
process = Runtime.getRuntime().exec("screencap -p " + outputPath);
process.waitFor();

참고 : 시스템 응용 프로그램은이 명령을 실행하기 위해 "su"를 실행할 필요가 없습니다.


2

매개 변수보기는 루트 레이아웃 객체입니다.

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;
                }

2

전체 페이지 스크롤 스크린 샷

전체보기 스크린 샷을 캡처하려면 (스크롤 뷰가 포함되어있는 경우)이 라이브러리를 확인하십시오

https://github.com/peter1492/LongScreenshot

Gradel을 가져 와서 BigScreenshot 오브젝트를 작성하기 만하면됩니다.

BigScreenshot longScreenshot = new BigScreenshot(this, x, y);

스크린 뷰 그룹을 통해 자동으로 스크롤하는 동안 캡쳐 된 스크린 샷의 비트 맵과 함께 콜백이 수신되고 끝에서 함께 조립됩니다.

@Override public void getScreenshot(Bitmap bitmap) {}

갤러리에 저장할 수 있거나 그 이후의 사용법이 필요합니다.


1

안드로이드 뷰의 스크린 샷을 찍습니다.

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;
}

-1

RelativeLayout 또는 LinearLayout 등과 같은 뷰 또는 레이아웃을 캡처하려면 다음 코드를 사용하십시오.

LinearLayout llMain = (LinearLayout) findViewById(R.id.linearlayoutMain);
Bitmap bm = loadBitmapFromView(llMain);

이제 다음을 통해이 비트 맵을 장치 저장소에 저장할 수 있습니다.

FileOutputStream outStream = null;
File f=new File(Environment.getExternalStorageDirectory()+"/Screen Shots/");
f.mkdir();
String extStorageDirectory = f.toString();
File file = new File(extStorageDirectory, "my new screen shot");
pathOfImage = file.getAbsolutePath();
try {
    outStream = new FileOutputStream(file);
    bm.compress(Bitmap.CompressFormat.PNG, 100, outStream);
    Toast.makeText(getApplicationContext(), "Saved at "+f.getAbsolutePath(), Toast.LENGTH_LONG).show();
    addImageGallery(file);
    //mail.setEnabled(true);
    flag=true;
} catch (FileNotFoundException e) {e.printStackTrace();}
try {
    outStream.flush();
    outStream.close();
} catch (IOException e) {e.printStackTrace();}
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.