प्रोग्राम को एंड्रॉइड पर स्क्रीनशॉट कैसे लें?


495

मैं किसी प्रोग्राम द्वारा नहीं बल्कि कोड से फोन-स्क्रीन के चयनित क्षेत्र का स्क्रीनशॉट कैसे ले सकता हूं?


4
एमुलेटर से नहीं। मुझे अपने प्रोग्राम के हिस्से का स्क्रीनशॉट बनाने की आवश्यकता है, और उसी प्रोग्राम में इसके साथ smth करें।
कोरोवाइसडेड

1
एक और अच्छा संदर्भ: stackoverflow.com/a/10296881/439171
इटालो बोरसत्तो

जवाबों:


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 () समारोह

नोट :

यदि आपके संवाद में सतह दृश्य है तो यह समाधान काम नहीं करता है। जानकारी के लिए कृपया निम्नलिखित प्रश्न का उत्तर देखें:

एंड्रॉइड टेक सरफेस ऑफ स्क्रीन सरफेस व्यू ब्लैक स्क्रीन दिखाता है


23
नमस्ते, क्या आप बता सकते हैं कि mCurrentUrlMask क्या है? मैंने इस कोड की कोशिश की है, लेकिन यह मुझे हमेशा Bitmap.createBitmap (v1.getDrawingCache) () पर NullPointerException दे रहा है, क्या कोई बता सकता है कि मैं क्या गलत कर रहा हूं? किसी भी मदद की सराहना की है। धन्यवाद।
मितेश सरधरा 19

4
@MiteshSardhara mCurrentUrlMaskहोना चाहिए Viewक्योंकि एंड्रॉइड एपीआई में अद्वितीय वर्ग है जो getRootView()विधि है। संभवतः UI में एक दृश्य है।
जिप्पी

6
क्या आप मुझे बता सकते हैं कि mCurrentUrlMask क्या है?
जयेशकुमार सोजित्रा

37
के insted View v1 = mCurrentUrlMask.getRootView();मैं का इस्तेमाल किया है View v1 = getWindow().getDecorView().getRootView();और यह मेरे लिए काम करता है।
enadun

9
यह जवाब सिर्फ ऐप का एक स्क्रीनशॉट लेता है - न कि "फोन स्क्रीन" जैसा कि सवाल में पूछा गया है - या क्या मैं कुछ गलत कर रहा हूं।
एलिकएल्ज़िन-किलाका

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
मैंने इसे कुछ अलग ऐप में थोड़ी देर के लिए इस्तेमाल किया है और इसमें कोई समस्या नहीं है।
जस्टिन मैरिसिस

3
यदि आप फोन का एक स्क्रीनशॉट प्राप्त करना चाहते हैं, जहां आपका ऐप पृष्ठभूमि में है, तो आप क्या करते हैं view? `
AlikElzin-kilaka

2
पासिंग getWindow().getDecorView().getRootView()स्क्रीन नहीं - बस एप्लिकेशन का एक स्क्रीनशॉट लेने में परिणाम देख सकते हैं।
एलिकएल्ज़िन-किलक

यह जवाब सिर्फ ऐप का एक स्क्रीनशॉट लेता है - न कि "फोन स्क्रीन" जैसा कि सवाल में पूछा गया है - या क्या मैं कुछ गलत कर रहा हूं।
एलिकएल्ज़िन-किलाका

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.pngरूप में पढ़ने के लिए Bitmapऔर अपनी इच्छा के रूप में उपयोग करें।


क्या इसे रूट एक्सेस की आवश्यकता है?
ज़ूम करें

3
हाँ आपको रूट एक्सेस की आवश्यकता है। कृपया शीर्ष पर ध्यान दें
विश्वनाथ लीक्षमान

नमस्ते, मुझे एक मिल गया है System.err : java.io.IOException: Error running exec(). Command: [su] Working Directory: null Environment: null , मेरा डिवाइस एंड्रॉइड 5.0 है
एडी

@ ईडी यह आपके डिवाइस पर निर्भर करता है
डेमियन

क्या परिणाम को सीधे फाइल में सहेजे बिना उसे दोबारा पढ़ने का कोई तरीका है? stackoverflow.com/questions/43914035
यज़ान डब्ल्यू यूसुफ

35

EDIT: डाउनवोट्स के साथ दया करें। यह 2010 में सच था जब मैंने सवाल का जवाब दिया था।

सभी प्रोग्राम जो स्क्रीनशॉट को रूट किए गए फोन पर ही काम करते हैं।


ऐसा लगता है कि इन दिनों यह टेग्रा आधारित चिपसेट के साथ एंड्रॉइड पर संभव है
जीडीआर

4.0.3 - तब यह शायद इन नए स्कूलों में से एक टेग्रा टैबलेट है
GDR

AFAIK जब उपकरणों को स्क्रीनशॉट कैप्चर करने के लिए एक स्टॉक ऐप होता है, तो यह विशेष हस्ताक्षर विशेषाधिकारों के साथ एक ऐप है जो इसे फ्रेमबफ़र (स्क्रीन पिक्सल में एक बफर के साथ बफर) को पकड़ने की अनुमति देता है। तो यह सच है, अगर आपके ROM में ऐसा कोई ऐप है, तो आपको रूट करने की जरूरत नहीं होगी, लेकिन केवल वही ऐप आपको कैप्चर कर सकता है, आपका नहीं।
रुई मार्केस

2
रूट एडीबी के "शेल" उपयोगकर्ता खाते के साथ सख्ती से बोलना हमेशा ऐसा करने की अनुमति थी, क्योंकि यह इच्छित उपयोग का मामला था। ऐतिहासिक रूप से उपलब्ध नहीं था (गलती के रूप में सामयिक बिल्ड पर छोड़कर) ऐसा करने के लिए एप्लिकेशन उपयोगकर्ता आईडी का एक तरीका था ।
क्रिस स्ट्रैटन

26

इस पद्धति के लिए कोई रूट अनुमति या कोई बड़ी कोडिंग की आवश्यकता नहीं है।


नीचे दिए गए कमांड का उपयोग करके शेल शेल पर आप स्क्रीन शॉट ले सकते हैं।

input keyevent 120

इस कमांड के लिए किसी रूट अनुमति की आवश्यकता नहीं होती है, इसलिए आप एंड्रॉइड एप्लिकेशन के जावा कोड से भी प्रदर्शन कर सकते हैं।

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

Android देखें में कीवेन्ट कोड के बारे में अधिक जानकारी http://developer.android.com/reference/android/view/KeyEvent.html

यहाँ हमने उपयोग किया है। KEYCODE_SYSRQ इसका मूल्य 120 है और सिस्टम अनुरोध / प्रिंट स्क्रीन कुंजी के लिए उपयोग किया जाता है।


जैसा कि CJBS ने कहा, आउटपुट तस्वीर को / sdcard / Pictures / स्क्रीनशॉट में सहेजा जाएगा


आउटपुट चित्र यहां सहेजा जाएगा:/sdcard/Pictures/Screenshots
CJBS

क्या इसके लिए रूट अनुमति की आवश्यकता है ??
तरनमीत सिंह 5

1
क्या यह मार्शमैलो पर काम करेगा? या यह सेवा पृष्ठभूमि में काम करेगा @JeegarPatel
karanatwal.github.io

2
प्रोग्रामेटिक रूप से काम नहीं किया, लेकिन शेल से काम करता है। नौगट से कोशिश की।
mehmet6parmak

1
su -c "input keyevent 120"ठीक है!!
ipcjs

17

Mualig का उत्तर बहुत अच्छा है, लेकिन मुझे वही समस्या थी जो इवोक का वर्णन करता है, मुझे पृष्ठभूमि नहीं मिल रही है। इसलिए कभी-कभी काफी अच्छा होता है और कभी-कभी मुझे ब्लैक बैकग्राउंड (थीम के आधार पर) पर ब्लैक टेक्स्ट मिलता है।

यह समाधान Mualig कोड और रोबोटियम में मुझे मिले कोड पर आधारित है। मैं ड्रॉ पद्धति से सीधे कॉल करके ड्रॉइंग कैश का उपयोग करना छोड़ रहा हूं। इससे पहले कि मैं वर्तमान गतिविधि से पहले इसे आकर्षित करने के लिए पृष्ठभूमि को आकर्षित करने की कोशिश करूंगा।

// 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" के साथ एक सूची है, और मैं स्क्रीनशॉट के लिए इस कोड का उपयोग करता हूं, मुझे अभी भी एक काली पृष्ठभूमि मिली है, क्योंकि मैंने पाया है कि विषय से प्राप्त होने वाली पृष्ठभूमि काली है, मैं इससे कैसे निपट सकता हूं सूची दृश्य?
वांगचो 077

गतिविधि गतिविधि = getCurrentActivity एरर अपरिभाषित विधि दे रही है।
शब्बीर धनंगोट

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

मार्शमैलो या इसके बाद के संस्करण का समर्थन करने के लिए , कृपया onCreate विधि में नीचे दिए गए कोड को जोड़ें

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

आवश्यकता है: <उपयोग-अनुमति एंड्रॉइड: नाम = "android.permission.WRITE_EXTERNAL_STORAGE" />
AndroidGuy

4
यह जवाब सिर्फ ऐप का स्क्रीनशॉट लेता है - न कि "फोन स्क्रीन" जैसा कि सवाल में पूछा गया है - या क्या मैं कुछ गलत कर रहा हूं?
एलिकएल्ज़िन-किलक

अगर मुझे सूची-बद्ध आइटम के स्क्रीनशॉट की आवश्यकता है तो क्या होगा?
अंशुल त्यागी

मैं एडॉप्टर से किसी भी विचार में कब्जा करना चाहता हूं मैं इसे कैसे कर सकता हूं?
दीप

16

एक संदर्भ के रूप में, एक ही रास्ता स्क्रीन (और न सिर्फ आपकी ऐप्लिकेशन गतिविधि) पर कब्जा करने के कब्जा करने के लिए है फ्रेमबफर (डिवाइस / dev / ग्राफिक्स / fb0)। ऐसा करने के लिए आपके पास या तो रूट विशेषाधिकार होना चाहिए या आपका एप्लिकेशन हस्ताक्षर अनुमतियों वाला ऐप होना चाहिए ("एक अनुमति जो सिस्टम केवल तभी देता है जब अनुरोध करने वाले एप्लिकेशन को उसी सर्टिफिकेट के साथ साइन किया जाता है जो उस एप्लिकेशन को अनुमति देता है") - जो है जब तक आप अपनी रॉम को संकलित नहीं करते हैं, तब तक बहुत संभावना नहीं है।

प्रत्येक फ़्रेमबफ़र कैप्चर, मेरे द्वारा परीक्षण किए गए उपकरणों के एक जोड़े से, बिल्कुल एक स्क्रीनशॉट समाहित । लोगों ने इसे अधिक समाहित करने की सूचना दी है, मुझे लगता है कि यह फ्रेम / प्रदर्शन आकार पर निर्भर करता है।

मैंने फ्रेमबफ़र को लगातार पढ़ने की कोशिश की, लेकिन यह एक निश्चित मात्रा में बाइट्स के लिए वापस आती है। मेरे मामले में (3 410 432) बाइट्स है, जो 854 * 480 RGBA (3 279 360 बाइट्स) के डिस्प्ले फ्रेम को स्टोर करने के लिए पर्याप्त है। हां, फ्रेम, बाइनरी में, fb0 से आउटपुट मेरे डिवाइस में RGBA है। यह ज्यादातर डिवाइस से डिवाइस पर निर्भर करेगा। आपके लिए इसे डिकोड करना महत्वपूर्ण होगा =)

मेरे डिवाइस / देव / ग्राफिक्स / fb0 में अनुमतियाँ इतनी हैं कि केवल रूट और समूह ग्राफिक्स के उपयोगकर्ता ही fb0 पढ़ सकते हैं।

ग्राफिक्स एक प्रतिबंधित समूह है इसलिए आप शायद केवल कमांड कमांड का उपयोग करके रूट फोन के साथ fb0 का उपयोग करेंगे।

एंड्रॉइड ऐप में यूजर आईडी (uid) = ऐप _ ## और ग्रुप आईडी (गाइड) = ऐप _ ## है

adb शेल में uid = शेल और गाइड = शेल है , जिसमें ऐप की तुलना में बहुत अधिक अनुमतियां हैं। आप वास्तव में / system/permissions/platform.xml पर उन अनुमतियों की जांच कर सकते हैं

इसका मतलब है कि आप बिना किसी रूट के adb शेल में fb0 पढ़ पाएंगे लेकिन आप इसे रूट के बिना ऐप में नहीं पढ़ पाएंगे।

इसके अलावा, READ_FRAME_BUFFER और / या ACCESS_SURFACE_FLINGER को AndroidManifest.xml पर अनुमति देना एक नियमित ऐप के लिए कुछ नहीं करेगा क्योंकि ये केवल ' हस्ताक्षर ' ऐप के लिए काम करेंगे ।

अधिक जानकारी के लिए इस बंद धागे को भी देखें।


2
यह कुछ फोन पर काम करता है (काम करता है?), लेकिन ध्यान दें कि GPU आधारित फोन एप्लीकेशन प्रोसेसर को एक रैखिक फ्रेमबफ़र प्रदान नहीं करते हैं।
क्रिस स्ट्रैटन

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
आपको एक अंतिम ब्लॉक में FileOutputStream को बंद करना चाहिए। यदि आप एक अपवाद का सामना करते हैं तो धारा बंद नहीं होगी।
वॉटु

आप क्या viewकर रहे हैं ImageUtils.loadBitmapFromView(this, view)?
एलिकएल्ज़िन-किलाका

1
आप v.layout (0, 0, v.getMeasuredWidth) (), v.getMeasuredHeight ()) का उपयोग क्यों करते हैं; ? क्या यह दृश्य (v) नहीं बदलता है?
सर्ज २

11

आप निम्न लाइब्रेरी को आज़मा सकते हैं: http://code.google.com/p/android-screenshot-library/ Android स्क्रीनशॉट लाइब्रेरी (ASL) रूट एक्सेस विशेषाधिकारों की आवश्यकता के बिना एंड्रॉइड डिवाइस से स्क्रीनशॉट को प्रोग्राम करने में सक्षम बनाता है। इसके बजाय, ASL बैकग्राउंड में चलने वाली एक देशी सेवा का उपयोग करता है, जो डिवाइस डिबग के अनुसार एक बार Android डिबग ब्रिज (ADB) के माध्यम से शुरू होता है।


1
मैंने यह कोशिश की। लेकिन यह अकेले चलने वाले ऐप का स्क्रीनशॉट लेता है। अगर मैं होमस्क्रीन का स्क्रीनशॉट लेना चाहता हूँ तो इसकी मदद नहीं कर सकता। क्या आप होमस्क्रीन withthat कोड का स्क्रीनशॉट कैसे लेते हैं?
जना

1
@ जनार्दन। यह वही है जो सवाल पूछ रहा है। क्या आप एक अलग प्रश्न पूछने के बजाय एक नए उत्तर के साथ विस्तृत कर सकते हैं।
त्रिगालिया

3
मेरे साथ भी यही समस्या है .. "मूल सेवा नहीं चल रही है !!"
योगेश माहेश्वरी

1
मेरे साथ "नेटिव सर्विस नॉट रनिंग !!" .... क्या कोई सहायता पाठ यहाँ जोड़ सकता है?
पंकज कुमार

1
मुझे भी! "मूल सेवा नहीं चल रही है !!" और उनके नवीनतम संस्करण 1.2 में वे उदाहरण के लिए सॉकेट की तरह एपीआई स्तर 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;
}

गुणवत्ता पैरामीटर या तो Bitmap.Config की एक निरंतर लेता है, आम तौर पर Bitmap.Config.RGB_565या Bitmap.Config.ARGB_8888


मामले की पृष्ठभूमि में सफेद रंग के साथ कैनवास खींचना अशक्त था मेरे लिए चाल। धन्यवाद ओलिवर
शालीन

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

}

ADD PERMISSION

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

यह जवाब सिर्फ ऐप का स्क्रीनशॉट लेता है - न कि "फोन स्क्रीन" जैसा कि सवाल में पूछा गया है - या क्या मैं कुछ गलत कर रहा हूं?
एलिकएल्ज़िन-किलाका

7

आप ऐसा कुछ करने की कोशिश कर सकते हैं,

एक लेआउट या एक दृश्य से एक बिटमैप कैश प्राप्त करना कुछ ऐसा कर रहा है जैसे पहले आप setDrawingCacheEnabledएक लेआउट के लिए जाना होगा (एक रेखीय या संबंध या एक दृश्य)

फिर

Bitmap bm = layout.getDrawingCache()

फिर आप बिटमैप के साथ जो चाहें करें। या तो इसे एक छवि फ़ाइल में बदल दें, या बिटमैप के यूरी को कहीं और भेजें।


1
यह सबसे अच्छा तरीका है अगर यह आपका ऐप है जिसे आप बिटमैप पर लिख रहे हैं। इसके अलावा, उन तरीकों से सावधान रहें जो कैश लेने से पहले देरी कर रहे हैं ... जैसे कि सूची दृश्य के लिए सूचित करें ... ()।
त्रिगालिया

सिर्फ इतना ही नहीं। लेआउट को पहले स्क्रीन पर प्रदर्शित किया जाना चाहिए। यह "कैश" है जिसे आप बाद में प्राप्त कर रहे हैं। दृश्य को छिपाने और पृष्ठभूमि में (सिद्धांत रूप में) स्क्रीनशॉट लेने की कोशिश की, लेकिन यह काम नहीं किया।
केविन टैन

अन्य समाधानों की तुलना में कहीं अधिक कुशल है
शिवजी

6

उन लोगों के लिए जो GLSurfaceView पर कब्जा करना चाहते हैं, getDrawingCache या कैनवास विधि के लिए ड्राइंग काम नहीं करेगा।

फ़्रेम के प्रस्तुत होने के बाद आपको OpenGL फ़्रेमबफ़र की सामग्री को पढ़ना होगा। यहाँ एक अच्छा जवाब है


6

मैंने एक साधारण पुस्तकालय बनाया है जो एक स्क्रीनशॉट लेता है Viewऔर या तो आपको एक बिटमैप ऑब्जेक्ट देता है या इसे सीधे आपके इच्छित किसी भी पथ पर सहेजता है

https://github.com/abdallahalaraby/Blink


क्या इसके लिए रूट किए गए फोन की आवश्यकता है?
नीलेश अग्रवाल

1
कोई रूटिंग की आवश्यकता नहीं है :)
अब्दुल्ला अलाराबी

उपयोग में यू का उल्लेख है Screenshot.takeScreenshot(view, mPath); imageView.setImageBitmap(Screenshot.getBitmapScreenshot(view, mPath)); कि वर्तमान गतिविधि का दृश्य कैसे प्राप्त करें। मैं xml की आईडी का उपयोग नहीं करना चाहता।
नीलेश अग्रवाल

takeScreenshotForScreen()इसके बजाय उपयोग करें ।
अब्दुल्ला अलारैबी

6

छोटा रास्ता है

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

5

बस टारलोका जवाब दे रहा है। इसे काम करने के लिए आपको फॉलोइंग लाइनों को जोड़ना होगा। मैंने छवि का नाम स्थिर कर दिया है। कृपया सुनिश्चित करें कि आप तारकोल के टाइमस्टैम्प वेरिएबल का उपयोग करते हैं, जिसे आपको गतिशील छवि नाम की आवश्यकता है।

    // 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 में पदावनत है । वर्तमान में स्क्रीनशॉट बनाने के लिए अनुशंसित एपीआई PixelCopyएपीआई 24 से उपलब्ध वर्ग है (लेकिन Windowपैरामीटर जो स्वीकार करते हैं, एपीआई 26 == एंड्रॉइड 8.0 ओरेओ से उपलब्ध हैं)। यहाँ एक नमूना कोटलिन कोड प्राप्त करने के लिए है 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
        }
    }
}

रेखाचित्र के समाधान पर PixelCopy के साथ समस्या यह है कि यह केवल दृश्यमान पिक्सेल को कैप्चर करता है। बाकी मेरे लिए काला है। इसलिए सामान को साझा करना संभव नहीं है जो स्क्रॉल करने योग्य है और आंशिक रूप से फ्रेम से बाहर है। क्या आपके पास इसके लिए कोई उपाय है?
हेनिंग

तुम सही हो। इसी तरह यह एक समस्या पैदा कर सकता है अगर एक और दृश्य मैं स्क्रीन के ऊपर दिखना चाहता हूं (जैसे कि दराज खोलने पर)। इन मामलों में मैं सिर्फ पुराने कैनवस तरीके का उपयोग करता हूं :(
मिलो ovskernilovský

1
क्या PixelCopy का उपयोग करके किसी भी रनिंग ऐप पर स्क्रीनशॉट लेना संभव है?
अमीर रज़ाई

2

केवल सिस्टम अनुप्रयोगों के लिए!

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

नोट: सिस्टम एप्लिकेशन को इस कमांड को निष्पादित करने के लिए "सु" को चलाने की आवश्यकता नहीं है।


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

आपको बस ग्रैडल आयात करना है, और बिगस्क्रीशॉट का एक ऑब्जेक्ट बनाना है

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

स्वचालित रूप से स्क्रीन दृश्य समूह के माध्यम से स्क्रॉल करते हुए और अंत में एक साथ इकट्ठे हुए स्क्रीनशॉट के बिटमैप के साथ कॉलबैक प्राप्त किया जाएगा।

@Override public void getScreenshot(Bitmap bitmap) {}

जिसे गैलरी में सहेजा जा सकता है या जो भी उनके उपयोग के बाद आवश्यक है


1

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

-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();}
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.