android studio開発で困ったことシリーズ

今まであったバグや「これ毎回調べてんなあ…」ってことの覚え書きです
特に注釈ない限り、android studio 3.0.1＋java 1.8.0

※「こうやったら動いた」程度のメモなのでもしかしたら間違った対処かもしれません。悪しからず
随時更新予定

#gradleビルド編
##Minimum supported Gradle version is 4.1. Current version is 2.14.1.
https://qiita.com/izuki_y/items/26e5735a26a3494b4833#errorminimum-supported-gradle-version-is
gradleのバージョンがあってないのであげれば解消する

##Error: '.' is not a valid file-based resource name character: File-based resource names must contain only lowercase a-z, 0-9, or underscore
https://teratail.com/questions/130852
ファイル名が不正ですよエラー
なぜか拡張子の前に```.```が二つあったので修正

##Manifest merger failed : uses-sdk:minSdkVersion 8 cannot be smaller than version 14 declared in library [com.google.android.gms:play-services:11.0.4]
https://qiita.com/naotsune/items/8a45fb5436b50d3fef56
minSdkVersionを上げろエラー
上げて解消

##Error:Execution failed for task ':approcessDebugGoogleServices'.
全文⬇︎

```
Error:Execution failed for task ':approcessDebugGoogleServices'.
>Please fix the version conflict either by updating the version of the google-services plugin (information about the latest version is available at https://bintray.com/android/android-tools/com.google.gms.google-services/) or updating the version of com.google.android.gms to 12.0.1.
```
FCMのパッケージをandroid studioの機能を使って追加したら発生
よくみたらappのbuild.gradleの

```
implementation 'com.google.firebase:firebase-messaging:11.0.4'
```
がエラーになってた。（android studioが自動で入れた部分）
言う通り12.0.1にそろえたら解決

##Error:Unable to find method 'org.gradle.api.artifacts.Configuration.defaultDependencies
全文⬇︎

```
Error:Unable to find method 'org.gradle.api.artifacts.Configuration.defaultDependencies(Lorg/gradle/api/Action;)Lorg/gradle/api/artifacts/Configuration;'.
Possible causes for this unexpected error include:<ul><li>Gradle's dependency cache may be corrupt (this sometimes occurs after a network connection timeout.)
```
言われるがままダウンロードしてみる
＞同じエラーが出る
＞https://stackoverflow.com/questions/37655814/gradle-sync-failed-unable-to-find-method
https://android.benigumo.com/20180121/build-environment-stable/
参考にbuild.gradleのバージョンをあげてみる（2.2.1 => 5.4.1）
＞解消

##Error:No such property: GradleVersion for class: JetGradlePlugin
###追記（2020/2/20）
https://cpoint-lab.co.jp/article/201908/11313/
によれば、gradleのバージョンに対してandroid studioのバージョンが低いことが原因のようです。
なので、

- android studioをアップデート
- gradleをダウングレード

のどちらかで解決するものと思われます。
特に事情がなければアップデートする方が良いかと。

###以前の作業録
https://stackoverflow.com/questions/53600179/errorno-such-property-gradleversion-for-class-jetgradleplugin
今度はダウングレードすると解決するらしい、、、
5.4.1 => 4.10.1にする
＞toolsがみつからないと言われる
＞https://developer.android.com/studio/releases/gradle-plugin.html#updating-gradle
の対応表を見つつ

```
- com.android.tools.build:gradle:3.4.1
+ com.android.tools.build:gradle:3.3.0
```
にする
＞まだ見つからないと言われる
＞https://stackoverflow.com/questions/46316213/errorcould-not-find-com-android-tools-buildgradle3-3-issue-raise-after-upgra
参考にPJルートのbuild.gradleにgoogle()を追加
＞ひとまず解消

##Error:Removing unused resources requires unused code shrinking to be turned on. 
https://stackoverflow.com/questions/52310841/removing-unused-resources-requires-unused-code-shrinking-to-be-turned-on
app.gradleの

```
- minifyEnabled false
+ minifyEnabled true
```
にしたら解決

#コンパイル編
##Error: Your project contains C++ files but it is not using a supported native build system.
cppを使ってるPJで発生。cppのコンパイラを入れる必要がある。
本来はcmakeが推奨なのだがエラーにより断念…

NDKをインストールした後、
https://qiita.com/kenmasu/items/598496840eef775db142
参考にbuild.gradle編集

```
Error:(177, 0) *** Android NDK: APP_STL stlport_static is no longer supported. Please switch to either c++_static or c++_shared. See https://developer.android.com/ndk/guides/cpp-support.html for more information.    .  Stop.
```
が出たので
https://github.com/google/ExoPlayer/issues/5052
を参考に```Application.mk```の```APP_STL```の参照を```APP_STL := c++_shared```に変更
＞解消

##Error:Execution failed for task ':app:transformDexArchiveWithExternalLibsDexMergerForDebug'.
複数の依存性が競合した時に起こるエラー。
何回も遭遇したので、その中の一例を示します

https://qiita.com/Capotasto/items/ad1824722da7c3d9da97
を参考にとりあえず```./gradlew app:dependencies```でエラーで言われてるライブラリを使っているところを探す
今回怒られたのは```Multiple dex files define Landroid/support/v4/view/MotionEventCompat;```

```
~~~中略~~~
+--- com.google.android.gms:play-services-base:12.0.1
|    +--- com.google.android.gms:play-services-basement:12.0.1
|    |    +--- com.android.support:support-v4:26.1.0
~~~中略~~~
```
上記によれば`com.google.android.gms:play-services-base:12.0.1`が呼び出しているらしいので、

```
compile ('com.google.android.gms:play-services-base:12.0.1') {
    exclude group: 'com.android.support', module: 'support-v4'
}
```
で依存性から外してやる。大体これでいけるはず

##org.gradle.tooling.BuildException: Could not run build action using Gradle distribution 'https://services.gradle.org/distributions/gradle-4.10.2-all.zip'.
全文がすごく長かったので関係ありそうな部分だけ抜粋

```
Error:Internal error:
org.gradle.tooling.BuildException: Could not run build action using Gradle distribution 'https://services.gradle.org/distributions/gradle-4.10.2-all.zip'.
Caused by: org.gradle.internal.exceptions.LocationAwareException: Execution failed for task ':app:javaPreCompileDebug'.
Caused by: org.gradle.api.tasks.TaskExecutionException: Execution failed for task ':app:javaPreCompileDebug'.Caused by: java.lang.RuntimeException: Annotation processors must be explicitly declared now.  The following dependencies on the compile classpath are found to contain annotation processor.  Please add them to the annotationProcessor configuration.
  - butterknife-6.1.0.jar (com.jakewharton:butterknife:6.1.0)
Alternatively, set android.defaultConfig.javaCompileOptions.annotationProcessorOptions.includeCompileClasspath = true to continue with previous behavior.  Note that this option is deprecated and will be removed in the future.
See https://developer.android.com/r/tools/annotation-processor-error-message.html for more details.
```
https://stackoverflow.com/questions/47087730/why-do-i-have-problems-whith-com-jakewhartonbutterknife7-0-1-in-android-stud
参考にapp/build.gradle修正

```
android {
    ~~~~~中略~~~~~

    defaultConfig {
        ~~~~~中略~~~~~
        //ここから追記部分
        javaCompileOptions {
            annotationProcessorOptions {
                includeCompileClasspath true
            }
        }
        //ここまで追記部分
    }
    ~~~~~中略~~~~~
}
```
＞解消！

#実行時のバグ編
##アクティビティ遷移時に勝手にキーボードが立ち上がる
https://codeday.me/jp/qa/20190205/219782.html
https://developer.android.com/reference/android/view/WindowManager.LayoutParams#SOFT_INPUT_STATE_ALWAYS_HIDDEN
立ち上げたくないアクティビティのonCreateメソッドに

```
this.getWindow().setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_STATE_ALWAYS_HIDDEN);
```
を追加で解消

ちなみに```setSoftInputMode```は指定のWindowに対するソフトキーボードの挙動を指定できる。
```WindowManager.LayoutParams.SOFT_INPUT_STATE_ALWAYS_HIDDEN```はフォーカスがあたったときにキーボードが立ち上がらないようにする

##アプリを起動/プッシュ通知からの遷移をしても通知が消えない
そもそも通知を消す処理がなかったのが原因
FCMではonMessageの中に

```
if(prefs.getInt("push_flg", 1)==1){
        NotificationManager mNotificationManager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
        Notification notification = new Notification(R.drawable.icon, null, System.currentTimeMillis());
        PendingIntent contentIntent = PendingIntent.getActivity(this, 0, new Intent(this, splash.class), 0);
        notification.setLatestEventInfo(this, "好きな文字列", str, contentIntent);
        mNotificationManager.notify(1, notification);
}
```
みたいな処理があるはず。
```mNotificationManager.notify(1, notification);```の第一引数が通知のID（int型）になっている。
消すときはこれを指定して任意の箇所で

```
//通知があったら消す
NotificationManager mNotificationManager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
mNotificationManager.cancel(1);
```
とすればOK
今回はトップページのonCreate始まってすぐのところに設置した。

ちなみに、上記メソッドのsetLatestEventInfo()は非推奨でAPIレベル23から削除されている。
推奨はNotificationCompatを使うことで、

```
if(prefs.getInt("push_flg", 1)==1){
          NotificationManager mNotificationManager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
          PendingIntent contentIntent = PendingIntent.getActivity(this, 0, new Intent(this, splash.class), 0);
          
          NotificationCompat.Builder mBuilder =
                  new NotificationCompat.Builder(this)
                  .setSmallIcon(R.drawable.icon)          //通知に出すアイコン
                  .setContentTitle("通知タイトル")           //通知のタイトル
                  .setContentText(str)                    //通知の本文
                  .setContentIntent(contentIntent);       //タップした時にどこに遷移するか
          
          mNotificationManager.notify(1, mBuilder.build());  //登録
}
```
な感じで使う。
さらに

```
mBuilder.setAutocancel(true);
```
とすれば通知をタップした時に通知を削除することもできる。
上記の```mNotificationManager.cancel()```も使えるので、こちらを使えば任意の場所で消せる。

##install_failed_no_matching_abis res =- 113
エミュレータで実行しようとした時に発生
https://stackoverflow.com/questions/36414219/install-failed-no-matching-abis-failed-to-extract-native-libraries-res-113
参考にapp/build.gradle修正

```
android {
    ~~~中略~~~~

    //追加
    splits {
        abi {
            enable true
            reset()
            include 'x86', 'armeabi-v7a', 'x86_64'
            universalApk true
        }
    }
    ~~~中略~~~~
}
```
で解消した
ちなみにこれをやるとリリースビルドで不都合が起きる可能性があるので、実機で発生しないならリリースビルドの時だけ上記を外す対応が必要
正直面倒なのでもっといい方法ないものか…

##android.os.NetworkOnMainThreadException
特定のAPIを飛ばす時にエラー

https://shirusu-ni-tarazu.hatenablog.jp/entry/2013/01/20/033030
http://shiro-16.hatenablog.com/entry/2014/03/25/004856
によると、android studio 3.xからの仕様で、メインスレッドから通信しようとしてはいけないらしい
別スレッドから飛ばすように修正

```
new Thread(new Runnable() {
   @Override
   public void run() {
      //API飛ばすメソッド
   }
}).start();
```
な感じ

##android studio Only the original thread that created a view hierarchy can touch its views.
こちらは上記と逆でメインスレッド以外からviewを変更しようとするとエラーになる。

上記エラーと絡んでるところで全部メインスレッドからやるわけにもいかない箇所だったので
http://accelebiz.hatenablog.com/entry/2016/09/01/061934
参考に`handler.post`を使って回避
だが、通信してるところまでhandler.postに入れてしまうと今度は上記の`NetworkOnMainThreadException`が起きるので注意

##requestFeature() must be called before adding content
https://stackoverflow.com/questions/4250149/requestfeature-must-be-called-before-adding-content
参考に対応

```
requestWindowFeature(Window.FEATURE_NO_TITLE);
```
を使っていたので、これをsuper()の直後に移した
＞解消だが、バージョン依存の可能性あり。要調査

##端末のバージョン判定がおかしい
Oreoなのにそう判定してくれない…
ブレークポイントで止めてみる限り、`isAtLeast0()`の結果がおかしい気がする
https://qiita.com/nukka123/items/60a942d054c17c9610ab
で言ってる通りメソッド自体にバグがあるっぽい
＞26.0.+の最新である26.0.1をちゃんと指定してみる
（バージョンは
https://dl.google.com/dl/android/maven2/index.html
で確認。)
＞`Error:(52, 13) Failed to resolve: com.android.support:support-v4:26.0.1`
＞https://qiita.com/meru_h/items/f198a300d41e0c59aea4
と同じ対応
＞解消

##android ver.9からhttp通信に失敗する
https://backport.net/blog/2018/12/27/how_to_allow_http_on_android_9/
http://blog.riskfinder.co.jp/2016/03/network-security-configuration-android-n.html
上記記事によると、android9.0からhttp通信してると弾かれるが、明示的に許可すれば通してくれるとのこと。
ぶっちゃけhttpsにする方が望ましいので、下記の対応は非推奨です…
今回はNetworkSecurityConfig.xml作成で対応

```network_security_config.xml
<?xml version="1.0" encoding="utf-8"?>
<network-security-config>
    <domain-config cleartextTrafficPermitted="true">
        <domain includeSubdomains="true">hoge.com</domain>
    </domain-config>
</network-security-config>
```
＞androidManifestに

```
   <application
        (省略)
        android:networkSecurityConfig="@xml/network_security_config"
        >
```
を追加、動作確認して終了

#その他
##ログキャットが出ない
android studio2.3で発生
非常に基本的なところで恥ずかしいですが自戒のためにメモ…

出力されないとかではなく、下部のタブにも存在せず、ウィンドウ自体が出せない
window出てないだけなので、
http://aws-mobile-development.hatenablog.com/entry/2016/11/06/065030#2Logcat%E8%A1%A8%E7%A4%BA%E6%96%B9%E6%B3%95
で表示。解決。
「logcat」じゃなくて「Android Monitor」という名前でwindowが追加されるので注意

##waiting for target device to come onlineが出続けて実行できない
http://b0npu.hatenablog.com/entry/2018/04/07/084709
cold boot nowしようとする
＞項目自体がない
＞https://stackoverflow.com/questions/42757928/waiting-for-target-device-to-come-online-in-android-studio-2-3
sdk toolsをupdateしてみる
＞変わらず
＞一旦他のバージョンで試す（このときのエミュレータはsdk19）
＞26でうまくいった
＞もう一度19でやってみてもいかない
＞19を一回削除して入れ直して見る
＞x86で入れないとパフォーマンス落ちるかもみたいなメッセージが出てたので、x86で入れてみる
＞やっとつながった…入れるソースが他のイメージと違ったらしい

別のケースだとandroid studio再起動で直ったこともあり