2012-06-09 15 views
7

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

मेरा इरादा एंड्रॉइड डिवाइस पर वास्तविक स्क्रीन का पूरा डंप लेना था। केवल जिस तरह से मैं एडीबी पुल का उपयोग किए बिना ऐसा करने के लिए पा सकता था, सिस्टम के फ्रेम बफर को सीधे एक्सेस करना था। स्पष्ट रूप से इस दृष्टिकोण को डिवाइस पर रूट विशेषाधिकारों की आवश्यकता होगी और ऐप चलाने के लिए! सौभाग्य से मेरे उद्देश्यों के लिए मेरा नियंत्रण है कि डिवाइस कैसे स्थापित किया गया है और मेरे आवेदन के लिए प्रदान किए गए रूट विशेषाधिकारों के साथ रूट डिवाइस को व्यवहार्य है। मेरा परीक्षण वर्तमान में 2.2.3 चल रहे पुराने Droid पर किया जा रहा है।

मुझे https://stackoverflow.com/a/6970338/1446554 से इसका दृष्टिकोण कैसे प्राप्त करने का पहला संकेत मिला। थोड़ी अधिक शोध के बाद मुझे एक और लेख मिला जो वर्णन करता है कि ठीक से run shell commands as root कैसे करें। वे रीबूट निष्पादित करने के लिए इसका उपयोग कर रहे थे, मैं वर्तमान फ्रेम बफर को वास्तविक फ़ाइल में भेजने के लिए इसका उपयोग करता हूं। मेरा वर्तमान परीक्षण केवल एडीबी के माध्यम से और मूल गतिविधि में (प्रत्येक को रूट प्रदान किया जा रहा है) के रूप में प्राप्त किया गया है। मैं पृष्ठभूमि में चल रही एक सेवा से आने वाले अपडेट से और परीक्षण करूँगा!

public class ScreenshotterActivity extends Activity { 
    public static final String TAG = "ScreenShotter"; 

    private Button _SSButton; 
    private PullScreenAsyncTask _Puller; 

    @Override 
    public void onCreate(Bundle savedInstanceState) { 
     super.onCreate(savedInstanceState); 
     setContentView(R.layout.main); 


     _SSButton = (Button)findViewById(R.id.main_screenshotButton); 
     _SSButton.setOnClickListener(new OnClickListener() { 

      public void onClick(View v) { 
       if (_Puller != null) 
        return; 
       //TODO: Verify that external storage is available! Could always use internal instead... 

       _Puller = new PullScreenAsyncTask(); 
       _Puller.execute((Void[])null); 
      } 
     }); 
    } 

    private void runSuShellCommand(String cmd) { 
     Runtime runtime = Runtime.getRuntime(); 
     Process proc = null; 
     OutputStreamWriter osw = null; 
     StringBuilder sbstdOut = new StringBuilder(); 
     StringBuilder sbstdErr = new StringBuilder(); 

     try { // Run Script 
      proc = runtime.exec("su"); 
      osw = new OutputStreamWriter(proc.getOutputStream()); 
      osw.write(cmd); 
      osw.flush(); 
      osw.close(); 
     } catch (IOException ex) { 
      ex.printStackTrace(); 
     } finally { 
      if (osw != null) { 
       try { 
        osw.close(); 
       } catch (IOException e) { 
        e.printStackTrace();      
       } 
      } 
     } 

     try { 
      if (proc != null) 
       proc.waitFor(); 
     } catch (InterruptedException e) { 
      e.printStackTrace(); 
     } 

     sbstdOut.append(readBufferedReader(new InputStreamReader(proc.getInputStream()))); 
     sbstdErr.append(readBufferedReader(new InputStreamReader(proc.getErrorStream()))); 
    } 

    private String readBufferedReader(InputStreamReader input) { 

     BufferedReader reader = new BufferedReader(input); 
     StringBuilder found = new StringBuilder(); 
     String currLine = null; 
     String sep = System.getProperty("line.separator"); 
     try { 
      // Read it all in, line by line. 
      while ((currLine = reader.readLine()) != null) { 
       found.append(currLine); 
       found.append(sep); 
      } 
     } catch (IOException e) { 
      e.printStackTrace(); 
     } finally { 
      try { 
       reader.close(); 
      } catch (IOException e) { 
       e.printStackTrace(); 
      } 
     } 

     return null; 
    } 

    class PullScreenAsyncTask extends AsyncTask<Void, Void, Void> { 

     @Override 
     protected Void doInBackground(Void... params) { 

      File ssDir = new File(Environment.getExternalStorageDirectory(), "/screenshots"); 
      if (ssDir.exists() == false) { 
       Log.i(TAG, "Screenshot directory doesn't already exist, creating..."); 
       if (ssDir.mkdirs() == false) { 
        //TODO: We're kinda screwed... what can be done? 
        Log.w(TAG, "Failed to create directory structure necessary to work with screenshots!"); 
        return null; 
       } 
      } 
      File ss = new File(ssDir, "ss.raw");    
      if (ss.exists() == true) { 
       ss.delete(); 
       Log.i(TAG, "Deleted old Screenshot file."); 
      } 
      String cmd = "/system/bin/cat /dev/graphics/fb0 > "+ ss.getAbsolutePath(); 
      runSuShellCommand(cmd); 
      return null; 
     } 

     @Override 
     protected void onPostExecute(Void result) { 
      super.onPostExecute(result); 
      _Puller = null; 
     } 
    } 
} 

यह भी प्रकट करने के लिए android.permission.WRITE_EXTERNAL_STORAGE अनुमति जोड़ने की आवश्यकता है: यहाँ अपने पूरे परीक्षण गतिविधि है कि एक फ़ाइल के लिए वर्तमान स्क्रीन निर्यात कर सकते हैं है। जैसा कि this post में सुझाया गया है। अन्यथा यह चलता है, शिकायत नहीं करता है, निर्देशिका और न ही फ़ाइल बनाता है।

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

+1

अपने कोडिंग के लिए धन्यवाद। हालांकि, '.raw' फ़ाइल में कोई समस्या हो सकती है। मैंने Google picassa के साथ '.raw' छवि फ़ाइल खोलने का प्रयास किया, लेकिन कहा कि कुछ भाग पिकासा पढ़ नहीं सकता है। क्या आपको पता है कि समस्या क्या है? मैं इससे सामान्य छवि फ़ाइल कैसे प्राप्त कर सकता हूं? धन्यवाद। –

+0

@swk यह उत्तर देने के लिए एक आसान सवाल नहीं है। अनुक्रमिक स्क्रीन शॉट्स के बीच मतभेदों को निर्धारित करने के दायरे में मेरी आवश्यकताएं अधिक थीं इसलिए मैंने पूरी तरह से निर्धारित नहीं किया है कि उन्हें छवियों में वापस कैसे बदला जाए! मैं विशेष रूप से स्टैक ओवरफ़्लो के बाकी हिस्सों की पूरी तरह से खोज करने का सुझाव दूंगा, विशेष रूप से किसी छवि में/dev/graphics/fb0 पर प्राप्त डेटा को कैसे चालू करें। – cgolden

+0

@swk क्या आपको फ्रेमबफर को एक छवि फ़ाइल में कवर करने का कोई तरीका मिला है ?? –

उत्तर

3

यह विभिन्न फोन के लिए अलग होगा। यह आपके डिवाइस के अंतर्निहित ग्राफिक्स प्रारूप पर निर्भर करता है। आप सिस्टम कॉल का उपयोग कर ग्राफिक्स प्रारूप क्या कर सकते हैं मतदान कर सकते हैं। यदि आप केवल उन डिवाइसों पर इसे चलाने जा रहे हैं जिन्हें आप जानते हैं कि आप का ग्राफिक्स प्रारूप एक कनवर्टर लिख सकता है जो इसे एक ज्ञात प्रारूप में बदल देता है।

आप निम्न परियोजना पर एक नजर है कर सकते हैं: http://code.google.com/p/android-fb2png/

आप fb2png.c के लिए स्रोत कोड को देखो, तो आप देख सकते हैं कि वे FBIOGET_VSCREENINFO मतदान के बारे में जो जानकारी शामिल है कैसे डिवाइस भंडार स्मृति में स्क्रीन छवि । एक बार जब आप इसे जानते हैं, तो आप इसे उस प्रारूप में रूपांतरित करने में सक्षम होना चाहिए जिसका आप उपयोग कर सकते हैं।

मुझे उम्मीद है कि इससे मदद मिलती है।

+0

यह समस्या को हल करने के लिए सबसे संभावित मार्ग की तरह दिखता है। चूंकि इस विषय में कोई और रुचि नहीं दिखती है, इसलिए मैं इसे उत्तर के रूप में चिह्नित कर रहा हूं। अगर कोई इसे पूरी तरह हल कर लेता है तो यह वास्तव में अच्छा होगा, लेकिन दुर्भाग्यवश मैं बदले में अन्य चीजों से घिरा हुआ हूं! – cgolden

4

आईसीएस उपकरणों के लिए एक आसान समाधान कमांड लाइन से निम्नलिखित

adb shell /system/bin/screencap -p /sdcard/screenshot.png 
adb pull /sdcard/screenshot.png screenshot.png 

यह उपयोग करने के लिए मौजूदा निर्देशिका में screenshot.png फाइल को सेव करेंगे।

सैमसंग गैलेक्सी एसआईआई पर चल रहा 4.0.3 चल रहा है।

+0

यह प्रश्न एक अलग मशीन से काम करने से संबंधित नहीं था। यह पूरी तरह से एक डिवाइस पर, क्षेत्र की स्थिति में था। एडीबी अच्छा है, लेकिन मुझे इस स्थिति में कोई अच्छा काम नहीं करता है। – cgolden

10

प्रोग्राम आप चला सकते हैं "adb शेल/प्रणाली/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(); 
+0

यह काम नहीं कर रहा है .. यह वापस लौट रहा है। यहां तक ​​कि मैंने अनुमति '<उपयोग-अनुमति एंड्रॉइड: नाम = "android.permission.WRITE_EXTERNAL_STORAGE" /> ' – ashish

+0

कौन सा एंड्रॉइड संस्करण –

+0

अपने किटकैट (4.4) @ विश्वनाथ – ashish

संबंधित मुद्दे