3

解決方法がわからない興味深い状況に直面しています。ユーザーが Android for Work ユーザーとして初めてア​​プリにサインインするとき、アプリがデバイス マネージャーとして登録されていることを確認する必要があります。を呼び出しDevicePolicyManager#isAdminActiveてこれに該当するかどうかを確認し、 が返された場合はwithfalseを起動して、デバイス管理を有効にする Android コントロールを起動します。これが発生すると、アプリが再度起動されたとき (またはデバイス管理フローから戻ったとき) の値が再度チェックされます。ユーザーがデバイス管理を有効にしている場合、すべて問題なく、アプリはそのまま続行されます。Intentaction=DevicePolicyManager.ACTION_ADD_DEVICE_ADMINDevicePolicyManager#isAdminActive

興味深いことに、これは、ユーザーが最初にフローを通過したときに、期待どおりに機能します。残念ながら、再起動後、ユーザーがアプリを起動すると、デバイス管理がまだオンになっていることを確認しますDevicePolicyManager#isAdminActive。これは、デバイスのセキュリティ設定を調べることで確認されますDevicePolicyManager#isAdminActivefalseさらに悪いことに、デバイス管理を有効にしようとすると、次の例外が発生します。

W/DeviceAdminAdd: 管理者 ComponentInfo{com.mysoft.myapp/com.mysoft.core.receivers.MyAppAdminReceiver} をアクティブ化しようとして例外が発生しました java.lang.IllegalArgumentException: 管理者は既に android.os.Parcel.readException(Parcel.java: 1550) で android.os.Parcel.readException(Parcel.java:1499) で android.app.enterprise.IEnterpriseDeviceManager$Stub$Proxy.setActiveAdmin(IEnterpriseDeviceManager.java:867) で android.app.enterprise.EnterpriseDeviceManager.setActiveAdmin(EnterpriseDeviceManager) .java:720) com.android.settings.DeviceAdminAdd.addAndFinish(DeviceAdminAdd.java:346) で com.android.settings.DeviceAdminAdd$3.onClick(DeviceAdminAdd.java:313) で android.view.View.performClick(View) .java:5242) android.widget.TextView.performClick(TextView.java:10571) で android.view.View$PerformClick.run(View.java:21196) で android.os.Handler.handleCallback(Handler.java:739) で android.os.Handler.dispatchMessage(Handler.java:95) でandroid.os.Looper.loop(Looper.java:145) で android.app.ActivityThread.main(ActivityThread.java:6938) で java.lang.reflect.Method.invoke(Native Method) で java.lang.reflect. Method.invoke(Method.java:372) at ...java.lang.reflect.Method.invoke(Method.java:372) で呼び出し (ネイティブ メソッド) ...java.lang.reflect.Method.invoke(Method.java:372) で呼び出し (ネイティブ メソッド) ...

システム セキュリティ設定ページからデバイス管理を手動で有効にしようとしても、この例外が logcat コンソールに表示されるため、元のIntent形式が正しくないとは思いません。

ここで問題があります。Android デバイス管理 API を 1 回呼び出すと、デバイス管理者がアクティブ化されていないことがわかりますが、同じ API をもう一度呼び出すと、アクティブ化されていることがわかります。2 番目のエラーは実際には間違っていると思いますが、管理を有効にできないため、ユーザーはループに陥り、アプリを使用できません。

他の誰かがこのエラーに遭遇しましたか?もしそうなら、どのようにコーディングしますか?

4

1 に答える 1

2

の AOSP ソースを分析しDevicePolicyManagerService.javaました。この場合に失敗している関数は と呼ばれsetActiveAdmin()、アプリケーションがデバイス管理者として既に追加されていると主張するため、例外をスローしています。この例外はsetActiveAdmin、 への呼び出しがgetActiveAdminUncheckedLocked()有効なオブジェクトを返した後にスローされ、要求されたデバイス管理者がアクティブであることを示します。

final ActiveAdmin existingAdmin
    = getActiveAdminUncheckedLocked(adminReceiver, userHandle);
if (!refreshing && existingAdmin != null) {
    throw new IllegalArgumentException("Admin is already added");
}
if (policy.mRemovingAdmins.contains(adminReceiver)) {
    throw new IllegalArgumentException(
            "Trying to set an admin which is being removed");
}

ただし、この前に、次のDevicePolicyManager.isAdminActiveロジックを含むを既に呼び出しています。

return getActiveAdminUncheckedLocked(adminReceiver, userHandle) != null;

これで問題ありません。これはまさに私たちが望んでいるものです。ただし、これは AOSP コードです。影響を受けるデバイスには別の実装が存在する可能性があり、その実装では のロジックにエラーがあり DevicePolicyManager#isAdminActive()、呼び出しが true を返すはずのときに false を返している可能性があると理論付けました。

本番環境でこの状態をキャッチするための計測器をデプロイした後、この仮説が正しいことを確認しました。私のメトリクスから推測すると、 によって返される列挙されたアクティブな管理者のリストにあるにもかかわらずisAdminActive(X)、 によって返される値が false を返すような実装が Android デバイス人口に存在します。幸いなことに、これは一般的なケースではありませんが、存在します。これらの呼び出しに依存して、このシナリオに対してコードを強化するコーダーにアドバイスします。 XgetActiveAdmins()

于 2018-02-28T19:43:40.197 に答える