अद्यतन कई अन्य पोस्ट हैं जो एंड्रॉइड में स्क्रीनशॉट कैसे प्राप्त करें, लेकिन किसी को ऐसा करने का पूरा जवाब नहीं मिला। मूल रूप से मैंने फ़्रेम बफर में स्ट्रीम खोलने का प्रयास करते समय एक विशेष समस्या के कारण इसे एक प्रश्न के रूप में पोस्ट किया था। अब मैंने फ़्रेम बफर को फ़ाइल में डंप करने के लिए बदल दिया है, इसलिए मैंने यह दिखाने के लिए अपनी पोस्ट अपडेट की है कि मैं वहां कैसे पहुंचा। संदर्भ (और पावती) के लिए, मुझे फ्रेमबफर को 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 में सुझाया गया है। अन्यथा यह चलता है, शिकायत नहीं करता है, निर्देशिका और न ही फ़ाइल बनाता है।
मूल रूप से मुझे फ्रेम बफर से उपयोग करने योग्य डेटा नहीं मिल सका क्योंकि यह समझने के लिए कि शेल कमांड को सही तरीके से कैसे चलाया जाए। अब जब मैं आदेशों को निष्पादित करने के लिए स्ट्रीम का उपयोग करने के लिए बदल गया हूं, तो मैं फ़्रेम बफर के वर्तमान डेटा को वास्तविक फ़ाइल में भेजने के लिए '>' का उपयोग कर सकता हूं ...
अपने कोडिंग के लिए धन्यवाद। हालांकि, '.raw' फ़ाइल में कोई समस्या हो सकती है। मैंने Google picassa के साथ '.raw' छवि फ़ाइल खोलने का प्रयास किया, लेकिन कहा कि कुछ भाग पिकासा पढ़ नहीं सकता है। क्या आपको पता है कि समस्या क्या है? मैं इससे सामान्य छवि फ़ाइल कैसे प्राप्त कर सकता हूं? धन्यवाद। –
@swk यह उत्तर देने के लिए एक आसान सवाल नहीं है। अनुक्रमिक स्क्रीन शॉट्स के बीच मतभेदों को निर्धारित करने के दायरे में मेरी आवश्यकताएं अधिक थीं इसलिए मैंने पूरी तरह से निर्धारित नहीं किया है कि उन्हें छवियों में वापस कैसे बदला जाए! मैं विशेष रूप से स्टैक ओवरफ़्लो के बाकी हिस्सों की पूरी तरह से खोज करने का सुझाव दूंगा, विशेष रूप से किसी छवि में/dev/graphics/fb0 पर प्राप्त डेटा को कैसे चालू करें। – cgolden
@swk क्या आपको फ्रेमबफर को एक छवि फ़ाइल में कवर करने का कोई तरीका मिला है ?? –