web-dev-qa-db-ja.com

Screenshot UX Trialのように、rootの許可なしにプログラムで他のアプリのスクリーンショットを撮る方法は?

Screenshot UX Trialのように、root権限なしにプログラムで他のアプリのスクリーンショットを撮る方法は?

  1. 私は自分のアプリでルートビューのビットマップをキャプチャできることを知っています。しかし、アプリがバックグラウンドで実行されている場合、他のアプリのルートビューを取得できません

    bitmap = Bitmap.createBitmap(rootview.getDrawingCache());

  2. マニフェストに現在のフレームバッファーをキャプチャする権限があります:Android.permission.READ_FRAME_BUFFER。しかし、一部のWebサイトでは、署名アプリ専用であると書かれています。

    Check Android Permissions-Protection Levels

Screenshot UX Trialを試した後、私は許可を読みました:

  • インターネット:ルート化された電話のlocalhostスクリーンショットサーバーに接続します。
  • SYSTEM_ALERT_WINDOW:一番上のカメラボタン用。
  • バイブレーション:バイブレーションフィードバック用。
  • WRITE_EXTERNAL_STORAGE:スクリーンショットを保存します。
  • GET_TASKS:非ルート&非プリロードキャプチャメソッドのフォアグラウンド開発設定アクティビティを検出します。

いずれかのSYSTEM_ALERT_WINDOWまたはGET_TASKSアプリがスクリーンショットを撮ることを許可します。私はそれがどのように機能するかについて2つの推測を持っています:

  1. フォアグラウンドアクティビティのActivityにアクセスでき、Activityのルートビューを取得し、スクリーンショットをキャプチャできます。
  2. glreadpixelsを呼び出す

私の推測のいずれかを試してみたら、結果を教えてください。

53
Victor Chang

これは非常に困難です。私はそれをしようとして数年を費やしました。最終的には成功しましたが、解決策には商業的な努力と技術的な努力が必要です。


2015年3月に更新

以下のもののほとんどはもはや最新ではありません。今、すべてのこれらの年後、_Android.media.projection_パッケージがあります https://developer.Android.com/reference/Android/media/projection/package-summary.html 必要!


独自のアプリケーションの画面イメージをキャプチャする

完全を期すために、Bitmap.createBitmap(rootview.getDrawingCache());および同様のメカニズムを使用して独自のアプリケーションの画像をキャプチャできるという独自のコメントを含めたいと思います。

バックグラウンドで別のアプリケーションの画面をキャプチャする

_READ_FRAMEBUFFER_パーミッションを使用する

まず、通常のアプリケーションでは「署名」レベルであるため、_READ_FRAMEBUFFER_パーミッションを使用できないことは間違いありません。つまり、このようなスクリーンショットを撮るには、AndroidシステムROMと同じキーで署名する必要があります。

これは少し悲しいと思ったので、2009年にオープンソースプロジェクトを提出するためにAndroidオープンソースプロジェクトを提出しました 1 。 AndroidアーキテクトのDianne Hackbornからの応答は次のとおりです。

いいえ。絶対に肯定的ではありません。

それで、それはうまくいきました!したがって、この許可は今日までsignatureレベルのままです。

ただし、この許可があれば、captureScreenISurfaceComposerメンバーを呼び出すことができます [2 。この関数にアクセスするには、Android NDKおよびドキュメント化されていないAPIを使用して、ネイティブコードを記述する必要があります。しかし、それは可能です。

内部的にAndroidグラフィックスサブシステム内で、これはglReadPixels呼び出しを使用して、GPUからCPUにピクセルを取得します。 (GPUはAndroidのほとんどの合成に使用されます。実際、Android 4.0+は追加のハードウェアコンポジターをサポートし、Surface FlingerはこれらのピクセルをCPUに戻すためにさらに多くの作業を行う必要があります。)

この呼び出しは、いくつかの小さな問題を除いて美しく機能します:

  • サポートされていないAPIを使用するリスクは、いつでも壊れる可能性があります。
  • C++で呼び出す手間
  • GPUパイプラインが停止する原因となり、GPUデザイナーを混乱させる可能性がありますが、実際には問題を引き起こしません
  • GPUbackからCPUへの広い帯域幅に依存しています。メモリアーキテクチャはデータを反対方向に送信するように設計されているため、これは問題となる場合があります。ただし、最新のAndroidチップセットアーキテクチャはすべて、GPUとCPUの間でメモリを直接共有していることを思い出しているようです。ただし、1つ(Broadcomかもしれません。非常に遅くなります。

...そして1つの大きな問題...

  • 最も重要なことは、通常のアプリケーションライターとして、必要な署名レベルのアクセス許可のためにこのAPIを呼び出すことさえできないことです。

それでも、ほとんどのAndroidデバイスでは、これから毎秒10フレームを取得できます。さらに良いことに、このAPIは実際には、GPUのハードウェアで結果の画像のスケーリングをサポートしているため、賢い場合は、画像を事前にスケーリングできますピクセルがCPUにヒットする前に必要なサイズ。そのため、非常に高いパフォーマンスが得られます。

もちろん、関連するOpenGLコンテキストにアクセスできないため、アプリケーションライターとしてglReadPixelsを呼び出すことはできません。表面のフリンガーが所有しています。

_/dev/graphics/fb0_などを使用する

フレームバッファを表すこれらのLinuxデバイスファイルを読み取ろうとする人もいます。ただし、次の3つの問題があります。

  • ルートが必要です。
  • 時々彼らもそこにいません。
  • 多くの場合、それらは実際の画面イメージを表していません。グラフィックはGPUで合成されることをAndroidで覚えておいてください。そのため、CPUが完全な合成画面イメージのコピーにアクセスする必要がある理由はありませんが、多くの場合はアクセスできません。このファイルには、ティアリング(最高の場合)とガベージイメージ(最悪の場合)が含まれることがあります。興味深いことに、根ざした携帯電話用のツールの一部はこの方法を使用していますが、これは間違いだと思います。ルートを取得している場合、定義上、すべてのAndroid権限を持っているため、上記のcaptureScreen APIを呼び出して正しいイメージを取得できます。

ハードウェアパートナーの使用

今、私たちは商業的な行動を必要とするソリューションに入ります。

Androidチップセットメーカーと話をすると、多くの場合、解決策が提示されます。ハードウェアを設計しているため、フレームバッファーにアクセスできます。また、カスタムカーネルドライバーに直接アクセスするだけで、Android権限モデルを完全に回避するライブラリを提供できます。

特定の電話モデルを目指している場合、これは多くの場合、前向きな方法です。もちろん、シリコンメーカーだけでなく、電話メーカーとも協力する必要があるでしょう。

これにより、優れた結果が得られる場合があります。たとえば、一部のハードウェアでは、電話ハードウェアフレームバッファーを直接電話ハードウェアH.264ビデオエンコーダーにパイプし、電話画面にあるものの事前にエンコードされたビデオストリームを取得することができると聞きました。素晴らしい。 (残念ながら、私はknowのみです。これはTI OMAPチップで可能であり、電話市場から徐々に撤退しています)。

セキュリティホールを使用する

Androidは許可モデルを厳密に実施し、セキュリティホールはほとんどありません。ただし、Android OEMは不注意な場合があります。

たとえば、名前がSで始まる大手OEMは、キーストロークを使用して画面をキャプチャする方法を実装しています。 SDカード上の誰でも読み取り可能なファイルに保存します。仮に、これらのキーをインターセプトするものを見つけて、それがどのように機能するかを見ることができるかもしれません。おそらく、あなたは似たようなことをすることができます。

また、おそらく名前がSで始まる別の大手OEM向けの方法があるかもしれません。

いいえ、このセクションではこれ以上詳しく説明しません。これらのことを行う方法を理解するには、リバースエンジニアリングされたソフトウェアが必要です。これは違法かもしれません。幸運を祈ります。

電話メーカーとの連携

前に説明したように、電話メーカーは動作するAPIにすぐにアクセスできます。また、電話メーカーにはsignatureレベルの権限が必要です。

だから、あなたがする必要があるのは、電話メーカーによって署名されたソフトウェアを取得することを手配することです。

ただし、これはhardです。ソフトウェアに署名することで、電話メーカーはその品質を保証しているため、ソースコードを監査する必要があります。また、Androidの性質により、ソフトウェアに署名する場合は、配布する必要があります。他の人の署名によって署名されている場合、マーケットに置くことはできません。

ただし、OEMはROMに含める必要はありません。Android市場で配布することができます。しかし、できません。

各ベンダーが小さなライブラリに署名すると、一般的なSDKからアクセスできるようになります。それは私を導く...

これをすでに解決したソフトウェアパートナーと連携する

RealVNCで働いていたので、これについてはよく知っています。これらのシグネチャレベルAPIにアクセスするために、すべての主要なAndroid電話ベンダーと協力しました。これを達成するために必要な多くの人的努力(商業的および技術的)を過度に強調することはできません。一部のOEMはこの作業を公表しています-たとえば、 4

はRealVNCで動作しなくなりました。そのため、彼らのソフトウェアを宣伝しても何も得られません。ただし、本当に本当に複数のAndroidデバイスで画面をキャプチャできるようにしたい場合は、 -リモートコントロールサービスまたはAndroid VNC SDKを使用 5 。これはオープンソースではないので、支払いを期待する必要があります。これらすべてのAndroid OEMとの作業に伴う多大な努力を考えると、これは十分に公平だと思います。

バランスをとるために、他のベンダーもこれについて電話メーカーと協力していることを指摘する必要があります。ソティ。しかし、これらはすべて、一般的なリモートコントロール/イベントインジェクションSDKではなく、特定のデバイス管理ソリューションを提供すると考えています。

USB経由

別のオプション-USB経由のデバッグ接続をリッスンするadbデーモンには、通常のアプリケーションよりもわずかに多くの特権があります。そのため、画面を取得できます(ddmsツールを使用してその画像を表示できます)。 adbを使用してコマンドを実行できる場合は、それらの特権も取得できます(前述のAndroid-screenshot-libraryに従って)。

Androidオープンソースプロジェクトに貢献する

最終的に、この問題は私をほこりに減らし、Android電話からピクセルを絞ろうとすることを伴わない、より緑の牧草地に向かいました。

しかし、RealVNCを離れる前に、これらのAPIをAndroidオープンソースプロジェクトに再提供しようとしました。今回は、より肯定的な反応を得ました 6 。要するに、セキュリティのアプローチはほぼ正しいが、グラフィックスシステムがパッチを受け入れるにはあまりにも混乱していることが示唆されました。さて、素晴らしいニュースは、グラフィックシステムが混乱していないことです。実際、グラフィックシステムの変更は一切必要ないというcaptureScreen APIを持っています。したがって、このAPIを中心にAOSPに新しいセキュリティメカニズムを送信して、この問題を最終的に解決できる可能性があります。

幸運を祈ります!

107
Adrian Taylor

多分 Android-screenshot-library が助けになるでしょう。しかし、彼らのUsageページでは、adbで開始されたネイティブサービスが必要であると述べています(Android sdk)から)。

PS:スクリーンショットUXはルート化されていないすべての電話で機能するわけではないことに注意してください。

3
DNax