Android'de programlı olarak ekran görüntüsü nasıl alınır?


495

Herhangi bir program tarafından değil, koddan seçilen bir telefon ekranı alanının ekran görüntüsünü nasıl alabilirim?


4
Emülatörden değil. Programımın bir bölümünün ekran görüntüsünü yapmam ve aynı programda onunla ilgili bir şey yapmam gerekiyor.
korovaisdead


Yanıtlar:


448

Ekran görüntümün bir SD kartta saklanmasına ve daha sonra ihtiyaçlarınız ne olursa olsun kullanılmasına izin veren kod:

İlk olarak, dosyayı kaydetmek için uygun bir izin eklemeniz gerekir:

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

Ve bu kod (bir Faaliyette çalışıyor):

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

Ve son oluşturulan görüntüyü şu şekilde açabilirsiniz:

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

Bunu parça görünümünde kullanmak istiyorsanız şunu kullanın:

View v1 = getActivity().getWindow().getDecorView().getRootView();

onun yerine

View v1 = getWindow().getDecorView().getRootView();

on takeScreenshot () işlevi

Not :

Diyalog pencereniz bir yüzey görünümü içeriyorsa bu çözüm çalışmaz. Ayrıntılar için lütfen aşağıdaki sorunun cevabını kontrol edin:

Android Ekran Görünümü Yüzey Görünümü Siyah Ekranı Gösterir


23
Merhaba, mCurrentUrlMask nedir açıklayabilir misiniz? Bu kodu denedim ama her zaman bana Bitmap.createBitmap (v1.getDrawingCache ()) NullPointerException veriyor, kimse ne yaptığımı söyleyebilir miyim? Herhangi bir yardım takdir. Teşekkürler.
Mitesh Sardhara

4
@MiteshSardhara , Android API'sında yönteme sahip benzersiz bir sınıf olduğu için mCurrentUrlMaskbir olmalıdır . Muhtemelen kullanıcı arayüzünde bir görüştür. ViewgetRootView()
gipi

6
Bana ne olduğunu söyleyebilir misin, mCurrentUrlMask?
Jayeshkumar Sojitra

37
View v1 = mCurrentUrlMask.getRootView();Ben ısrar kullandı View v1 = getWindow().getDecorView().getRootView();ve benim için çalışıyor.
enadun

9
Bu cevap, yalnızca uygulamanın ekran görüntüsünü alıyor - soruda sorulduğu gibi "telefon ekranı" değil - veya yanlış bir şey mi yapıyorum?
AlikElzin-kilaka

126

Aşağıdaki ekran görüntüsünü almak istediğiniz en çok ViewGroup dışından geçerek bu yöntemi çağırın:

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
Bu, kabul edilen yanıttan daha temiz bir kod gibi görünüyor. İyi performans gösteriyor mu?
jophde

2
Bir süredir birkaç farklı uygulamada kullandım ve herhangi bir sorun yaşamadım.
JustinMorris

3
Uygulamanızın arka planda olduğu telefonun ekran görüntüsünü almak istiyorsanız, ne olarak view
geçiyorsunuz

2
getWindow().getDecorView().getRootView()Görünüm olarak geçmek , ekranın değil yalnızca uygulamanın ekran görüntüsünün alınmasıyla sonuçlanır.
AlikElzin-kilaka

Bu cevap, yalnızca uygulamanın ekran görüntüsünü alıyor - soruda sorulduğu gibi "telefon ekranı" değil - veya yanlış bir şey mi yapıyorum?
AlikElzin-kilaka

42

Not: yalnızca köklü telefon için çalışır

Programlı olarak, adb shell /system/bin/screencap -p /sdcard/img.pngaşağıdaki gibi çalıştırabilirsiniz

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

Daha sonra okumak img.pngolarak Bitmapve istediğiniz gibi kullanabilirsiniz.


Kök erişimine ihtiyaç var mı?
zoom

3
Evet, root erişimine ihtiyacınız var. Lütfen başlıktaki Notu kontrol edin
Viswanath Lekshmanan

Merhaba, Bir tane var System.err : java.io.IOException: Error running exec(). Command: [su] Working Directory: null Environment: null , cihazım android 5.0
Eddy

@Eddy Cihazınıza bağlı
Demian

Çıktıyı dosyaya kaydetmeden ve tekrar okumadan doğrudan çıktı almanın bir yolu var mı? stackoverflow.com/questions/43914035
Yazan W Yusuf

35

EDIT: downvotes ile merhamet var. Soruyu cevapladığım 2010 yılında doğruydu.

Ekran görüntülerine izin veren tüm programlar yalnızca köklü telefonlarda çalışır.


Bu günlerde Tegra tabanlı yonga seti ile Android'lerde mümkün görünüyor
GDR

4.0.3 - o zaman muhtemelen bu yeni okul tegra tabletlerinden biri
GDR

Cihazların ekran görüntülerini yakalamak için bir stok uygulaması olduğunda AFAIK, çerçeve tamponunu (ekran piksellerini içeren bir tampon) yakalamasına izin veren özel imza ayrıcalıklarına sahip bir uygulamadır. Bu nedenle, ROM'unuzda böyle bir uygulama varsa, root olmanız gerekmeyecektir, ancak yalnızca bu uygulama sizin değil, yakalayabilir.
Rui Marques

2
Kesin olarak, kök ADB'nin "kabuk" kullanıcı hesabıyla birlikte, her zaman amaçlanan kullanım durumu olduğu için bunu yapma izni vardı. Tarihsel olarak mevcut olmayan (zaman zaman yapılan hatalar hariç) uygulama kullanıcı kimliklerinin bunu yapmasının bir yoluydu .
Chris Stratton

26

Bu yöntem için kök izni veya büyük kodlama gerekmez.


Aşağıdaki komutu kullanarak adb kabuğunda ekran görüntüsü alabilirsiniz.

input keyevent 120

Bu komut herhangi bir root izni gerektirmez, bu yüzden aynı zamanda android uygulamasının java kodundan da yapabilirsiniz.

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

Android'deki önemli kod hakkında daha fazla bilgi için bkz. Http://developer.android.com/reference/android/view/KeyEvent.html

Burada kullandık. KEYCODE_SYSRQ değeri 120'dir ve Sistem İsteği / Ekranı Yazdır tuşu için kullanılır.


CJBS'nin dediği gibi, çıktı resmi / sdcard / Pictures / Screenshots


Çıktı resmi buraya kaydedilir:/sdcard/Pictures/Screenshots
CJBS

root izni gerektiriyor mu ??
Taranmeet Singh

1
hatmi üzerinde çalışacak mı? ya da hizmet arka planda çalışır @JeegarPatel
karanatwal.github.io

2
programlı olarak çalışmadı, ama kabuktan çalışıyor. Nuga ile denedim.
mehmet6parmak

1
su -c "input keyevent 120"tamam!!
ipcjs

17

Mualig cevabı çok iyi, ama Ewoks'un açıkladığı aynı problemi yaşadım, arka planı alamıyorum. Bu yüzden bazen yeterince iyi ve bazen siyah arka plan üzerinde siyah tema alıyorum (temaya bağlı olarak).

Bu çözüm ağırlıklı olarak Mualig koduna ve Robotium'da bulduğum koda dayanıyor. Doğrudan draw yöntemini çağırarak çizim önbellek kullanımını atıyorum. Bundan önce, ilk önce çizmek için arka planı mevcut etkinlikten çekilebilir hale getirmeye çalışacağım.

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

Ben aktivite ile android: cacheColorHint = "# 00000000" ile bir listview var ve ben bu kodu ekran görüntüsü için kullanın, hala siyah bir arka plan var, çünkü tema almak arka plan siyah, nasıl başa çıkabilirim liste görünümü?
Wangchao0721

Etkinlik etkinliği = Eroor undefined yöntemi veren getCurrentActivity.
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();
    }
}

Manifest'e izin ekle

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

Marshmallow veya üstü sürümleri desteklemek için lütfen onCreate yöntemindeki etkinliğe aşağıdaki kodu ekleyin

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

Gerektirir: <kullanımları-izni android: name = "android.permission.WRITE_EXTERNAL_STORAGE" />
AndroidGuy

4
Bu cevap, yalnızca uygulamanın ekran görüntüsünü alıyor - soruda sorulduğu gibi "telefon ekranı" değil - yoksa yanlış bir şey mi yapıyorum?
AlikElzin-kilaka

Bir liste görünümü öğesinin ekran görüntüsüne ihtiyacım olursa ne olacak?
Anshul Tyagi

herhangi bir fikir nasıl yapabilirim adaptör yakalamak istiyorum?
Derin Dave

16

Referans olarak, ekranı yakalamanın bir yolu (sadece uygulama etkinliğinizi değil), çerçeve arabelleğini (device / dev / graphics / fb0) yakalamaktır . Bunu yapmak için ya kök ayrıcalıklarına sahip olmanız ya da uygulamanızın imza izinlerine sahip bir uygulama olması gerekir ("Sistemin yalnızca istekte bulunan uygulama izni bildiren uygulama ile aynı sertifika ile imzalanmışsa verdiği izin") - kendi ROM'unuzu derlemediğiniz sürece çok olası değildir.

Test ettiğim birkaç cihazdan her çerçeve tamponu yakalaması tam olarak bir ekran görüntüsü içeriyordu . İnsanlar daha fazlasını içerdiğini bildirdiler, sanırım çerçeve / ekran boyutuna bağlı.

Framebuffer'ı sürekli okumaya çalıştım, ancak okunan sabit bir bayt için geri dönüyor gibi görünüyor. Benim durumumda (3 410432) bayt, bu da 854 * 480 RGBA (3 279 360 bayt) ekran çerçevesini saklamak için yeterli. Evet, ikili olarak, fb0'dan çıkan çerçeve aygıtımda RGBA . Bu büyük olasılıkla cihazdan cihaza bağlı olacaktır. Bu kod çözmeniz için önemli olacaktır =)

Cihazımda / dev / graphics / fb0 izinleri yalnızca kök ve grup grafiklerinden kullanıcılar fb0'ı okuyabilir.

graphics kısıtlı bir gruptur, bu nedenle fb0'a sadece root komutuyla su komutunu kullanarak erişebilirsiniz.

Android uygulamalarının kullanıcı kimliği (uid) = uygulama _ ## ve grup kimliği (guid) = uygulama _ ## vardır .

adb shell , bir uygulamadan çok daha fazla izni olan uid = shell ve guid = shell'e sahiptir. Bu izinleri gerçekten /system/permissions/platform.xml adresinden kontrol edebilirsiniz.

Bu, kök olmadan adb kabuğundaki fb0'ı okuyabileceğiniz, ancak kök olmadan uygulamada okuyamayacağınız anlamına gelir.

Ayrıca, AndroidManifest.xml dosyasına READ_FRAME_BUFFER ve / veya ACCESS_SURFACE_FLINGER izinleri vermek normal bir uygulama için hiçbir şey yapmaz, çünkü bunlar yalnızca ' imza ' uygulamaları için çalışır.

Daha fazla ayrıntı için bu kapalı ipliği de kontrol edin .


2
Bu, bazı telefonlarda çalışır (çalıştı?), Ancak GPU tabanlı telefonların uygulama işlemcisine doğrusal bir çerçeve tamponu sağlamadığını unutmayın.
Chris Stratton

15

Benim çözümüm:

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

ve

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

Görüntüler harici depolama klasörüne kaydedilir.


1
Sonunda bir blokta FileOutputStream kapatmalısınız. Şimdi bir istisna ile karşılaşırsanız akış kapatılmaz.
Wotuu

Ne viewgeçiyorsun ImageUtils.loadBitmapFromView(this, view)?
AlikElzin-kilaka

1
neden v.layout (0, 0, v.getMeasuredWidth (), v.getMeasuredHeight ()) kullanıyorsunuz; ? Bu görüşü değiştirmez mi (v)?
serj

11

Aşağıdaki kitaplığı deneyebilirsiniz: http://code.google.com/p/android-screenshot-library/ Android Ekran Görüntüsü Kitaplığı (ASL), kök erişim ayrıcalıklarına sahip olmanıza gerek kalmadan Android cihazlardan ekran görüntülerini programlı olarak yakalamanızı sağlar. Bunun yerine, ASL, cihaz önyüklemesi başına Android Hata Ayıklama Köprüsü (ADB) aracılığıyla başlatılan arka planda çalışan yerel bir hizmet kullanır.


1
Bunu denedim.Ancak sadece çalışan uygulamanın ekran görüntüsünü alır. Ana ekranın ekran görüntüsünü almak istiyorsanız onun yardımcı olamaz. bu kodu içeren ana ekranın ekran görüntüsünü nasıl alabilirim?
Jana

1
@ Janardhanan.S: Sorunun istediği bu. Ayrı bir soru sormak yerine yeni bir cevapla ayrıntıya girebilir misiniz?
trgraglia

3
Benimle Aynı Sorun .. "Yerel Hizmet Çalışmıyor !!"
Yogesh Maheshwari

1
Benimle aynı "Yerel Hizmet Çalışmıyor !!" .... yardım metnini buraya ekleyen var mı?
Pankaj Kumar

1
burada aynı! "Yerel Hizmet Çalışmıyor !!" ve son sürümleri 1.2'de örneğin Socket gibi API LEVEL 19 sınıflarını kullanıyorlar.
user347187

10

Yukarıdaki @JustinMorris ve burada @NiravDangi'nin cevabına dayanarak https://stackoverflow.com/a/8504958/2232148 bir görünümün arka planını ve ön planını almalı ve bunları böyle bir araya getirmeliyiz:

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 parametresi, tipik olarak Bitmap.Config.RGB_565veya olmak üzere bir Bitmap.Config sabiti alır Bitmap.Config.ARGB_8888.


arka plan null olması durumunda beyaz renk ile tuval çizimi benim için hile yaptı. Teşekkürler Oliver
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();
}

}

İZİN EKLE

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

Bu cevap, yalnızca uygulamanın ekran görüntüsünü alıyor - soruda sorulduğu gibi "telefon ekranı" değil - yoksa yanlış bir şey mi yapıyorum?
AlikElzin-kilaka

7

Böyle bir şey yapmaya çalışabilirsiniz,

Bir mizanpaj veya görünümden bir bitmap önbelleği alma Öncelikle setDrawingCacheEnabledbir mizanpaja (doğrusal bir düzene veya göreceli düzeneğe veya bir görünüme) ihtiyacınız var.

sonra

Bitmap bm = layout.getDrawingCache()

Sonra bitmap ile ne istersen yaparsın. Ya bir görüntü dosyasına dönüştürün ya da bitmap'in uri'sini başka bir yere gönderin.


1
Uygulamanız bir bitmap'e yazıyorsanız, bu en iyi yöntemdir. Ayrıca, önbellek almadan önce gecikme olan yöntemlere dikkat edin ... liste görünümleri için Bildir ... () gibi.
trgraglia

Sadece bu degil. Düzen, önce ekranda görüntülenmelidir. Daha sonra elde edeceğiniz "önbellek". Görünümü gizlemeye ve arka planda (teoride) ekran görüntüleri almaya çalıştım, ancak işe yaramadı.
Kevin Tan

Diğer çözümlere göre çok daha verimli
sivi

6

Bir GLSurfaceView yakalamak isteyenler için getDrawingCache veya kanvasa çizim yöntemi çalışmaz.

Çerçeve oluşturulduktan sonra OpenGL çerçeve arabelleğinin içeriğini okumalısınız. Burada iyi bir cevap var


6

Bir ekran görüntüsünü alan Viewve size bir Bitmap nesnesi veren veya doğrudan istediğiniz herhangi bir yola kaydeden basit bir kütüphane oluşturdum

https://github.com/abdallahalaraby/Blink


Köklü telefon gerektiriyor mu?
Nilesh Agrawal

1
Köklenme gerekmez :)
Abdallah Alaraby

Kullanımda u Screenshot.takeScreenshot(view, mPath); imageView.setImageBitmap(Screenshot.getBitmapScreenshot(view, mPath)); Mevcut etkinliğin görünümü nasıl elde edilir bahsetti . Ben xml kimliğini kullanmak istemiyorum.
Nilesh Agrawal

kullanın takeScreenshotForScreen().
Abdallah Alaraby

6

Kısa yol

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

5

Taraloca'nın cevabını uzatıyorum. Çalışması için aşağıdaki satırları eklemelisiniz. Görüntü adını statik yaptım. Lütfen dinamik görüntü adına ihtiyacınız olduğunda taraloca'nın zaman damgası değişkenini kullandığınızdan emin olun.

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

Ve AndroidManifest.xml dosyasında aşağıdaki girişler gereklidir:

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

4

Ekran görüntüsünü buradan almak istiyorsanız, fragment aşağıdakileri uygulayın:

  1. Geçersiz kıl 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. Ekran görüntüsü almak için mantık:

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

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

Aktivite için sadece kullanabilirsiniz View v1 = getWindow().getDecorView().getRootView();yerinemView


3

Bu sorunun yanıtlarının çoğu, Canvasçizim yöntemini veya çizim önbellek yöntemini kullanır. Ancak, View.setDrawingCache()yöntem API 28'de kullanımdan kaldırılmıştır . Şu anda ekran görüntüsü almak için önerilen API PixelCopy, API 24'te bulunan sınıftır (ancak Windowparametreyi kabul eden yöntemler API 26 == Android 8.0 Oreo'da mevcuttur). İşte a almak için bir Kotlin kodu 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 çözümü üzerindeki PixelCopy ile ilgili sorun, yalnızca görünür piksel yakalaması gibi görünüyor. gerisi benim için siyah. Dolayısıyla kaydırılabilir ve kısmen çerçevenin dışında olan şeyleri paylaşmak mümkün değildir. Bunun için bir çözümünüz var mı?
Henning

Haklısın. Benzer şekilde ekran görüntüsü almak istediğim Görünüm'ün üzerinde başka bir Görünüm gösterilirse (örneğin çekmece açıldığında) soruna neden olabilir. Bu durumlarda sadece eski Canvas yöntemini kullanıyorum :(
Miloš Černilovský

1
PixelCopy kullanarak çalışan herhangi bir uygulamada ekran görüntüsü almak mümkün mü?
Amir Rezaei

2

Sadece sistem uygulamaları için!

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

Not: Sistem uygulamalarının bu komutu yürütmek için "su" çalıştırması gerekmez.


2

Parametre görünümü kök düzen nesnesidir.

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

Tam Sayfa Kaydırma için Ekran Görüntüsü

Tam Görünüm ekran görüntüsü (bir kaydırma görüntüsü vb.) Yakalamak istiyorsanız, bu kütüphanede bir kontrol yapın

https://github.com/peter1492/LongScreenshot

Tek yapmanız gereken Gradel'i içe aktarmak ve bir BigScreenshot nesnesi oluşturmak

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

Ekran görünümü grubunda otomatik olarak kaydırılırken ve sonunda bir araya getirilirken alınan Ekran Görüntülerinin bitmap'i ile bir geri çağrı alınacaktır.

@Override public void getScreenshot(Bitmap bitmap) {}

Hangi galeriye kaydedilebilir veya ne olursa olsun kullanımı gerekli onların sonra


1

Android'de bir görünümün ekran görüntüsünü alın.

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 veya LinearLayout vb. gibi bir görünüm veya düzen yakalamak istiyorsanız sadece kodu kullanın:

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

şimdi bu bitmap'i cihaz depolama alanına şu şekilde kaydedebilirsiniz:

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();}
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.