2015年12月22日火曜日

2015年12月21日月曜日

SharedPreferences 非推奨のMODE_WORLD_READABLEで読み込めない

突然おかしな現象に陥りました。
別のアプリのSharedPreferencesの値が正しく参照されないという現象に。
これが起こったのが一通りコード修正が終わり、手持ちの端末にインストールしてたところNexus9(Android6.0.1)だけ設定をいくら変えても反映されない状態に。

さすがに非推奨となっている内容をそろそろ使用をやめようと思ってはいるので、良い機会なので書き換えようかなと。

改めて調べてみると代替えとなるContentProviderが予想以上にリソースを消費しそうなところと、アクセスを頻繁に行うのには向かなさそうというところが引っかかってしまいました。

非推奨とならない実装方法もあるのかもしれませんが、結局手軽に扱えそうなものが判らないのでとりあえず現状がっどうなっているのか調べることにしました。

まず値を設定している側のアプリは全く問題なく動いています。見かけ上もデバッグログもとくに変なエラーは吐いていません。
読み込む側のアプリも同様にエラーなども見当たりません。

ただ、結果として値を参照する側が明らかに読み込めていません。

コードにデバッグログを仕込んだところパッケージマネージャで値の入っているアプリを取得してgetSharedPreferencesでSharedPreferencesを取得するところは処理がちゃんと通っていることを確認しました。
さらにその先のgetIntなども行えています。が、エラーはありませんが、どうも値が読み込めていないようです。

アプリ自体に問題はなさそうなのでアンインストールとインストールを繰り返してみたところ、設定が目で不思議な現象に気づきました。
通常アンインストールを行うとSharedPreferencesの設定値は消えるはずなのですが、これがどうも消えていない様子。
と、するとあり得るのはAndroidの機能としてインストール時にクラウドから設定値が復元されているのではないかと感じました。

試しにAndroidの設定のバックアップと復元の「自動的に復元する」をオフにしてアンインストールとインストールを行ったところ値がデフォルトに戻ったのを確認。さらにこの状態で設定した状況が反映されていました。

再度「自動的に復元する」を有効にして同様の事を行ったところ、設定が反映されなくなって今いました。
この状態でアプリ情報からアプリのストレージに保存されているデータを消去して設定を行ったところ、これもまた正しく動作し始めました。

原因は自動復元によってSharedPreferencesファイルが復元されていることが原因でした。

2015年12月13日日曜日

gmsのプラグイン?

アプリで不可解なエラーが出始めて色々と確認しています。

2015年12月5日土曜日

リスナー系の実装方法

~Listenerというクラスの実装方法は色々あると思いますが、主に利用しているパターンは2つのパターンです。

①無名クラスで実装する方法
②メインとなるクラスにimplementsで実装してしまう方法
他にもちゃんと名前を付けたクラスを定義して実装する方法もありますが使ったことはありません。

実際のコード(例ではシークバーを扱っています)は次のようになります。
①の例
public class ~Activity extends Activity {
    :
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        :
        seekBar~.setOnSeekBarChangeListener(
            new SeekBar.OnSeekBarChangeListener() {
                public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) {
                    //
                }
                public void onStartTrackingTouch(SeekBar seekBar) {
                    //
                }
                public void onStopTrackingTouch(SeekBar seekBar) {
                    //
                }
            }
        );
        :
    }
    :
}
②の例
public class ~Activity extends Activity
    implements SeekBar.OnSeekBarChangeListener {
    :
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        :
        seekBar~.setOnSeekBarChangeListener(this);
        :
    }
    :
    @Override
    public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) {
        //
    }
    @Override
    public void onStartTrackingTouch(SeekBar seekBar) {
        //
    }
    @Override
    public void onStopTrackingTouch(SeekBar seekBar) {
        //
        switch (seekBar.getId()){
            case R.id.seekBar~:
                break;
        }
    }
    :
}

好みもありますが、個人的には①のほうがスッキリしていてコードも見やすいので好きなのですが、複数シークバーが有るときにはどうしても助長に見えます。また無名クラスとはいえ内部でクラスが生成されているのも気になります。(Javaが実際にどのように動作しているのかは理解していませんが)
②の場合は一つの時には何も考えなくてもよいのですが、複数ある場合は引数のseekBarを見てどのseekBarなのか判断する必要があります。コードには条件分岐が必要になるので複雑になってしまいます。ただしクラスの生成が発生していない分、余計な生成時間やメモリーがなさそうです。

まだどちらが良い悪いという結論が出せていません。

2015年12月3日木曜日

Android Sturio 2.0 Preview

確か先々週あたりから表示されるようになっていて、先週アップデートしました。
古いプロジェクトを開くとビルドはできるようですが、gradle関連のファイルやソース内のエラーや警告表示があってとりあえず気づいた点を書いておきたいと思います。