55

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

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

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

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

    Android のアクセス許可を確認する - 保護レベル

Screenshot UX Trial を試した後、許可を読みました。

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

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

  1. Activityフォアグラウンド アクティビティのにアクセスできる場合があります。 のルート ビューをActivity取得し、スクリーンショットをキャプチャします。
  2. 通話中glreadpixels

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

4

3 に答える 3

114

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


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- レベルです。

ただし、この権限があれば、 2captureScreenのメンバーを呼び出すことができます。この関数にアクセスするには、Android NDK と文書化されていない API を使用して、ネイティブ コードを記述する必要があります。ただし、可能です。ISurfaceComposer

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

この呼び出しは、いくつかの小さな問題を除けば、うまく機能します。

  • いつでも壊れる可能性のあるサポートされていない API を使用するリスク。
  • C++で呼び出す手間
  • これにより、GPU パイプラインが失速し、GPU 設計者を動揺させる可能性がありますが、実際には問題を引き起こすことはありません
  • これは、GPU からCPU に戻る大きな帯域幅に依存しています。メモリ アーキテクチャはデータを逆方向に送信するように設計されているため、これが問題になる場合があります。ただし、最近のすべての Android チップセット アーキテクチャは、GPU と CPU の間でメモリを直接共有していることを思い出しているようです。

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

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

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

もちろん、アプリケーション作成者はglReadPixels、関連する OpenGL コンテキストにアクセスできないため、呼び出すことができないことに注意してください。水上フリンガーが所有しています。

使用/dev/graphics/fb0および類似

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

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

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

今、私たちは商業的な行動を必要とする解決策に入ります.

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

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

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

セキュリティ ホールの使用

Android はパーミッション モデルを厳格に適用しており、セキュリティ ホールはほとんどありません。ただし、Android OEM は不注意な場合があります。

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

また、名前が S で始まる別の大手 OEM にも道があるかもしれません。

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

電話メーカーとの連携

前述のように、電話メーカーは、機能する API にすぐにアクセスできます。また、電話メーカーには、signature必要な レベルのアクセス許可があります。

そのため、電話メーカーがソフトウェアに署名するよう手配するだけで済みます。

しかし、これは難しいです。ソフトウェアに署名することで、電話メーカーはその品質を保証することになります。そのため、ソース コードを監査する必要があります。また、Android の性質上、ソフトウェアに署名する場合は、それを配布する必要があります。他人の署名がある場合、市場に出すことはできません。

ただし、OEM はそれを ROM に含める必要はありません。Android マーケットで配布することはできます。しかし、あなたはできません。

良い解決策は、各ベンダーが小さなライブラリに署名し、共通の SDK からアクセスできるようにすることです。それは私を...

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

私は RealVNC で働いていたので、これについてはよく知っています。これらの署名レベルの API にアクセスできるようにするために、すべての主要な Android スマートフォン ベンダーと協力しました。これを達成するために必要な、非常に多くの工数 (商業的および技術的) の努力はいくら強調してもしすぎることはありません。一部の OEM は、この作業を公表しています (例: 4 ) 。

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

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

USB経由

別のオプション - adbUSB 経由のデバッグ接続をリッスンするデーモンは、通常のアプリケーションよりもわずかに多くの権限を持っているため、画面を取得できます (ddmsツールを使用してそのイメージを確認できます)。を使用して任意のコマンドを実行できる場合はadb、それらの権限も取得できます (以前にリンクされた android-screenshot-library に従って)。

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

結局、この問題は私を粉々にしてしまい、Android フォンからピクセルを絞り出そうとする必要のない、より環境に優しい牧草地に向かいました。

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

頑張ってください!

于 2013-02-05T22:59:09.900 に答える
3

android-screenshot-libraryが役立つかもしれません。しかし、彼らの使用ページでは、(Android SDKから)adbで開始されたネイティブサービスが必要であると書かれています。

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

于 2012-10-31T18:00:40.337 に答える
0

Androidでは別のアプリのフレームバッファにアクセスできないと思います。これはAndroidのセキュリティの一部にすぎません。各アプリは独自のリソースを保持する必要があります。

アプリのスクリーンキャプチャを本当に取得する必要がある場合は、ネイティブのスクリーングラブ「ジェスチャー」を使用することをお勧めします。たとえば、Nexus 7の場合、「...電源ボタンと音量小ボタンを同時に約2秒間押し続けます」。

グーグル検索は通常あなたのデバイスでトリックを見つけるでしょう。

于 2012-11-21T20:20:03.437 に答える