AndroidデバイスのAPIの秘密。 Yandexレポート

Android開発の主な課題の1つは断片化です。 ほとんどすべてのメーカーがAndroidをニーズに合わせて変更しています。 開発者のAndrey Makeevは、ベンダーの実装と元のAndroidオープンソースプロジェクトの違いをリストしました。 レポートから、さまざまなデバイスのファームウェアの個々の機能を活用する方法を学ぶことができます。





-私は学校からプログラミングをしてきましたが、Android向けに3年間開発しています。 これらのうち、私は1年間Yandexで過ごし、LauncherやPhoneなどのプロジェクトに参加しました。







AndroidデバイスのAPIの断片化が、プラットフォーム開発者と携帯電話の開発者の観点から、外部、アプリケーション開発者、内部の両方からどのように見えるかについてお話したいと思います。



レポートは2つの部分で構成されています。 最初に、APIが外部で断片化される方法について説明しましょう。 次に、コードを確認します。抽象的な電話の独自の機能がどのように実現され、開発がどのように構築されるかを確認します。



APIの断片化は、デバイスを断片化できるパラメーターの1つです。 最も明白で最も簡単なのは、Android SDKによる断片化です。Androidの開発の最初の数日から、文字通り断片化が発生しています。 表示されたAPIのバージョンとバージョン、削除されたバージョン、バックアップされたバージョン、および使用可能なバージョン、および既に削除されたバージョンはわかっています。 原則として、Googleのさまざまなサポートライブラリを使用して生活を簡素化します。 すでに多くのことが行われています。











コードでは、次のようになります。現在のSDKのバージョンに応じて、一部の機能をオンにし、一部をオフにします。 いずれかを使用する場合、通常は同じですが、内部で行われます。



このタイプのフラグメンテーションには焦点を合わせません。 短所は誰もが知っています-少なくともアプリケーションをテストするために、さまざまなバージョンのデバイス全体を保持する必要があります。 さらに、追加のコードを書く必要があります。 これは、Android向けの開発を始めたばかりのときに特に不便であり、突然判明しました。古いデバイスをサポートするには、2、3年前に何があったかを知る必要があります。 肯定的な側面:APIの開発、技術の進歩、Androidの新規ユーザーの獲得、開発者とユーザーの両方にとってより便利になっています。



これをどのように使用しますか? また、ライブラリを使用しており、古いバージョンのサポートを拒否した場合は非常に満足しています。 これを一年以上やっているみんなの人生には、こんな瞬間があったと思う。 これはただの幸せです。 これは明白で単純なフラグメンテーションオプションです。 次はAndroidタイプのフラグメンテーションです。 それらのいくつかがあります。 Android TVはそれ自体を語っています。AndroidAutoは主にカーラジオ、Android Things-IoTおよび同様の組み込みデバイスを対象としています。 Wは、Android向けの以前のAndroidウォッチであるWear OSです。 これが開発者の側からどのように見えるかを検討しようとします。 そして、最も興味深いことに、内部からどのように見えるかを考えてみましょう。







developer.android.comから2つの例を取り上げます。 1つはWear OSです。 アプリケーションを作成するには何が必要ですか? compileOnly依存関係をbuild.gradleに追加し、マニフェストに2行追加します:uses-feature android.hardware.type.watchおよびuses-library。これは、接続したライブラリと同じパッケージ名に対応します。







どうすれば実装できますか? アクティビティを作成します。この場合のみ、操作に使用される標準のアクティビティを使用せず、複合アクティビティも使用せず、WearableActivityを使用し、それに固有のメソッド(この場合はsetAmbientEnabled())を呼び出します。 したがって、compileOnly依存関係があります。つまり、アプリケーションの過程には入りません。 Uses-libraryは、明らかに、OSにこれらのクラスとこのコードをデバイスのランタイムで使用するように強制し、使用する新しいクラスを強制します。







Android Things APIは実質的に違いはありません。 uses-featureは使用せず、uses-library、compileOnly-dependencyのみを規定しています。







アクティビティを作成します。この場合、それはAndroid Things APIのPeripheralManagerクラスに固有のものです。 GPIOをポーリングし、誓約しようとしています。







このようなアプリは携帯電話でどのように動作しますか? 2つのオプションがあります。







uses-library android:required =” true”を指定した場合、アプリケーションをインストールするためのPackageManagerの必須要件を満たしていなかったため、基本的にインストールを拒否します。 android:required =” false”を指定した場合、アプリケーションはインストールされますが、PeripheralManagerクラスにアクセスしようとすると、標準のAndroidにはそのようなクラスがないため、NoClassDefFoundErrorが発生します。



これからの結論は何ですか? compileOnly依存関係は、アセンブリ中に接続するためにのみ接続します。使用するクラスはデバイス上で待機しており、マニフェストの特定の行を使用して接続されます。 Google Playでこのアプリケーションを配布できるデバイスまたは配布できないデバイスを区別するために、より頻繁に必要となる機能を規定する場合があります。



この種の断片化のマイナス面を特定することはできませんでした。 開発した人だけが、電話では遭遇しなかった完全に理解できない馴染みのないバグにどのように遭遇したかについて多くの話をします。 良い面は、これらは追加の市場、追加のユーザー、追加の経験であり、常に良いことです。



どのように作業するのですか? さらにアプリケーションを作成します。 一般的な推奨事項は、すべてのタイプのAndroid用に複数のバージョンのアプリケーションを作成することですが、それでも異なるバージョンを作成することです。 Android Thingsの場合、携帯電話に書かれているものはどれもふさわしくありません。 また、Android開発者、および場合によってはデバイス開発者が提供するライブラリを使用します。



次に研究されている断片化のタイプは、プロデューサーの断片化です。 ソースコードを受け取った各製造元-まれにAOSPであり、ハードウェア開発者によって何らかの形で修正されることが多い-に変更を加えます。 原則として、このタイプの断片化の悪影響については、Google Playでの否定的なレビューからです。誰かが何かを壊したためです。 または、特定のデバイスでのみ突然何かが理解できない方法でクラッシュした場合、クラッシュ分析からこれを学習します。 最良の場合、特定のデバイスでテストするときに何かがうまくいかなかった場合、QAからこれを学習します。







このテーマについては、開発ランチャーから素晴らしいストーリーがあります。 アクティビティが全画面に拡大されず、お気に入りのデフォルトの壁紙がまったく表示されないというバグレポートを受け取りました。 デコードされず、空のウィンドウが表示されました。 再現するデバイスすらありませんでした。 画面に引き伸ばすことで、機能しないローエンドデバイスを見つけることができ、Androidを使用してすべてを簡単に修正できました。マニフェストでresizeableActivity =” true”。 壁紙を使用すると、すべてがはるかに複雑になりました。 約2日間、連絡を取り、より詳細な情報を取得しようとしました。 最終的に、複数のデバイスで、プログレッシブjpegをデコードするコーデックにバグが実装されていることがわかりました。複数の圧縮アルゴリズムが互いの結果に使用された場合です。 この場合、apk自体にプログレッシブ方式でエンコードされた壁紙を配置する場合、アプリケーションをビルドするときにビルドをファイルするリントチェックを記述しました。 すべての壁紙を再コーディングし、バックエンドで状況を繰り返しました。これにより、残りの壁紙セットが配布され、すべてがうまく機能します。 しかし、それは約2日間の手続きを要しました。







コードではこのように見えます。 不快ですが、残念ながら、そのように。 通常、これらの行は長いデバッグ後に表示されます。







APIが壊れてアプリケーションが原則的に動作しないようにするために、Googleはどのような保証を提供しますか? まず、CDDがあります。CDDには、何が可能か、何が変更できないか、何が後方互換性があり、何がそうでないかが記述されています。 これは、一般的な推奨事項が記載された数十ページのドキュメントです。もちろん、すべてのケースをカバーするわけではありません。 より多くのケースをカバーするために、CTSがあります。CTSは、電話がGoogleから証明書を受け取り、Googleサービスを使用できるようにするために渡す必要があります。 これは約350,000の自動テストのセットです。 CTS Verifierもあります。これは、一連のチェックを行うために携帯電話に置くことができる通常のAPKです。 ちなみに、手で携帯電話を購入すると、そのように確認できます。



Trebleの出現により、VTSプロジェクトが登場し、低レベルの開発者の可能性が高くなりました。 Project Trebleで始まるドライバーAPIをチェックし、バージョン管理され、同様のテストを受けます。 さらに、携帯電話の開発者自身も、Androidアプリケーションをうまく動作させることを望んでいる健康な人ですが、これはまさしく希望です。 マイナス面は、アプリケーションがデバイスで起動されるまで予測できない予期しないバグが発生することです。 繰り返しますが、APIの異なるバージョンに加えて、それらをチェックするために異なるメーカーの追加のデバイスもあるという事実に加えて、購入を余儀なくされています。



しかし、肯定的な側面があります。 少なくとも、メーカーが最も頻繁に実装する機能はAndroid自体に含まれます。 指紋で画面のロックを解除できるデバイスよりも後に標準の指紋APIが登場したことを覚えている人もいるかもしれません。 現在、XDA Developersによると、Android APIは顔のカメラを使用してロックを解除することも望んでいますが、これはまだ正確ではありません。 私たちはあなたと一緒にこれについて知るでしょう。



さらに、デバイス開発者自身も、非標準のAPIを作成するときに、通常の開発者向けにAPIを操作するためのライブラリを公開できます。 これまでにこれをやったことがない場合は、アプリケーションの使用統計を見て、最も人気のあるメーカーを確認し、そのサイトの開発者ポータルを調べることをお勧めします。 多くの人が、興味深いハードウェア機能、セキュリティ機能、クラウドサービス、またはその他の興味深いAPIを持っていることに喜んで驚かれると思います。 そして、一見すると個々のデバイスに個々の機能を書くことはワイルドに思えますが、デバイスに加えて、さらに小さなプロセッサーも製造しています。 たとえば、Qualcommには、カメラからの画像を認識するための素晴らしいハードウェアアクセラレーションがあり、非常に使用できます。



したがって、このタイプのフラグメンテーションからも、誰でも何らかの利点を得ることができます。 これで何をしていますか? バグを報告したり、デバイス開発者やAndroid開発者にバグレポートを送信したりすることは決してありません。 CTSテストを作成する価値のあるAPIが破損した場合、そのAPIが作成され、そのような前例があったため、APIの信頼性が向上するためです。



Androidを学び、メーカーが提供するものを学び、彼らに誓うのではなく、協力してください。



内部からはどのように見えますか? 携帯電話に固有の機能を実装し、通常のAndroidアプリケーションからこのAPIを使用するにはどうすればよいですか?







ちょっとした理論。 Android開発者自身が内部AOSPデバイスをどのように説明していますか? 最上位のレイヤーは、ユーザーまたは電話自体の開発者によって作成されたアプリケーションであり、高い権限を持たず、標準APIのみを使用します。 これはフレームワークです。これらは、Activity、Parcelable、Bundleなど、アプリケーションの一部ではないクラスです。システムの一部であり、フレームワークと呼ばれます。 デバイス上で利用可能なクラス。 次はシステムサービスです。 これがシステムに接続するものです。ActivityManagerService、WindowManagerService、PackageManagerServiceは、システムとの内部対話を実装します。



次はハードウェアアブストラクションレイヤーです。これはドライバーの最上位レイヤーで、画面に表示したり、Bluetoothなどとやり取りしたりするためのすべてのロジックが含まれています。 カーネルは、ドライバー、システム管理の最下層です。 核心とは何かを知っている人は、言う必要はありませんが、長い間話すことができます。







デバイス上ではどのように見えますか? 当社のアプリケーションは、標準フレームワークと相互作用するだけでなく、メーカーのカスタムフレームワークとも相互作用できます。 また、このフレームワークを介して、カスタムサービスと通信できます。 これらがハードワイヤードまたは低レベルの機能である場合、HALはそれらのために、必要に応じてカーネルレベルのドライバーでさえ記述されます。







機能をどのように記述しますか? 計画は簡単です。ほとんどのAndroid開発者が作成したライブラリとそれほど変わらないフレームワークを作成する必要があります。皆さんはこれを知っていると思います。 システムサービスを記述する必要がありますが、これは通常のアプリケーションであり、システム内であまり一般的ではない一連の権限を持っています。 また、必要に応じて、HALを記述できますが、これは省略します。 カーネルレベルで独自のドライバーを作成できますが、現在は検討しません。 そして、これらすべてを使用するクライアントアプリケーションを作成します。







システムとやり取りするためには、何らかの種類のコントラクトを作成する必要があります。これには、すでにAIDLインターフェイスの優れたメカニズムがあります。 これは、システムが拡張可能な追加のクラスを生成するためのインターフェイスの一種にすぎません。このクラスを介して、アプリケーションとシステムサービス間のプロセス間通信が実行されます。







次に、このインターフェイスの実装を保持するフレームワークであるライブラリを作成し、すべての呼び出しをプロキシします。 興味があるなら、ActivityManager、PackageManager、WindowManagerはほぼ同じ方法で動作します。 ここで実装したロジックよりも少し多くのロジックがありますが、本質はそれだけです。







フレームワークを実装しました。システム側からデータを受信するシステムサービスを記述する必要があります。この場合、整数を送信および読み取ります。 クラスを作成し、前のスライドでAIDLから生成されたインターフェイスも拡張します。 値を書き込み、読み取り、セッター、ゲッターを書き込むフィールドを作成します。 唯一のことは、十分なロックがないことですが、スライドにあまり収まりませんでした。







さらに、このシステムサービスを利用できるようにするには、システムサービスマネージャーに登録する必要があります。この場合、通常のアプリケーションでは利用できないのと同じクラスです。 これは、システムパーティション内のプラットフォームに存在するユーザーのみが使用できます。 Application.onCreate()でサービスを登録し、作成したクラスの名前で利用できるようにします。



onCreate()を起動し、サービスをメモリにロードするには何が必要ですか? アプリケーションAndroidのマニフェストに次のように記述します:persistent =” true”。 これは、これが永続的なプロセスであり、システム機能を実行するため、常にメモリ内に存在する必要があることを意味します。







また、マニフェスト自体でandroid:sharedUserId(この場合はsystem)を指定できますが、さまざまなIDを使用できます。これにより、アプリケーションはシステム内でより広い権限を取得し、通常のアプリケーションでは利用できないさまざまなAPIやサービスと対話できます



この場合、たとえば、このようなものは使用しませんでした。







フレームワークを作成し、システムサービスを作成しました。 内部のメカニズムは省略しますが、これはやや複雑なトピックなので、別のレポートに値します。



フレームワークをアプリケーション開発者に提供する方法は? 2つの形式。 本格的なクラスを発行して、アプリケーションにコンパイルする本格的なライブラリを作成できます。すべてのロジックは、dexeの一部になります。



または、スタブクラスの形式でフレームワークを配布できます。これは、コンパイル中にのみ関係し、これらのクラスが、デバイス自体のAndroidのさまざまなバージョンの以前の例と同様に待機することを期待できます。 SDKの新しいバージョンをインストールする方法と同様に、誰もが知っている通常のMavenリポジトリまたはAndroid Studio sdkmanagerを介して配布できます。 どちらの方法がより便利かを言うのは困難です。 個人的にMavenを接続する方が便利です。







簡単なアプリケーションを作成しています。 おなじみの方法で、compileOnly依存関係を接続しますが、それがライブラリになりました。 作成し、デバイス上に置いたuses-libraryを規定しています。 Activityを作成し、これらのクラスにアクセスして、システムと対話します。 そのため、いくつかの追加デバイスへのデータ転送、追加のハードウェア機能など、あらゆる機能を完全に実装することが可能です。



したがって、すべての開発者は、デバイスの固有の機能を開発者が利用できるようにします。 これらは、パートナーのみに提供するプライベートAPIである場合があります。 パブリックなものや、開発者ポータルで見つけることができるものもあります。 そのようなことを実装する方法は他にもありますが、GoogleおよびAndroid開発者の間で主要な方法と考えられる方法を説明しました。



デバイス開発者を、アプリケーションを壊す人として扱うべきではありません。 これらは同じ開発者であり、ほぼ同じレベルで同じコードを記述します。 バグレポートを書いてください、彼らは本当に助けて、私はしばしばそれらを分析します。 より多くのアプリケーションを作成し、Androidとデバイス自体の両方が提供する機会を活用してください。 私はそれをすべて持っています。



All Articles