Android снимок экрана на рутированном устройстве
UPDATE Есть ряд других постов, спрашивающих, как сделать скриншот в Android, но ни один, похоже, не дал полного ответа о том, как это сделать. Первоначально я опубликовал это как вопрос из-за конкретной проблемы, с которой я столкнулся при попытке открыть поток в буфер кадров. Теперь я переключился на сброс буфера кадров в файл, поэтому я обновил свой пост, чтобы показать, как я туда попал. Для справки (и подтверждения) я нашел команду для отправки FrameBuffer в файл изэта почта (к сожалению, он не сообщил, как он дошел до этого момента). Мне просто не хватает, как превратить необработанные данные, которые я извлек из буфера кадров, в настоящий файл изображения.
Мое намерение состояло в том, чтобы взять полный дамп реального экрана на устройстве Android.only Я смог найти способ сделать это без использования моста adb - прямой доступ к кадровому буферу системы. Очевидно, что этот подход потребует привилегий суперпользователя на устройстве и для приложения, на котором он запущен! К счастью, для моих целей у меня есть контроль над тем, как настроено устройство и как рутирование устройства с привилегиями root, предоставленными моему приложению, возможно. Мое тестирование в настоящее время проводится на старом Droid 2.2.3.
Я нашел свои первые намеки на то, как подойти к нему сhttps://stackoverflow.com/a/6970338/1446554, После нескольких дополнительных исследований я нашел другую статью, в которой описано, как правильнозапускать команды оболочки от имени пользователя root, Они использовали его для перезагрузки, я использую его для отправки текущего кадра буфера в реальный файл. Мое текущее тестирование дало мне возможность проделать это только через ADB и в базовом действии (каждому из них был предоставлен 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
разрешение на Манифест. Как предложено вэта почта, В противном случае он запускается, не жалуется, не создает каталоги или файл.
Первоначально я не мог получить пригодные для использования данные из буфера кадров из-за непонимания того, как правильно запускать команды оболочки. Теперь, когда я перешел к использованию потоков для выполнения команд, я могу использовать & gt; отправлять текущие данные буфера кадров в фактический файл ...