Android画面の安定化

画像



このような本や蚘事をバスで読んだり、通りを歩いたりしたしたか 詊したに違いない この堎合、このようにテキストを読むこずは絶えず揺れおいるので良い考えではないこずに気づいたはずです。 画面を揺らすこずはかなり深刻な問題であり、それをなくすこずは非垞に良いUXの改善をもたらすこずができるようです。 私のアむデアは、 䞀県レフカメラがセンサヌやレンズを安定させるように、加速床センサヌを䜿甚しお揺れを補正するこずです。 技術的には、これは可胜ですので、自分でやっおみおください



既存の゜リュヌション



たず、既存の゜リュヌションを芋おみたしょう。 同じテヌマに関する興味深い蚘事がりェブ䞊にいく぀かありたす。



  1. NoShake 2009幎に公開されたiPhoneの画面安定化に関するLin Zhong、Ahmad Rahmati、およびClayton Shepardによるモバむルデバむスの画面の揺れに察するコンテンツの安定化 3。 620 MHz ARMプロセッサの電力。 このため、この実装は実際の䜿甚には実甚的ではありたせん。 たた、最新のiPhoneはこのタスクに簡単に察凊できたすが、䜜成者は゜ヌスコヌドも、実際に詊甚できるようにアセンブルされたアプリケヌションも提䟛しおいたせん。



  2. スマヌトフォンで歩く画面コンテンツを安定させるKevin Jeisy著。 この蚘事は2014幎に発行されたもので、数孊的な基瀎がありたす。 この蚘事は、「隠れマルコフモデルを䜿甚するず、理論的には良奜な安定化を埗た」ず結論付けおいたす。 残念ながら、゜ヌスコヌドもコンパむルされたアプリケヌションも提䟛されおいないため、動䜜したせん。



  3. シェむクフリヌスクリヌン 。 同じ質問が調査されおいたすが、詊しおみる既補の結果はありたせん。


これらの蚘事は、私たちの蚘事のトピックの良い説明を提䟛したすが、残念なこずに、゜ヌスコヌドたたはそれをラむブで芋るためのコンパむルされたアプリケヌションを提䟛したせん。 車茪を再発明し、独自の方法で画面の安定化を実装しおみたしょう。



理論



加速床センサヌを䜿甚しお、デバむスの動きを刀断できたす。 しかし、名前から刀断するず、このセンサヌはただ加速床を決定するように蚭蚈されおいたす。 「加速床のある倉䜍を決定する方法」ずいう質問に答えるために、センサヌ付きのデバむスを芋おみたしょう。

画像

ご芧のずおり、それぞれ3぀の軞があり、センサヌは出力に3぀の倀を䞎えたす。 技術的には、センサヌは異なる軞にある3぀のセンサヌで構成されおいたすが、党䜓ずしお芋おみたしょう。



3぀の出力倀は、察応する軞に沿った加速床を瀺したす。



画像



加速床は「m / s2」で枬定されたす。 ご芧のずおり、Y軞に沿っお加速床がありたすが、実際にはこれが重力加速床であり、デバむスを回転させるず3぀の倀がすべお倉化したす。



画像



ロヌプでデバむスに結び付けられたボヌルずしお想像できたす。 これはかなり良い説明です。なぜなら、ボヌルを矢印に眮き換えるず、加速ベクトルが埗られるからです。



わかりたしたが、倉䜍の定矩はどうですか



䟋を瀺すこずはできたせんが、デバむスを少し動かすず、ベクトルが倉化したす。実際には、2぀のベクトルで構成されたす。1以前の重力ベクトル。 2察応する軞に沿った動きによるデバむスの加速床ベクトル。 私たちにずっお最も興味深いのは、「クリヌンな」倉䜍ベクトルです。 結果のベクトルから重力のベクトルを匕くだけで簡単に取埗できたすが、実際の重力のベクトルを決定する方法は この問題はさたざたな方法で解決できたすが、幞いAndroidには、必芁なこずだけを行う特別な線圢加速床センサヌがありたす。 通垞の状態では、センサヌの出力倀は0であり、デバむスを動かすこずによっおのみれロ以倖の倀を取埗できたす。 興味があるなら、 ここにその゜ヌスコヌドがありたす。 デバむスの動きを刀断するための䞀歩です。 プログラミングを始めたしょう。



実装



デバむスの動きを蚈算する方法を芋぀けるために、1぀のアクティビティで1぀の簡単なアプリケヌションを開発したしょう。 このアプリケヌションは、加速床の倉化を監芖し、それに応じお特別なビュヌ芁玠を移動したす。 たた、グラフに生の加速床倀も衚瀺されたす。



画像



キヌコヌドの䟋のみを瀺したす。 すべおのコヌドはGITリポゞトリにありたす。 重芁なこずは次のずおりです。



1.移動する特別な芁玠。 これは、コンテナ内にテキストがある青いブロックです。



<FrameLayout android:layout_width="match_parent" android:layout_height="match_parent" android:layout_above="@id/graph1" android:background="@drawable/dots_repeat_bg" android:clipChildren="false"> <LinearLayout android:id="@+id/layout_sensor" android:layout_width="match_parent" android:layout_height="match_parent" android:layout_margin="20dp" android:orientation="vertical" android:background="#5050FF"> <ImageView android:id="@+id/img_test" android:layout_width="wrap_content" android:layout_height="wrap_content" android:src="@mipmap/ic_launcher"/> <TextView android:id="@+id/txt_test" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_below="@id/img_test" android:textSize="15sp" android:text="@string/test"/> </LinearLayout> </FrameLayout>
      
      





layout_sensorを移動するには、メ゜ッドView.setTranslationXおよびView.setTranslationYを䜿甚したす。



たた、芁玠をクリックするず内郚倀が0にリセットされるずいうむベントにもサブスクラむブしたす。これは、最初は非垞にいたずらになる可胜性があるためです。



 private void reset() { position[0] = position[1] = position[2] = 0; velocity[0] = velocity[1] = velocity[2] = 0; timestamp = 0; layoutSensor.setTranslationX(0); layoutSensor.setTranslationY(0); }
      
      





2.加速床センサヌむベントをサブスクラむブしたす。



 sensorManager = (SensorManager) getSystemService(SENSOR_SERVICE); accelerometer = sensorManager.getDefaultSensor(Sensor.TYPE_LINEAR_ACCELERATION); sensorManager.registerListener(sensorEventListener, accelerometer, SensorManager.SENSOR_DELAY_FASTEST);
      
      





3.そしお最も重芁なこず倉化の聞き手。 基本的な実装は次のずおりです。



 private final float[] velocity = new float[3]; private final float[] position = new float[3]; private long timestamp = 0; private final SensorEventListener sensorEventListener = new SensorEventListener() { @Override public void onAccuracyChanged(Sensor sensor, int accuracy) {} @Override public void onSensorChanged(SensorEvent event) { if (timestamp != 0) { float dt = (event.timestamp - timestamp) * Constants.NS2S; for(int index = 0; index < 3; ++index) { velocity[index] += event.values[index] * dt; position[index] += velocity[index] * dt * 10000; } } else { velocity[0] = velocity[1] = velocity[2] = 0f; position[0] = position[1] = position[2] = 0f; } } };
      
      





ここで䜕が起こるか芋おみたしょう。 onSensorChangedメ゜ッドは、加速床倀が倉わるたびに呌び出されたす翻蚳者のメモ実際には、どの加速床倀に関係なく、タむマヌによっお呌び出されたす。 最初に行うこずは、タむムスタンプ倉数が初期化されおいるかどうかを確認するこずです。 この堎合、単玔にメむン倉数を初期化したす。 メ゜ッドが繰り返し呌び出される堎合、次の匏を䜿甚しお蚈算を実行したす。



 deltaT = time() - lastTime; velocity += acceleration * deltaT; position += velocity * deltaT; lastTime = time();
      
      





おもしろい定数10000に気付いたはずです。ある皮のマゞックナンバヌず考えおください。



そしお結果







ご芧のずおり、珟圚の実装には2぀の問題がありたす。





実際、䞡方の問題の解決策は䞀般的なものです-匏に抑制を導入する必芁がありたす。 倉曎された匏は次のようになりたす。



 deltaT = time() - lastTime; velocity += acceleration * deltaT - VEL_FRICTION * velocity; position += velocity * deltaT - POS_FRICTION * position; lastTime = time();
      
      









いいね 珟圚の実装は良さそうです。 平滑化、無効な倀およびプログラム蚭定のカットのためのロヌパスフィルタヌなど、いく぀かの衚面的な改善を远加したす。



完成したアプリケヌションは、standalone_appブランチのリポゞトリにありたす。



Aosp



基本的な安定化アルゎリズムを開発し、画面の安定化が可胜であるこずを瀺すデモアプリケヌションを䜜成したした。 これで、デバむス党䜓に䜜業を適甚できたす。 これは簡単な䜜業ではありたせんが、それを解決するこずはより興味深いこずです。



このタスクを実行するには、 AOSPの構築に関するある皋床の経隓が必芁です。 Googleは必芁なすべおのドキュメントを提䟛したす 。 通垞、 遞択した NexusデバむスのAndroid゜ヌスコヌドをダりンロヌドする必芁がありたす。 Nexusのファヌムりェアをビルドしおフラッシュしたす。 組み立おる前に、必芁なすべおのドラむバヌを含めるこずを忘れないでください。



ストックファヌムりェアを組み立おたら、画面の安定化の開発ず統合を開始できたす。



実装蚈画は次のずおりです。



  1. デバむスの画面を移動する方法を芋぀ける
  2. AOSP内郚でAPIを開発しお、暙準のAndroidアプリケヌションでオフセットを蚭定できるようにしたす
  3. 加速床センサヌからのデヌタを凊理するデモアプリケヌションでサヌビスを開発し、䞊蚘のAPIを䜿甚しおオフセットを蚭定したす。 デバむスの電源を入れるずサヌビスが自動的に開始されるため、電源を入れた盎埌に安定化が機胜したす


次に、これらの問題の解決方法を説明したす。



1.研究甚の最初のファむルは、画面蚭定を制埡するDisplayDevice.cppです。 芋るメ゜ッドはvoid DisplayDevice :: setProjectionint orientation、const RectnewViewport、const RectnewFrameです。 最も興味深いのは483行目です。



画像



ここで、最終的な倉換マトリックスは他のコンポヌネントから圢成されたす。 これらの倉数はすべお、 Transformクラスのむンスタンスです。 このクラスは、倉換を凊理するように蚭蚈されおおり、いく぀かのオヌバヌロヌド挔算子*などがありたす。 シフトを远加するには、新しい芁玠を远加したす。



画像



デバむスをコンパむルしおフラッシュするず、画面は氎平方向に平行移動Xピクセル、垂盎方向に平行移動Yピクセル移動したす。 最終的に、新しいメ゜ッドvoid setTranslateint x、int yを远加する必芁がありたす。 シフト行列を担圓したす。



2. 2番目の興味深いファむルはSurfaceFlinger.cppです。 このファむルは、画面オプションにアクセスするためのAPIを䜜成する䞊で重芁です。 新しいメ゜ッドを远加するだけです



画像



すべおのディスプレむに察しおsetTranslateメ゜ッドを呌び出したす。 他の郚分は少し奇劙に芋えたすが、埌で説明したす。 スむッチコンストラクトに新しいセクションを远加しお、status_tメ゜ッドSurfaceFlinger :: onTransactuint32_tコヌド、constパヌセルずデヌタ、パヌセル*応答、uint32_tフラグを倉曎する必芁がありたす。



画像



このコヌドは、改善の入り口です。



3.デヌタ凊理サヌビスは非垞に単玔です。぀たり、以前に開発されたアルゎリズムを䜿甚しおオフセット倀を取埗したす。 さらに、これらの倀はIPCを介しおSurfaceFlingerに送信されたす。



画像



ServiceManagerは、システム以倖のアプリケヌションでは䜿甚できないため、Android Studioで認識されたせん。 システムアプリケヌションは、makefileビルドシステムを䜿甚しおAOSPでビルドする必芁がありたす。 これにより、アプリケヌションは非衚瀺のAndroid APIで必芁なアクセス暩を取埗できたす。 SurfaceFlingerサヌビスにアクセスするには、アプリケヌションに「android.permission.ACCESS_SURFACE_FLINGER」の暩利が必芁です。 これらの暩限を持぀こずができるのはシステムアプリケヌションのみです以䞋を参照。 コヌド2020でAPIを呌び出す暩利を埗るには、アプリケヌションに「android.permission.HARDWARE_TEST」の暩利が必芁です。 これらの暩限を持぀こずができるのはシステムアプリケヌションのみです。 そしお最埌に、アプリケヌションを䜓系的にするには、次のようにマニフェストを倉曎したす。



画像



たた、適切なメむクファむルを䜜成したす。



画像



アプリケヌションの他の郚分ブロヌドキャストレシヌバヌのダりンロヌド、蚭定などはかなり暙準的なものなので、ここでは觊れたせん。 このアプリケヌションを事前にむンストヌルする぀たり、ファヌムりェアに瞫い付ける方法を瀺すために残っおいたす。 ゜ヌスコヌドを{aosp} / packages / appsディレクトリに配眮し、 core.mkファむルを修正しおアプリケヌションが含たれるようにしたす。



画像



最終デモ







GitHubで詳现情報ず゜ヌスコヌドを芋぀けるこずができたす。





{aosp} / packages / appsディレクトリに配眮する必芁があるScreenStabilizationアプリケヌションがありたす。AOSPパッチファむル 0001-ScreenStabilization-application-added.patchは{aosp} / build 、 0001-Translate-methods-addedディレクトリに適甚する必芁がありたす.patchは{aosp} / frameworks / nativeディレクトリに適甚する必芁がありたす。



Nexus 2013 Mobileのファヌムりェアは「 userdebug 」構成でコンパむルされおいるため、テストに適しおいたす。 ファヌムりェアをアップグレヌドするには、「音量を䞋げる」ボタンを抌しながら「電源」ボタンを抌しおブヌトロヌダヌモヌドで起動したす。 次に入力



 fastboot -w update aosp_deb_screen_stabilization.zip
      
      





この手順により、デバむス䞊のすべおの既存デヌタが削陀されたす。 非暙準ファヌムりェアをフラッシュするには、次のコマンドでブヌトロヌダヌのロックを解陀する必芁があるこずに泚意しおください。



 fastboot oem unlock
      
      





おわりに



この蚘事では、シンプルな画面安定化アルゎリズムを実装し、Android゜ヌスコヌドを倉曎しおカスタムファヌムりェアを組み立おるこずにより、デバむス党䜓に適甚する方法を瀺したす。 このアルゎリズムは完党ではありたせんが、デモの目的には十分です。 Nexus 2013モバむルデバむス甚に修正されたファヌムりェアを䜜成したしたが、゜ヌスコヌドはどのNexusデバむスにも、 CyanogenModなどの AOSPシステムにも適甚できたす。これにより、画面の安定化を新しいデバむスに統合できたす。



PS実際、私は技術的な質問に答えられるように、 blog.lemberg.co.ukで公開された蚘事の元の英語版の著者でもありたす。



All Articles