アプリの高速化を計るため、devToolでどこが遅いか調べていたところ、
ログインページ辺りでjavascriptの読み込みがやや遅くなっていたので
performancesタブで詳細を取ってみました。するとやはり最初にscriptタグを
読んでいた辺りが怪しかったのでindex.htmlの中のscriptタグの
読み込みを少し修正。。。
修正箇所は、”text/javascript” src=”cordova.js”async>
の赤文字の部分。
text/javascriptの部分を抜き取ります。
</pre> <script src="cordova.js"async></script> <pre>
HTML5では、scriptタグのtypeのデフォルト値が 最初から”text/javascript” に
設定されており、これが付いている状態で読み込むと、同じ属性”text/javascript” を
二回読むことになってしまい読み込み時間にラグが生まれるという訳です。
ここは省略して–script src=”cordova.js”async</script>–のようにすることで
速度の改善を見込むことができます。
正しくはこんな感じ↓
</pre> <script src="cordova.js"async></script> <pre>
scriptタグが多く設定している時ほど威力を体感できるのではないでしょうか。
後は古い機種(android5.0とか)でも感度良さげですね。
cordovaでプラグインを入れ直した直後に
ビルドしたところ、FCMPrugin is not foundのエラーに遭遇。
デバッグした結果、この中で一つ当てはまった場合に起きるエラー
のようです。
①FCMPruginが正常に読み込まれていない
②tokenが無効な値
③onDeviceReady内で処理をしていない
④FCMPruginが他のプラグインとせり合いを起こしている
自分の場合は④で、FCMPruginのバージョンが古かったため
他のfirebaseのプラグインと役割が被っていたのが原因でした。
④に関してはFCMPruginのバージョンを下げて追加
することで解決させることができます。
それでも解決しない場合は、platformsを削除、そのあとfirebaseに関わるプラグインを
全て消して再び追加、最後にplatformsを追加
をしてください。
以上がFCMPrugin is not foundの解決方法になります。
plugin関係は依存度の理解とかプラグインのエラーの原因と
なったファイルを探す探索力が必要になってくるのですが、
まだまだそこが理解できていない部分があるので
慣れておく必要があると感じました。
gradleのバージョンを5.4.1にしてビルドをすると
cordova-plugin-firebaseとcordova-plugin-fcmが競り合いを起こして
Cannot add task ‘:processDebugGoogleServices’のエラーとなります。
解決方法は
①cordova-plugin-firebaseとcordova-plugin-fcmをそれぞれcordova plugin rm 〇〇する
②cordova platforms rm android
③cordova platforms add android@6.4.0をadd
④cordova-plugin-firebaseとcordova-plugin-fcmをそれぞれcordova plugin add 〇〇する
⑤ビルド後gradleの変更(android Gradle Plugin Vesion 3.0.1 Gradle Version 4.1)
⑥gradle-wrapper.propertiesの6行目 gradle-4.1-all.zipに変更
⑦ビルドでエラーが出なければ成功
cordova platforms add androidの際は、何も指定しないでaddを
すると、android6.3.0がインストールされますが、このバージョンだと
cordovaのライブラリで一部競り合いが起こるものが入っているので
避けた方が良いです。代わりに一つ上の6.4.0を使うことで
ライブラリ系のトラブルを減らすことができます。
node_moduleがno such file or directoryの時に対応したこと
cordova prepare androidをした時に出てきたエラーです↓
ERROR in ./node_modules/react-router-dom/node_modules/warning/warning.js
Module build failed: Error: ENOENT: no such file or directory, open ‘C:\Users\swift0910\Documents\NEW_APP\node_modules\react-router-dom\node_modules\warning\warning.js’
@ ./node_modules/react-router-dom/HashRouter.js 7:15-33
@ ./www/js/app.js
ERROR in ./node_modules/react-router-dom/Route.js
Module not found: Error: Can’t resolve ‘react-router/Route’ in ‘C:\Users\swift0910\Documents\NEW_APP\node_modules\react-router-dom’
@ ./node_modules/react-router-dom/Route.js 5:13-42
@ ./www/js/app.js
ファイルが見つからない為正常にビルドができませんと言いたいようです。
react-router-domなんてnpm installしたら必ずついてくるのにも関わらずです。
node_moduleを作成した後のファイルが見つからないなんてどういうことなのか
まだ理解できていないのですが、このままでビルドするわけにもいかないので
少しずつ修正作業へ。
npm cache cleanでキャッシュを削除
npmのバージョンを6.9.0から3.10.10にダウングレード
node_moduleを手動で消した後にnpm installで解消
6.9.0だとnode_moduleが競り合いを起こす。そもそも
新しいnpmに対応していないファイルを呼ぼうとしている
->ファイルが見つからないということです。
参考 https://stackoverflow.com/questions/52215541/module-build-failed-error-cannot-find-module-node-sass
build.gradleに書いてあるtask wrapper(type: Wrapper)は
gradle5.0から書き方が変わったらしく、そのままビルドすると
ERROR: Cannot add task 'wrapper' as a task with that name already exists.
エラーになってしまいます。
ここでは一番最初に記載されてあるtaskとtype:Wrapperを消去して
これを task wrapper(type: Wrapper) { gradleVersion = '5.4' }
修正 wrapper{ gradleVersion = '5.4' }
wrapperのみ記述することでエラーを回避することができます。
現状ではこの回避方法が無難かなぁと思います。
愚痴ですが、gradleのバージョンを上げなければandroidStudioでビルドしてくれない。
上げたら上げたでまた別の依存関係が出てくる(主にgoogle-serviceとか)
google-serviceの依存関係って本当面倒だ・・・。
javaでは、Html.fromHtml(何かの変数)メソッドを使うことでhtmlタグでTextView
を操作することが出来ます。
部分的に強調したいところがあったりTextViewをリンクとして
使いたくなった時に色を変えたい時が主な用途です。
まず、sring.xmlで文字を追加します。
<pre><string name="sample" translatable="false">※[<font color=\"navy\">%s</font>]</string></pre>
stringタグを作った後に色を変えたい箇所を<と>で囲みます。囲まれている
$sが今回表示したい文字になります。
color=\”何かの色\の形式で好きな色に変えることができます。
続いてxml↓
<pre><TextView android:id="@+id/text_sample" android:layout_width="150sp" android:layout_height="wrap_content" android:layout_marginStart="10dp" android:layout_marginEnd="20dp" android:layout_marginTop="110dp" android:textColor="#444444" android:background="@drawable/selector" android:textSize="16sp" android:textStyle="bold" /></pre>
後にコード上で文字列を入れるのでテキストには何も設定しません。
ですがこれだけではこのまま表示されてしまうので、次にMainActivityに
実際に文字を入れていきます。
まず、String.formatでstring.xmlから文字を抽出しています。第一引数
が形式、第二引数が入れたい文字となっております。
次に、入れたい文字列ですが、ここではhogehogeが先ほどのstring.xmlの%sに入っていきます。
最後にsetTextの中でHtml.fromHtml(text)でhtmlタグを使って
@InjectView(R.id.text_sample) TextView sampleText; protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_help); ButterKnife.inject(this); String text = String.format(getText(R.string.sample).toString(), "hogehoge"); sampleText.setText(Html.fromHtml(text)); }
string.xml内の文字列を翻訳して色が変われば無事終了となります。簡単
なコード数行で済むのでhtml経験者ならもっと自在に扱えそう・・・・。
でもcssなしでここまでカスタマイズできるなら上等かなぁと思います。
画像読み込みライブラリのpicassoが便利なのは前のブログで
散々説明してきたので割愛します。
今回は、キャッシュした画像はどこから取ってきたかを
調べるためにPicasso.with(getApplicationContext()).setIndicatorsEnabled(true);
を使います。
この一行を加えるだけでpicassoがどこを通じてキャッシュしたか
分かるようになります。
例えば、ピカソの画像の左上を見ると
角の部分が緑色になっているの
が分かります。
これはメモリ経由、つまりメモリ上でキャッシュした画像を
引き出して表示しているという意味合いになります。
もともとはこの画像はネットワーク上から取得したのですが、picassoは取得した画像を
指定の場所にキャッシュをするので、必然的にこの画像の発生場所は
メモリ上になるということです。
この他にもネットワークから直接持ってきた場合は赤、ディスクから
持ってきた場合は青色の角として表示されます。
出自元が分かればそこまで調べる必要はなさそうですが、ダウンロードした
画像がちゃんとキャッシュされているか確認したい場合は使う価値大ですね。
数あるshuffle法の中で最も分かりやすいかつ速度が安定している
Fisher-Yatesアルゴリズムで値をごちゃまぜにしてみました。
どこまで値を増やしてもO(n)のままなので、速度にこだわらない
のであれば大体これ一択という流れになります。
こちらは、15個の値を順に並べ、シャッフルボタンを
押すと1から順に並んだ値とランダムで出した値を100通り
shuffleしています。
このやり方、先週ブログでも書いた文字列を判定する方法と
似ていますね。これを更に応用してランダムに1番から15番の値を
iが100に達するまで回しています。
100のところは500でも1000でもその限度まで回してくれるので
もっと回したい!というかたはお好みで。
<pre>public class MainActivity extends AppCompatActivity { int[] data = {1,2,3,4,5,6,7,8,9,10,11,12,13,14,15}; int[] first = new int[5]; int[] sec = new int[5]; int[] drawableIds; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); ButterKnife.inject(this); //drawableIds = new int[typedArray.length()]; } @OnClick(R.id.shuffle) public void shuffle() { Random rand = new Random(); for(int i = 0; i < 100; i++){ for(int j =0; j < data.length; j++) { int temp; int num = rand.nextInt(data.length); temp = data[j]; data[j] = data[num]; data[num] = temp; } } } }</pre>
更に、このままだとシャッフルしただけで何も面白くないという
ことなので、せっかくなのでカードゲームのように最初の列から
値を5個ずつ取ってみましょう。
まず、一番最初にfirstという配列にドローした値を格納しています。
このfirstはもういじることはないので、次に連続して引きたい時に
先ほど引いた5個の値を後ろに押し戻して次の5個の値を
取り出します。
同時に10列目の値群も動かさないといけないので5の倍数で
動かしていきます。
一通り入れ替えたらSystem.out.printlnをして確認してみましょう。
こちらが確認できれば組立終了です。
@OnClick(R.id.take) public void draw() { for(int d = 0; d < data.length / 3; d++){ first[d] = data[d]; } System.out.println(Arrays.toString(first)); for(int s = 0; s < data.length / 3; s++){ int temp; temp = data[s]; data[s] = data[s+5]; data[s+5] = data[s+10]; data[s+10] = temp; } System.out.println(Arrays.toString(data)); }
シャッフルクラスの説明は以上でおしまいです。
これを一つのクラスにまとめればトランプとかボウズめくりの
ための汎用クラスとして使えそうですね。
StringBuilderを使ってhttpURLConnectionで好きなだけデータを
postする汎用メソッドを作りました。
使い方はシンプルで、ただ拡張for文を使って回すだけなので
特別な制約は無いです。
</pre> @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); StringBuilder contentsBuilder = new StringBuilder(); Map<String, String> map = new HashMap<>(); String str = "hello!!"; double lat = 34.222222; double longi = 137.111111; String line = ","; String strlati = String.valueOf(lat); String strlong = String.valueOf(longi); map.put("string", str); map.put("latitude", strlati); map.put("longitude", strlong); for (String val : map.values()) { if (contentsBuilder.length() > 0) { contentsBuilder.append(line); } contentsBuilder.append(val); } } <pre>
変数latとlongiはdoubleですが、途中でString.valueOf()で変換することで
送ることができるようになります。
もしサーバー側で変換したい場合は、\nとか、ごとに切り分けた後に
各値に合った型に戻してあげればいけそうですね。
本当はもっと簡単に書きたかったですがこの辺で妥協します。
入力した文字列を反転させるミニアプリを作りました。
ライブラリを使えばこんな手間なんてかからないのですが、
なんとなく生のjavaを触って反転させたいと思ったのがきっかけです。
public class MainActivity extends AppCompatActivity {
EditText ed;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Button button = findViewById(R.id.altBtn);
ed = findViewById(R.id.mountingText);
button.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
String beforeAlterText;
beforeAlterText = ed.getText().toString();
char[] chars = beforeAlterText.toCharArray();
int i = beforeAlterText.length();
if(i % 2 == 0) {
int dev = i / 2;
for(int j = 0; j < dev; j++){
char temp = chars[j];
chars[j] = chars[i – j – 1];
chars[i – j – 1] = temp;
}
System.out.println(chars);
}else if(i % 2 == 1){
int notdev = i / 2 + 1;
for(int j = 0; j < notdev; j++){
char temp = chars[j];
chars[j] = chars[i – j – 1];
chars[i – j – 1] = temp;
}
System.out.println(chars);
}
}
});
}
}
最初の分岐で奇数か偶数か判別した後に入力した文字を2で割って中間地点を決めます。
この中間地点まで文字を反転させるといった感じになっています。
バブルソートは値の大小を判断しますがここではただの文字列
なのでそのまま文字を置き換えています。
文字は出てこないですがSystem.outで反転後の文字列が
確認することができます。
以上ですが見ての通り中身が何もないです。
ttsとか使って応用できればもっと面白そうなアプリが作れるかもしれません。
とりあえずソートの練習をしたいとか見てみたいとか思ったら試してみてください。
P.S.余談ですが、自分はこのコードの中で文字列を
退避するところをゴミ箱って呼んでます。