Вопрос по root, android, screenshot – Android снимок экрана на рутированном устройстве

7

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; отправлять текущие данные буфера кадров в фактический файл ...

@swk Это не простой вопрос для ответа. Мои требования были в большей степени связаны с определением различий между последовательными снимками экрана, поэтому я не до конца определил, как превратить их в изображения! Я бы предложил провести тщательный поиск остальной части переполнения стека, чтобы выяснить, как превратить данные, найденные в / dev / graphics / fb0, в изображение. cgolden
@swk Нашли ли вы какой-нибудь способ включения кадрового буфера в файл изображения? Yogesh Maheshwari
Спасибо за вашу кодировку. Тем не менее.raw файл может иметь проблему. Я пытался открыть.raw Файл изображения с Google Picassa, но там говорится, что часть Picassa не может прочитать. Знаете ли вы, в чем проблема? Как я могу получить нормальный файл изображения из него? Благодарю. user1468308

Ваш Ответ

3   ответа
3

графического формата вашего устройства. Вы можете опросить, какой графический формат использует системные вызовы. Если вы собираетесь запускать это только на устройствах, которые вам известны в графическом формате, вы можете написать конвертер, который преобразует его в известный формат.

Вы можете взглянуть на следующий проект:http://code.google.com/p/android-fb2png/

Если вы посмотрите на исходный код fb2png.c, то увидите, что они опрашивают FBIOGET_VSCREENINFO, в котором содержится информация о том, как устройство хранит изображение экрана в памяти. Как только вы это узнаете, вы сможете преобразовать его в формат, который вы можете использовать.

Надеюсь, это поможет.

Это похоже на наиболее вероятный путь решения этой проблемы. Поскольку нет больше интереса к этой теме, я отмечаю это как ответ. Было бы действительно хорошо, если бы кто-то полностью решил это, но я, к сожалению, сейчас просто завален другими вещами! cgolden
4

го из командной строки

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

Это сохранит файл screenshot.png в текущем каталоге.

Проверено на Samsung Galaxy SII под управлением 4.0.3.

Этот вопрос не был связан с работой с отдельной машины. Это было чисто для устройства, в полевой ситуации. АБР хорош, но не приносит мне никакой пользы в этой ситуации. cgolden
10

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();
Хорошо, что вы не объяснили, на самом деле у Киткат есть проблема с<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" /> Можете ли вы обратиться к вопросам, касающимся этого разрешения на KitKat
Не работает .. Возвращается NULL. даже я установил разрешение<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
Какую версию Android вы используете
Nevermind: он отлично работает на моем рутированном устройстве. Спасибо!
его KitKat (4.4) @ Viswanath

Похожие вопросы