Получите скриншот текущего приложения переднего плана на Android с правами root
Я занимаюсь разработкой приложения, которое установлено в системном разделе, и я хотел бы знать, возможно ли получить снимок экрана текущего приложения переднего плана от службы. Конечно, это приложение любого стороннего приложения.
Я не интересуюсь вопросами безопасности или чем-то связанным с этим вопросом. Я только хочу получить снимок текущего стороннего приложения переднего плана.
Примечание: я знаю о /system/bin/screencap
Решение, но я ищу более элегантную альтернативу, которая делает все программно.
2 ответа
Прошли месяцы с тех пор, как я задал этот вопрос, но только сейчас было время добавить эту функцию. Способ сделать это просто позвонив screencap -p <file_name_absolute_path>
а затем захватывает файл. Далее приведен код, который я использовал:
private class WorkerTask extends AsyncTask<String, String, File> {
@Override
protected File doInBackground(String... params) {
File screenshotFile = new File(Environment.getExternalStorageDirectory().getPath(), SCREENSHOT_FILE_NAME);
try {
Process screencap = Runtime.getRuntime().exec("screencap -p " + screenshotFile.getAbsolutePath());
screencap.waitFor();
return screenshotFile;
} catch (IOException ioe) {
ioe.printStackTrace();
} catch (InterruptedException ie) {
ie.printStackTrace();
}
return null;
}
@Override
protected void onPostExecute(File screenshot_file) {
// Do something with the file.
}
}
Не забудьте добавить <uses-permission android:name="android.permission.READ_FRAME_BUFFER" />
разрешение на манифест. В противном случае screenshot.png будет пустым.
Это намного проще, чем то, что сказал Горан, и это то, что я наконец использовал.
Примечание: это работало только для меня, когда приложение установлено в системном разделе.
Метод, который я собираюсь описать ниже, позволит вам программно делать снимки экрана любого приложения, находящегося на переднем плане, из фонового процесса.
Я предполагаю, что у вас есть рутированное устройство. В этом случае вы можете использовать инфраструктуру uiautomator для выполнения работы.
Этот фреймворк был создан для автоматизации тестирования приложений на Android в "черном ящике", но он также подойдет и для этой цели. Мы собираемся использовать метод
takeScreenshot(File storePath, float scale, int quality)
Это идет в классе обслуживания:
File f = new File(context.getApplicationInfo().dataDir, "test.jar");
//this command will start uiautomator
String cmd = String.format("uiautomator runtest %s -c com.mypacket.Test", f.getAbsoluteFile());
Process p = doCmds(cmd);
if(null != p)
{
p.waitFor();
}
else
{
Log.e(TAG, "starting the test FAILED");
}
private Process doCmds(String cmds)
{
try
{
Process su = Runtime.getRuntime().exec("su");
DataOutputStream os = new DataOutputStream(su.getOutputStream());
os.writeBytes(cmds + "\n");
os.writeBytes("exit\n");
os.flush();
os.close();
return su;
}
catch(Exception e)
{
e.printStackTrace();
Log.e(TAG, "doCmds FAILED");
return null;
}
}
Это класс для uiautomator:
public class Test extends UiAutomatorTestCase
{
public void testDemo()
{
UiDevice dev = UiDevice.getInstance();
File f = new File(Environment.getExternalStorageDirectory().getAbsolutePath());
dev.takeScreenshot(f, 1.0, 100);
}
}
Лучше всего, если вы создадите фоновый поток, в котором будет работать uiautomator, чтобы он не работал в потоке пользовательского интерфейса. (Служба работает в потоке пользовательского интерфейса).
uiatuomator не знает или имеет контекст Android. Как только uiautomator получит элемент управления, вы сможете вызывать внутри него методы Android, которые не принимают параметр контекста или принадлежат к классу контекста.
Если вам необходимо установить связь между uiautomator и службой (или другими компонентами Android), вы можете использовать LocalSocket. Это позволит общаться обоими способами.