masaibarの雑記

胃腸は弱いが肉は好き

Huawei社製端末の「保護されたアプリ」設定画面をこじ開ける

はじめに

近頃値段の割に高性能とうことでHuawei製のAndroid端末が多く出回っております。 私自身、HuaweiのGR5という端末を購入したのですが数々のメーカー独自の素敵設定があるお陰で購入当初は苦労しました。 そんな素敵設定の中の一つに「保護されたアプリ」という項目があります。 これは保護されていないアプリに関しては、画面ロック時に問答無用でプロセスを殺すというオチャメな機能です。

www.sim-jozu.net

大概のユーザーはこのような設定があることをつゆ知らず、LINEやGmailが届かなくなったと騒ぎ、私の個人開発しているアプリでも「いきなり動かなくなったぞ、早く改善しろ」という温かいメッセージをいただく度にggrkという言葉を飲み込んでこの機能の事を説明して設定を見直してもらっております。

流石にメーカー側も問い合わせが多かったのか、LINE等のメジャーどころに関しては最近の端末ではデフォルトで保護されているアプリに追加しているようですが、殆どのアプリはそこまで特別待遇をしてもらえるわけではありません。

そこで、今回ご紹介するのはこの設定画面を直接開くためのコードです。 これによってHuawei社製端末の場合のみ設定を案内することで、問い合わせ件数を減らせないかと思い現在組み込み実装中です。

実装

簡単に説明をするとhasProtectedAppSetting()で設定画面の有無を確認後、存在していた場合にのみopenProtectedSettings()を呼ぶことで設定画面を開いてくれます。 ※試験できる実機が手元のGR5しかないので全てのHuawei端末で正しく動く保証はありません。

public class HuaweiUtil {

    private static final String PACKAGE_NAME_HUAWEI_SYSTEM_MANAGER = "com.huawei.systemmanager";
    private static final String ACTIVITY_NAME_HUAWEI_PROTECT_ACTIVITY =
            ".optimize.process.ProtectActivity";

    private Context mContext;

    public HuaweiUtil(Context context) {
        mContext = context;
    }

    public boolean hasProtectedAppSettings() {
        Intent intent = new Intent();
        intent.setClassName(
                PACKAGE_NAME_HUAWEI_SYSTEM_MANAGER,
                String.format("%s%s",
                        PACKAGE_NAME_HUAWEI_SYSTEM_MANAGER, ACTIVITY_NAME_HUAWEI_PROTECT_ACTIVITY)
        );

        List<ResolveInfo> resolveInfos = mContext.getPackageManager()
                .queryIntentActivities(intent, PackageManager.MATCH_DEFAULT_ONLY);

        return resolveInfos.size() > 0;
    }

    public void openProtectedSettings() {
        try {
            String cmd = String.format(
                    "am start -n %s/%s",
                    PACKAGE_NAME_HUAWEI_SYSTEM_MANAGER,
                    ACTIVITY_NAME_HUAWEI_PROTECT_ACTIVITY
            );

            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1) {
                cmd = String.format("%s --user %s", cmd, getUserSerial());
            }

            Runtime.getRuntime().exec(cmd);
        } catch (IOException ignored) {
        }
    }

    private String getUserSerial() {
        Object userManager = mContext.getSystemService("user");
        if (userManager == null) {
            return "";
        }

        try {
            Method myUserHandleMethod =
                    android.os.Process.class.getMethod("myUserHandle", (Class<?>[]) null);
            Object myUserHandle =
                    myUserHandleMethod.invoke(android.os.Process.class, (Object[]) null);
            Method getSerialNumberForUser =
                    userManager.getClass()
                            .getMethod("getSerialNumberForUser", myUserHandle.getClass());
            long userSerial = (Long) getSerialNumberForUser.invoke(userManager, myUserHandle);

            return String.valueOf(userSerial);

        } catch (NoSuchMethodException | IllegalArgumentException |
                InvocationTargetException | IllegalAccessException ignored) {
        }
        return "";
    }
}

おわりに

実際の設定値の取得方法まではわからない(多分外部アプリに対して公開はされていない)ため、設定済みのユーザーにも案内してしまう可能性が出てきてしまうものの、設定画面を直接開いて設定を促せることによって苦しむユーザーと問い合わせ件数を減らせるのではないでしょうか。

また、自分はあまりスマホに詳しくないのだというユーザーの皆様につきましては、不具合かなと思ったらとりあえず価格コムの該当端末に関する口コミを確認すると同じことで苦しんでいる人と解決方法が見つかるやもしれませんので一度ご確認をオススメしますし、調べずに問い合わせるにしても高圧的な態度で来られるとこちらも人間なので辛いです。

ちなみに買った端末はこちら。 購入当時スペックの割に安かったし指紋認証もあって値段相応の満足はさせてもらいました。

上述の「保護されたアプリ」に加え、ロック画面に通知が出なかった(有料アプリでカバー)り、未だに5.1からアップデートされる気配がないのでそろそろ買い替えたい所存ですが。

今もしHuawei端末を買うのならP10 Liteの評判が良さそうです、同僚も買ってました。

参考

stackoverflow.com