android の java.lang.VerifyError は悩ましい

先週やってた作業の中で突然androidアプリでjava.lang.VerifyErrorが出始めたケースがあった。結果から言うと根本原因はわからんかった。

解決方法としてはコールバック処理の一部のソースをリファクタリングしてメソッドとして外に移動 (Extract Method) させたら現象が消えたというていたらく。。。

何か作法としてあまりよくない書き方をしてたんだろうなとは思いつつも問題は解決せねばならぬ。

show must go on なのだ。。。

[android] androidxにプロジェクト移行したら、OssLicensesMenuActivity でエラー

調べたけどなかなかぴったり説明が出なかったので。

targetSdkVersion 27 を 28 にしてねwariningがよく出るようになってきたので 28にアップしたら、androidxにしなきゃダメみたいなメッセージが出てきたので、ライブラリの依存性をごりごり修正してたら、OSSライセンス一覧生成画面のところで以下のエラー

java.lang.IncompatibleClassChangeError: Class 'com.google.android.gms.oss.licenses.OssLicensesMenuActivity' does not implement interface 'androidx.lifecycle.LifecycleOwner' in call to 'androidx.lifecycle.Lifecycle androidx.lifecycle.LifecycleOwner.getLifecycle()' (declaration of 'androidx.lifecycle.LiveData' appears in ・・・

解決方法 以下をgradleに追加

implementation "androidx.appcompat:appcompat:1.1.0-rc01"

何も考えずにGlideを使う(Android)

取り急ぎ細部は考えずにRESTからのURLで画像を表示する。

public class ListRecycleViewAdapter extends RecyclerView.Adapter<ListViewHolder> {

    private List<InfoRowData> list;
    private Context context;


    public ListRecycleViewAdapter(Context context, List<InfoRowData> list) {
        this.context = context;
        this.list = list;
    }

    @NonNull
    @Override
    public ListViewHolder onCreateViewHolder(@NonNull final ViewGroup parent, int viewType) {
        View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.list_row, parent, false);
        return new ListViewHolder(view);
    }

    @Override
    public void onBindViewHolder(@NonNull final ListViewHolder holder, final int position) {
        //  非同期取得
        if (list.get(position).getLogoUri() != null) {
            String url = list.get(position).getLogoUri();
            Glide.with(context)
                    .load(url)
                    .placeholder(R.drawable.ic_default_icon)
                    .into(holder.LogoIcon);
        } else {
            Glide.with(context)
                    .load(R.drawable.ic_default_icon)
                    .placeholder(R.drawable.ic_default_icon)
                    .into(holder.LogoIcon);
        }
    }
}
public class DetailsFragment extends Fragment {

    @Nullable
    @Override
    public View onCreateView(@NonNull LayoutInflater inflater, @Nullable final ViewGroup container, @Nullable Bundle savedInstanceState) {

        View view = inflater.inflate(R.layout.fragment_details, container, false);

        ImageView iconView = view.findViewById(R.id.logoIcon);
        //  非同期取得
        if (data.getLogoUrl() != null) {
            String url = data.getLogoUrl();
            Glide.with(getContext())
                    .load(url)
                    .placeholder(R.drawable.ic_default_icon)
                    .into(iconView);
        } else {
            Glide.with(getContext())
                    .load(R.drawable.ic_default_icon)
                    .placeholder(R.drawable.ic_default_icon)
                    .into(iconView);
        }

    }
}

案件固有名詞をわざわざ除去するのは面倒だな。そういうツールも作るべきかね。

https://github.com/bumptech/glide/wiki

https://bumptech.github.io/glide/doc/getting-started.html

Android : GestureDetectorの非推奨コンストラクタについて

とりあえず少しずつでも見つけた支障のない技術Tipsは書いていこう。

GestureDetector(GestureDetector.OnGestureListener listener)は非推奨APIになった。
GestureDetector(Context context,GestureDetector.OnGestureListener listener)を使うようにする。

http://developer.android.com/intl/ja/reference/android/view/GestureDetector.html

古いGestureDetectorのコンストラクタを使うと、比較的新しいAndroid OSではジェスチャーの検出がまれにおかしくなるみたい(イベント抜け等)。
古めのAndroid OSで問題が出ず新しいAndroid OSでGestureDetectorを使うとタッチ検出がおかしいときは、contextを指定するだけで問題解決することもあるようだ。