Вопрос по root, android, screenshot – 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; отправлять текущие данные буфера кадров в фактический файл ...
.raw
файл может иметь проблему. Я пытался открыть.raw
Файл изображения с Google Picassa, но там говорится, что часть Picassa не может прочитать. Знаете ли вы, в чем проблема? Как я могу получить нормальный файл изображения из него? Благодарю.
user1468308
графического формата вашего устройства. Вы можете опросить, какой графический формат использует системные вызовы. Если вы собираетесь запускать это только на устройствах, которые вам известны в графическом формате, вы можете написать конвертер, который преобразует его в известный формат.
Вы можете взглянуть на следующий проект:http://code.google.com/p/android-fb2png/
Если вы посмотрите на исходный код fb2png.c, то увидите, что они опрашивают FBIOGET_VSCREENINFO, в котором содержится информация о том, как устройство хранит изображение экрана в памяти. Как только вы это узнаете, вы сможете преобразовать его в формат, который вы можете использовать.
Надеюсь, это поможет.
го из командной строки
adb shell /system/bin/screencap -p /sdcard/screenshot.png
adb pull /sdcard/screenshot.png screenshot.png
Это сохранит файл screenshot.png в текущем каталоге.
Проверено на Samsung Galaxy SII под управлением 4.0.3.