aswww log

エンジニアの技術録。アプリとかウェブとか

nightmareJsのインストールとElectronに関わるコマンドと参考リンク

npm install vo

○npmパッケージ一覧表示

npm ls --depth=0

○npmパッケージ詳細一覧表示

npm ls 

○Electronのパッケージ化パッケージインストール

npm i electron-packager -g

○Electronパッケージ生成

$ # electron-packager <sourcedir> <appname> --platform=<platform> --arch=<arch> --version=<version>
electron-packager ./jstest getAdToday --platform=darwin,win32 --arch=x64 --version=0.36.1

nightmarejsで参考にしたサイト
googleログイン

  • Nightmareがv2(Electronベース)になり、使いやすく感動したのでLIGブログのPV/UUデータ取得を自動化してみた。

http://qiita.com/n0bisuke/items/8a7a52321380e5cf0379

○オプション一覧

  • Nightmareさんとこをざっくり訳

http://kurokokoruru.hatenablog.com/entry/2016/01/03/185817

  • Nightmarejsでセッションを維持しない

http://qiita.com/notsunohito/items/c8d7768cc6b30dd8e441

Electronで参考にしたサイト
○Electronをパッケージ化する

  • 30分で出来る、JavaScript (Electron) でデスクトップアプリを作って配布するまで

http://qiita.com/nyanchu/items/15d514d9b9f87e5c0a29#%E3%82%A4%E3%83%B3%E3%82%B9%E3%83%88%E3%83%BC%E3%83%AB

○package.jsonの書き方とか

  • はじめてのElectronAdd

https://goo.gl/koUKXI


エラー関連
■npm ERR! enoent ENOENT: no such file or directory, open package.json
electron-packager入れてなかったことが原因

■実行ファイルを実行したらError: Unable to find a valid app
package.jsonがソースディレクトリになかったことが原因[]
https://github.com/electron-userland/electron-packager/issues/264

SharedPreferenceの変更時に警告アラート表示

アプリの設定(SharedPreference)を変更した際、スマホの画面解像度(画面サイズdp)が小さいとWebViewが表示崩れが発生する恐れがでてきた。
表示崩れが発生する可能性がある設定に変更した時、警告アラートを出すことにした。

まず、基準となる解像度を調査。以下のようなQiita記事を参考。

2015年発売Android端末のdp解像度まとめ
http://qiita.com/nein37/items/0a622f7ebbbb92db93d5#_reference-05eb2ffe676dfafa464c

んで画面サイズを取得
Androidでデバイスの大きさをdpで取得する
http://aroundthedistance.hatenadiary.jp/entry/2015/03/16/122827
(一部引用)

DisplayMetrics displayMetrics = getResources().getDisplayMetrics();
float dpWidth = displayMetrics.widthPixels / displayMetrics.density;

それで調べた通り、PreferenceFragmentなクラスに実装

    public static class SampleFragment extends PreferenceFragment {

	    ︙
		//設定変更された時に呼ばれる
        @Override
        public void onSharedPreferenceChanged(SharedPreferences sharedPreferences, String key) {
            if(key.equals(対象の設定[])){
                //画面解像度(横幅)をdbで取得
                DisplayMetrics displayMetrics = getResources().getDisplayMetrics();
                float dpWidth = displayMetrics.widthPixels / displayMetrics.density;
				
                if(dpWidth <= 基準サイズ){
                    int screenSize = sharedPreferences.get(key, null);
				    //画面サイズ最大のときのみ警告を出す
				  }
			    }
            }
        }

参考:
http://u64178.blogspot.jp/2014/07/android-preferencefragment-preference.html

AlertDialogでネストしたい時

アプリでダイアログ表示した後、ユーザーが特定のボタン(NeutralButton)を選択して押した時に更に新しいダイアログを表示するようにした。
ここではまったのは新しいダイアログの方のnew AlertDialog.Builder(this)の引数。Contextを指定してほしいと言われたので

new AlertDialog.Builder(this)

とか

new AlertDialog.Builder(getApplicationContext())

とか色々試したけどダメ。結果、どこかのstackOverFlowで見たMainActivity.thisを指定してあげたら動いたよ。
thisってインスタンスじゃないの?クラス名.で呼び出せるのってstaticなクラスだけじゃないんだっけか?

private void showAlert(){
    new AlertDialog.Builder(this)
        .setTitle("title")
        .setMessage("message")
        setNeutralButton("NeutralButton"), new DialogInterface.OnClickListener() {
            @Override
            public void onClick(DialogInterface dialog, int which) {
				new AlertDialog.Builder(MainActivity.this)
				   ︙
            }
        })
        .create().show();
}

AdMob実装で大いにハマった備忘録

AdMobに関係あるのからないのまで。
何日もハマった上にいろんな設定を色々いじって何やったか忘れてしまったので、雑な感じですが備忘録的な感じでなにとぞ。

1).AdMobの実装を一通り終えてbuildしようとしたら以下のエラーが出た。

java.lang.ClassNotFoundException: Didn't find class "com.google.firebase.provider.FirebaseInitProvider" on path: DexPathList[[dex file "/data/data/[パッケージ名].debug/files/instant-run/dex/slice-com.google.firebase-firebase-iid-9.6.1_17f9eed5e9c1fe52c568855cb2090871a90f4031-classes.dex", dex file "/data/data/[パッケージ名].debug/files/instant-run/dex/slice-com.google.android.gms-play-services-ads-9.6.1_1aa317fdb75c8fb2b8ae8bfdfb55c4013d6bc40a-classes.dex"],nativeLibraryDirectories=[/vendor/lib64, /system/lib64, /vendor/lib64, /system/lib64]]

よくわからないけどDexファイルがなんとか?
メモによると以下のとおりMultiDexを設定ファイルに書き加えたらエラー解消したらしい。

build.gradle

android {
    compileSdkVersion 21
    buildToolsVersion "21.1.0"

    defaultConfig {
        ...
        minSdkVersion 14
        targetSdkVersion 21
        ...

        // Enabling multidex support.
        multiDexEnabled true
    }
    ...
dependencies {
  compile 'com.android.support:multidex:1.0.0'
}


AndroidManifest.xml

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.example.android.multidex.myapplication">
    <application
・・・
        android:name="android.support.multidex.MultiDexApplication"
・・・
    >

参考:
http://qiita.com/nshmura/items/c7e8faa05c5ad4a66b3d#_reference-91cadc916c4dc5fe7d87
https://developer.android.com/studio/build/multidex.html?hl=ja#dev-build


2.)メソッド数が64k(65536)を超えるとビルドエラーになる

具体的なログはロストしてしまったが、65536という数字が出たらきっとこのエラー。
以下のとおり対処を調べた。このうちの1,2,4を実施。
どれかでエラーが解消された。(4かな)

[対処1]. メソッド数の確認
以下、リンク先より抜粋

http://qiita.com/konifar/items/d98c78facbaae63badca
実際どのくらいのメソッド数なのかを確認します。dex-method-countというツールを使うと、簡単にapkのメソッド数を確認できます。

$ git clone https://github.com/mihaip/dex-method-counts.git
$ ./gradlew assemble # ビルド
$ ./dex-method-counts path/to/app.apk # or .zip or .dex or directory
こんな感じで出力されます。まずは出力してみると、節約できるところが見つかるかもしれません。
Read in 60366 method IDs.
<root>: 60366
    : 8
    android: 10815
        accessibilityservice: 6
        accounts: 8
        animation: 2
        app: 351
        bluetooth: 2
        content: 303

...(略)...

    com: 39448

...(略)...

        google: 18513
            ads: 165
                mediation: 134
                    admob: 24
                    customevent: 40
                    jsadapter: 38

[対処2].google playSDKのインストールはやめる
以下、リンク先より抜粋
http://qiita.com/garlicG/items/fac54cf96d66cfcb4b8d

play-service全体のライブラリは少し巨大なので、AdMobだけが必要であれば以下のような記述でおKです。
build.gradle(AndroidStudio利用時)

compile 'com.google.android.gms:play-services-ads:7.3.0'

[対処3].ProGuardを導入する
もうしてました。(デフォルトでそうなってる?)

[対処4]. gradleでjumboModeオプションを有効にする
また以下のリンク先のとおりに修正。
http://qiita.com/konifar/items/d98c78facbaae63badca


3).support-appcompat-v7のFile size 0 byteエラー
buildも通るようになったので、Android Studioからエミュレータ(ADV)起動して確認しようとしたらエラーった。

10-28 22:38:19.568 2306-2306/[パッケージ名].debug E/System: Unable to load dex file: /data/data/[パッケージ名].debug/files/instant-run/dex/slice-com.android.support-appcompat-v7-23.3.0_e72ec210e17d195522eaa56b35521a9733e3c94a-classes.dex
10-28 22:38:19.569 2306-2306/[パッケージ名].debug E/System: java.io.IOException: Failure to verify dex file '/data/data/[パッケージ名].debug/files/instant-run/dex/slice-com.android.support-appcompat-v7-23.3.0_e72ec210e17d195522eaa56b35521a9733e3c94a-classes.dex': Bad file size (32768, expected 550080d)
                                                                         at dalvik.system.DexFile.openDexFileNative(Native Method)


                                                                      Caused by: java.io.IOException: Failed to find dex file 'x-classes.dex' in oat location 'x': Failed to find existing oat file at x: File size of 0 bytes not large enough to contain ELF header of 52 bytes: '/data/data/[パッケージ名].debug/cache/slice-com.android.support-appcompat-v7-23.3.0_e72ec210e17d195522eaa56b35521a9733e3c94a-classes.dex'
	

原因不明。Android Studioの設定から見なおしたけど一向に治らなかった。
AVDを新規作成したらこのエラーが出なくなった。(ソースとかのせいとかじゃなかった。)
こんなのに2日も振り回されて私ってホント馬鹿。

4.)AdMobの実装エラー
やっとまともに起動したAVDで出たエラー。

java.lang.IllegalStateException: The ad size can only be set once on

ad size がなんたら。
以下のとおり、content_main.xml(active_main.xml)とソース内両方でAdsizeを指定したのがまずかった。

content_main.xml

    <com.google.android.gms.ads.AdView
	・・・
        ads:adSize="SMART_BANNER" //これと
	・・・

MainActivity.java

        MobileAds.initialize(this, getString(R.string.banner_ad_unit_id));
        adView=(AdView) findViewById(R.id.adView);
        adView.setAdSize(AdSize.SMART_BANNER);   //これ
	・・・

ソースの方をコメントアウトしたら表示できたよ!
http://stackoverflow.com/questions/23337802/ad-size-and-ad-unit-id-must-be-set-before-loadad-is-called

広告表示でここまで大変なんだなー。AdMob仕様変わらないでほしいな。。。もうやりたくない。。。

AndoroidアプリにAdMobバナー広告を設定するときにハマった

AdMobを設定するために以下のサイトを参考にbuild.gradleを実装したり、google-services.jsonを設置したりした。

https://firebase.google.com/docs/admob/android/quick-start?hl=ja

すると例のR.が読めなくなるエラーとともに以下のエラーが出力された。

エラー :Execution failed for task ':app:processDebugGoogleServices'. > No matching client found for package name '[パッケージ名].debug'

原因は先日追加した開発用モジュールdebugが原因らしい。
そこで、以下のとおり修正したgoogle-services.jsonを/debug/配下に設置した。

  "client": [
    {
      "client_info": {
        "mobilesdk_app_id": "1:209109689792:android:463e3def0de05f38",
        "android_client_info": {
          "package_name": "[パッケージ名].debug"
        }

するとR.が読み込めなくなる例のエラーは解消された。

参考:
http://stackoverflow.com/questions/34990479/no-matching-client-found-for-package-name-google-analytics-multiple-productf

WebView内で通信エラーでエラー画面表示さす

WebView内で通信エラーになった場合(net::ERR_CONNECTION_TIMED_OUT)、エラーページを表示さすようにハンドリング
#WebViewClient生成時に定義してあげる

○準備(既にassetsディレクトリがある場合は不要)
HTMLを置くassetsディレクトリを作成する。
AndroidStudioのプロジェクトのappを右クリック→[新規]→[New]→[Folder]→[Assets Folder]を選択。
app/src/main/asestsディレクトリが作成される。
また、build.gradleに以下のとおり追記する。(自動挿入されることもあるので、既にあったら編集不要)

android {
    sourceSets{
        main{
            assets.srcDirs=["src/main/assets"]
        }
    }
・
・
・

app/src/main/asestsにエラー画面のHTML(network_error.html)を配置して準備終了

○WebViewクラスにコーディング

次のとおりWebView生成時にオーバーラードして実装する。

WebView webView = (WebView) findViewById(R.id.webView);
webView.setWebViewClient(new WebViewClient() {
    @Override
    public void onReceivedError(WebView webview, int errorCode, String description, String failingUrl) {
        if(errorCode < 0){
            // 自作のエラーページを表示
            webView.loadUrl(“file:///android_asset/network_error.html”);
        }
    }

参考URL
http://www.hangout.co.jp/blog/archives/148
http://stackoverflow.com/questions/4997677/android-webview-onreceivederror
http://growsic.com/blog/androidlocalhtml/

Andoridアプリの開発と本番の取扱をGradleでどうにかする

参考にしたサイトは以下。
https://firespeed.org/diary.php?diary=kenz-1824

Andoroidアプリ界隈で開発と本番は

開発=debug、本番=release

っぽいので以下はそれに則って記載する。

○一つの端末にデバッグバージョンアプリとリリースバージョンアプリを共存させたい
Module内にあるbuild.gradleを以下のとおり修正する。

    buildTypes {
        debug{
            applicationIdSuffix ".debug"
        }
        release {
		・
		・
		・

ビルド時にデバッグバージョンアプリの時は、アプリIDに.debugがつくので、アプリバージョンIDがリリースバージョンと被らない=共存できる

○開発と本番で設定ファイルを切り替えたい。
以下のとおり設定ファイルを切り替えられる。

  • 本番用定数

/src/main/res/values/strings.xml

<resources>
    <string name="app_name">Sample application</string>
    <string name="url">http://gati.net</string>
</resources>

/src/debug/res/values/strings.xml

<resources>
    <string name="url">http://uso.net</string>
</resources>

Javaソースコード内で参照する際は普通にR.string.urlでOK。

WEBアプリのようにENVで切り替えられないのは少し不便。