Intereting Posts
Проект Android с использованием httpclient -> http.client (apache), метод post / get Как избежать ограничения на использование 65k при использовании сервисов Google Play Попытка динамического добавления TextView в ScrollView сбой при использовании XML-макета Показать предыдущий фрагмент Android, Как правильно использовать метод readTypedList в классе Parcelable? Ошибка телефона cmd: сбой команды с кодом выхода ENOENT MediaPlayer перестает играть примерно через 5 секунд Открыть DatePickerDialog при нажатии EditText занимает два клика Android ListView: верхний / нижний колонтитул, который заполняет оставшееся пространство на экране Как вызвать перерисовку родительского представления, когда кто-либо из его детей перерисовывается? Как преобразовать 16-битный бит байтового массива PCM в двойной или плавающий массив? Почему приложение неожиданно закрывается, не вызывая никаких ошибок? Android Stringblock.get Исключение NullPointer на Lollipop Можно ли масштабировать drawableleft & drawableright в текстовом режиме? LayerDrawable программно

Как захватить содержимое экрана устройства Android?

Возможный дубликат:
Как программно сделать снимок экрана на Android?

Как захватить содержимое экрана устройства Android и сделать файл изображения с использованием данных моментальных снимков? Какой API я должен использовать или где я могу найти связанные ресурсы?

BTW: нет снимка камеры, но экран устройства

Solutions Collecting From Web of "Как захватить содержимое экрана устройства Android?"

Согласно этой ссылке , можно использовать ddms в каталоге tools android sdk для захвата экрана.

Для этого в приложении (а не во время разработки) есть приложения для этого. Но, как указывает @ zed_0xff, это, конечно, требует root.

Используйте следующий код:

Bitmap bitmap; View v1 = MyView.getRootView(); v1.setDrawingCacheEnabled(true); bitmap = Bitmap.createBitmap(v1.getDrawingCache()); v1.setDrawingCacheEnabled(false); 

Здесь MyView – это View через который нам нужно включать экран. Вы также можете получить DrawingCache из любого View this way (без getRootView() ).

Есть и другой способ.
Если у нас есть ScrollView виде корневого представления, то лучше использовать следующий код,

 LayoutInflater inflater = (LayoutInflater) this.getSystemService(LAYOUT_INFLATER_SERVICE); FrameLayout root = (FrameLayout) inflater.inflate(R.layout.activity_main, null); // activity_main is UI(xml) file we used in our Activity class. FrameLayout is root view of my UI(xml) file. root.setDrawingCacheEnabled(true); Bitmap bitmap = getBitmapFromView(this.getWindow().findViewById(R.id.frameLayout)); // here give id of our root layout (here its my FrameLayout's id) root.setDrawingCacheEnabled(false); 

Вот метод getBitmapFromView()

 public static Bitmap getBitmapFromView(View view) { //Define a bitmap with the same size as the view Bitmap returnedBitmap = Bitmap.createBitmap(view.getWidth(), view.getHeight(),Bitmap.Config.ARGB_8888); //Bind a canvas to it Canvas canvas = new Canvas(returnedBitmap); //Get the view's background Drawable bgDrawable =view.getBackground(); if (bgDrawable!=null) //has background drawable, then draw it on the canvas bgDrawable.draw(canvas); else //does not have background drawable, then draw white background on the canvas canvas.drawColor(Color.WHITE); // draw the view on the canvas view.draw(canvas); //return the bitmap return returnedBitmap; } 

Он отобразит весь экран, включая контент, скрытый в вашем ScrollView

ОБНОВЛЕНО НА 20-04-2016

Существует еще один лучший способ сделать снимок экрана.
Здесь я сделал снимок экрана WebView .

 WebView w = new WebView(this); w.setWebViewClient(new WebViewClient() { public void onPageFinished(final WebView webView, String url) { new Handler().postDelayed(new Runnable(){ @Override public void run() { webView.measure(View.MeasureSpec.makeMeasureSpec( View.MeasureSpec.UNSPECIFIED, View.MeasureSpec.UNSPECIFIED), View.MeasureSpec.makeMeasureSpec(0, View.MeasureSpec.UNSPECIFIED)); webView.layout(0, 0, webView.getMeasuredWidth(), webView.getMeasuredHeight()); webView.setDrawingCacheEnabled(true); webView.buildDrawingCache(); Bitmap bitmap = Bitmap.createBitmap(webView.getMeasuredWidth(), webView.getMeasuredHeight(), Bitmap.Config.ARGB_8888); Canvas canvas = new Canvas(bitmap); Paint paint = new Paint(); int height = bitmap.getHeight(); canvas.drawBitmap(bitmap, 0, height, paint); webView.draw(canvas); if (bitmap != null) { try { String filePath = Environment.getExternalStorageDirectory() .toString(); OutputStream out = null; File file = new File(filePath, "/webviewScreenShot.png"); out = new FileOutputStream(file); bitmap.compress(Bitmap.CompressFormat.PNG, 50, out); out.flush(); out.close(); bitmap.recycle(); } catch (Exception e) { e.printStackTrace(); } } } }, 1000); } }); 

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

AFAIK. Все методы, используемые для захвата скриншота Android, используют фреймбуфер / dev / graphics / fb0. Это включает в себя ddms. Это требует, чтобы корень читался из этого потока. Ddms использует adbd для запроса информации, поэтому root не требуется, поскольку adb имеет разрешения, необходимые для запроса данных из / dev / graphics / fb0.

Фреймбуфер содержит 2 + «кадры» изображений RGB565. Если вы можете прочитать данные, вам нужно будет узнать разрешение экрана, чтобы узнать, сколько байтов необходимо для получения изображения. Каждый пиксель составляет 2 байта, поэтому, если разрешение экрана было 480х800, вам нужно было бы прочитать 768 000 байт для изображения, так как изображение 480х800 RGB565 имеет 384 000 пикселей.

Для новых платформ Android можно выполнить системную утилиту «screencap» в / system / bin, чтобы получить скриншот без разрешения root. Вы можете попробовать «/ system / bin / screencap -h», чтобы узнать, как использовать его в adb или любой оболочке.

Кстати, я думаю, что этот метод хорош только для одного моментального снимка. Если мы хотим захватить несколько кадров для воспроизведения экрана, это будет слишком медленно. Я не знаю, существует ли какой-либо другой подход для более быстрого захвата экрана.

[Исходный код Android:]

На стороне C ++ SurfaceFlinger реализует API-интерфейс captureScreen. Это отображается через интерфейс IPC связующего, каждый раз возвращающий новую область зольника, содержащую необработанные пиксели с экрана. Фактический снимок экрана выполняется через OpenGL.

Для системных клиентов C ++ интерфейс <surfaceflinger_client/SurfaceComposerClient.h> через класс ScreenshotClient, определенный в <surfaceflinger_client/SurfaceComposerClient.h> для Android <4.1; Для Android> 4.1 use <gui/SurfaceComposerClient.h>

Перед JB, чтобы сделать снимок экрана в программе на C ++, этого было достаточно:

 ScreenshotClient ssc; ssc.update(); 

С JB и несколькими дисплеями он становится немного сложнее:

 ssc.update( android::SurfaceComposerClient::getBuiltInDisplay( android::ISurfaceComposer::eDisplayIdMain)); 

Затем вы можете получить к нему доступ:

 do_something_with_raw_bits(ssc.getPixels(), ssc.getSize(), ...); 

Используя исходный код Android, вы можете скомпилировать свою собственную общую библиотеку для доступа к этому API, а затем разоблачить ее через JNI на Java. Чтобы создать экранный снимок вашего приложения, приложение должно иметь разрешение READ_FRAME_BUFFER . Но даже тогда, по-видимому, вы можете создавать снимки экрана только из системных приложений, то есть тех, которые подписаны с тем же ключом, что и система. (Эта часть я до сих пор не совсем понимаю, так как я недостаточно разбираюсь в системе Android Permissions.)

Вот фрагмент кода для JB 4.1 / 4.2:

 #include <utils/RefBase.h> #include <binder/IBinder.h> #include <binder/MemoryHeapBase.h> #include <gui/ISurfaceComposer.h> #include <gui/SurfaceComposerClient.h> static void do_save(const char *filename, const void *buf, size_t size) { int out = open(filename, O_RDWR|O_CREAT, 0666); int len = write(out, buf, size); printf("Wrote %d bytes to out.\n", len); close(out); } int main(int ac, char **av) { android::ScreenshotClient ssc; const void *pixels; size_t size; int buffer_index; if(ssc.update( android::SurfaceComposerClient::getBuiltInDisplay( android::ISurfaceComposer::eDisplayIdMain)) != NO_ERROR ){ printf("Captured: w=%d, h=%d, format=%d\n"); ssc.getWidth(), ssc.getHeight(), ssc.getFormat()); size = ssc.getSize(); do_save(av[1], pixels, size); } else printf(" screen shot client Captured Failed"); return 0; } 

Вы можете попробовать следующую библиотеку: http://code.google.com/p/android-screenshot-library/ Android Screenshot Library (ASL) позволяет программно снимать скриншоты с Android-устройств без необходимости иметь права доступа root. Вместо этого ASL использует собственный сервис, работающий в фоновом режиме, который запускается через Android Debug Bridge (ADB) один раз за загрузку устройства.

Если вы хотите сделать захват экрана с Java-кода в Android-приложении AFAIK, у вас должны быть корневые резервы.

Кажется, что Framebuffer идет, он не всегда будет содержать 2+ фрейма, как упоминалось Райаном Конрадом. В моем случае он содержал только один. Я думаю, это зависит от размера рамки / дисплея.

Я пытался читать фреймбуфер непрерывно, но, похоже, он возвращается для фиксированного количества прочитанных байтов. В моем случае это (3 410 432) байт, что достаточно для хранения кадра отображения 854 * 480 RGBA (3 279 360 байт). Да, кадр в двоичном формате, выводимый из fb0, – это RGBA на моем устройстве . Это, скорее всего, будет зависеть от устройства к устройству . Это будет важно для вас, чтобы расшифровать его =)

В моих разрешениях device / dev / graphics / fb0 так, что только root и пользователи из групповой графики могут читать fb0. Графика – ограниченная группа, поэтому вы, вероятно, будете иметь доступ только к fb0 с помощью корневого телефона с помощью команды su.

Приложения для Android имеют приложение id (uid) пользователя _ ## и идентификатор группы (guid) _ ## .

В оболочке adb есть оболочка uid и оболочка guid , которая имеет гораздо больше разрешений, чем приложение. Фактически вы можете проверить эти разрешения на /system/permissions/platform.xml

Это означает, что вы сможете читать fb0 в оболочке adb без root, но вы не будете читать его в приложении без root.

Кроме того, предоставление разрешений READ_FRAME_BUFFER и / или ACCESS_SURFACE_FLINGER для AndroidManifest.xml ничего не сделает для обычного приложения, потому что они будут работать только для приложений подписи.