読者です 読者をやめる 読者になる 読者になる

とりあえず移転してみました

ニュースねたや、IT系の記事を書いていくつもり・・・ですが、どうなるかわかりません。まあ、とりあえず やってみます。

AndroidStudioで色々とはまったので、まとめてみる。自己ログ

androidStudioで色々とはまってしまった。WEB上の情報も色々と見たのだけど、まとめておかないと後で大変そうだったので自己ログ。

事の始まり

メインのActivityから遷移して、次のActivityに移った時に、タブ付の表示にしてみることにした。
タブの配置にするには「TabHost」を使う方法があるのだけど、新しいAPIでは推奨されていない。「TabLayout」を使い「ViewPager」と「ViewPagerAdapter」で実現する方法がいいと。

f:id:imsdJava:20170330135640p:plain
Activity遷移イメージ

f:id:imsdJava:20170330135740p:plain
ActivityとViewPagerAdapterなどの関連図

まずは、タブを実装するActivityのレイアウトファイルに、TabLayoutとViewPagerを追加

<android.support.design.widget.TabLayout
        android:id="@+id/tab_layout"
        android:layout_width="match_parent"
        android:layout_height="wrap_content" />

    <android.support.v4.view.ViewPager
        android:id="@+id/view_pager"
        android:layout_width="match_parent"
        android:layout_height="match_parent" />

ViewPagerAdapterを使うために新しくクラスを作成し、FragmentPagerAdapterを継承する。

import android.support.v4.app.Fragment;
import android.support.v4.app.FragmentManager;
import android.support.v4.app.FragmentPagerAdapter;


public class ViewPagerAdapter extends FragmentPagerAdapter {
    public ViewPagerAdapter(FragmentManager fm) {
        super(fm);
    }

    @Override
    public Fragment getItem(int position) {
        Fragment fragment = null;

        switch (position) {
            case 0:
                fragment = rentFragment.newInstance("rent");
                break;
            case 1:
                fragment = srvFragment.newInstance("srv");
                break;
            default:
                break;
        }
        return fragment;
    }

    @Override
    public int getCount() {
        return 2;
    }

    @Override
    public CharSequence getPageTitle(int position) {
        CharSequence  charSequence = null;
        switch (position) {
            case 0:
                charSequence = "貸出";
                break;
            case 1:
                charSequence = "予約";
                break;
            default:break;
        }
        return charSequence;
    }
}

次に、タブを追加するクラスにタブのレイアウトなどを追加する。

TabLayout tabLayout = (TabLayout)findViewById(R.id.tab_layout);
        tabLayout.addTab(tabLayout.newTab());
        tabLayout.addTab(tabLayout.newTab());

        ViewPager viewPager = (ViewPager)findViewById(R.id.view_pager);
        viewPager.setAdapter(new ViewPagerAdapter(getSupportFragmentManager()));

        tabLayout.setupWithViewPager(viewPager);

タブレイアウトを追加し、ViewPagerにはViewPagerAdapterもセットする。
タブレイアウトに、ViewPagerを関連付けてタブとViewPagerが連動するようになる。

次に、タブとして表示されるFragmentを用意する必要がある。ここでは、rentFragmentとsrvFragmentとして指定してある。
Fragmentを作成するには、右クリック->Fragment->Fragment(Blank) で作成することができる。


f:id:imsdJava:20170331105217p:plain

XMLファイルも同時に作られるので、名前を指定すれば別々に用意する必要はない。
ただ、要らないメソッドとかがあるので、修正をしないと動かない。ちと面倒だけど一から作るよりはいい。

まずは、表示だけのテストを行いたいので、基本のFragmentだけあればいい。ところが・・・getSupportFragmentManager()が赤くなりエラーになっている。エラー内容をみる限り、そんなメソッドねえよということらしい。

Activityではなく、v7.app.AppCompatActivityを使えということで、importに追加

import android.support.v7.app.AppCompatActivity;

さらに継承の指定を、ActivityからAppCompatActivityに変更する必要がある。ここで、エラーがなくなりBuildできるようなったので、テストしてみる。

不明なエラー

ここからが実際の迷走の始まり。実行したところで、Activityが表示される時にアプリが落ちてしまう。エラーを見ると、以下の文でエラーになっているように見える。

protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

ここのsuper.onCreate(savedInstanceState);でエラーになるというのだけど、Activityが表示される際にonCreateが呼ばれる。その最初の1行目なので定型のようなもの。何も実行されていない。おかしい・・・

ネットで調べてみても、なかなか情報がない。AppCompatActivityが問題だというのはあるけど、解決策はActivityに変更するという方法ばかり、これではViewPagerが使えない。

海外のサイトでは、バージョンの話がされている。バージョンね・・・

AndroidStudioのバージョン関連

バージョンと言っても、沢山存在する・・・まずは、AndroidStudioのバージョン。それから、AndroidStudioは、Gradleの上で動作しているのでGradleのバージョンとBuiledバージョンも存在する。さらに、Androidプラグインバージョンも存在する。

さらに・・・APIのバージョン。コンパイルバージョン、supportライブラリのバージョン・・・

なんなんだ・・・

まずは、GradleとAndroidプラグインバージョンを調べてみる。File->ProjectStructureで表示される画面で確認できる

f:id:imsdJava:20170330143322p:plain

これは、変更された数字で、変更前はGradle2.2.1 androidプラグイン1.2.3という数字だった。この画面でも変更が出来る。海外のサイトの情報では、プラグインを2以上にしないとダメということ。単純に2以上を指定してもエラーになる。
Buildすらされなくなってしまう。

Gradleのバージョンもサイトを見る限り新しいバージョンがあるようなのだが・・・

https://jcenter.bintray.com/com/android/tools/build/gradle/

バージョンを変えてみたり、サイトで動いたバージョンなどを指定してもダメ。ここで、かなり時間をとられた。
バージョンについては、以下のサイトを見ないとダメだった・・・

Android Plugin for Gradle Release Notes | Android Studio

f:id:imsdJava:20170330144145p:plain

プラグインバージョンと関連するGradleバージョンも書かれているので、これに従ってバージョンを指定する。
Gradle2.13 androidプラグイン2.1.2という数字で落ち着いた。

これだけでは済まなかった。次に見ないといけないのは、コンパイルなどのバージョン。
GradleScriptsの中のbuile.gradle(Module:app)の内容を確認する。

android {
    compileSdkVersion 25
    buildToolsVersion "24.0.3"

    defaultConfig {
        applicationId "????"
        minSdkVersion 15
        targetSdkVersion 22
        versionCode 1
        versionName "1.0"
    }

minSdkVersionは、14以上を指定する必要があるとか、元々15に指定していた。compileSdkVersionは、25と新しいバージョンを指定。buildToolsVersionが問題のようで、ここを変更した。v7.app.AppCompatActivityを使うには、API24.2.0より上という情報があったので、24.0.3を指定。

色々とバージョンを変更してみるとBuildが通るようになった。エラーもなくなったので、なんとか動くようだ。
実際には、supportライブラリーのバージョンも関係するのかもしれない。一応コピペ。

dependencies {
    compile fileTree(dir: 'libs', include: ['*.jar'])
    compile 'com.android.support:appcompat-v7:25.2.0'
    compile 'com.google.android.gms:play-services:8.3.0'
    compile 'com.squareup.okhttp3:okhttp:3.6.0'
    compile 'com.android.support:support-v4:25.2.0'
    compile 'com.android.support:support-v13:25.2.0'
    compile 'com.android.support:design:24.2.0'
}

okhttp3は、http通信用なので通信しない場合は、必要なし。

さて、テストを実行してみると、エラーになってしまった・・・

エラー内容は・・・

JDKを1.8にしろと・・・

はい、すみません。してませんでした・・・

Javaのアップデートを実行する。JDKのパスも変更する。

テストの再実行・・・・・・あっさり動いた・・・なんだったんだ・・・
でも、表示だけなので、Fragmentの中身を実装しないと。

AppCompatActivityを使うだけで、こんなに大変だとは。AndroidStudioに関係するバージョンは、上げてしまうと今まで作成してプロジェクトがエラーになってしまうので、意識的に変えていなかった。これで、関係性がわかったけど、APIのバージョンを上げると、使っていたメソッドが非推奨になっていたりするので、大変なのだ。なんとかならんのかな~。