著者アーカイブ asaba

asaba 著者:asaba

【npm】Error: Cannot find module ‘webpack-cliから抜け出す方法

npm uninstall react-tabsをしたら警告が出てしまいました。found 14 vulnerabilities (5 low, 2 moderate, 7 high)と書いてあったので恐らく非推奨のパッケージだと思いすぐにnpm iでまとめてインストールし直したのですが、インストールしたのにも関わらず存在しないことになっている・・・。よく見ると、npm auditを入力して脆弱性のあるパッケージを調査しろとメッセージがあったので急いでリトライをしました。lowが脆弱性が低くてhighが危険ですよってことですね。vulnerabilitiesと書いてあったのに見落としてしまいました・・・。

auditとは、npm installでnode_modules配下にインストールしたpackageの脆弱性をチェックしてくれるプロパティです。元々liftsecurity.ioという企業の技術でした。が、セキュリティノウハウをnpm側が取得したことによりふろんとpackageの脆弱性のチェックが手軽にできるようになりました。

npm auditで検知されたパッケージは、脆弱性を含んでいると見なされ、これらを解決させない限りはビルドを通すことができない仕組みになっています。

npm auditをして下にスクロールしていくと、画像のようにnpm install 〇〇をインストールしてねというメッセージが表示されます。

このメッセージに従ってnpm install 〇〇を追加していけばhighやmoderateの数が減っていくので、0になったらまたビルドをして通るかどうか確認してみてください。流れとしては、npm run buildをするー>found 〇〇 vulnerabilities(4 low,4,moderate,10high)のようにメッセージが出るー>npm install 〇〇コマンドでメッセージに従ってパッケージをいれていくー>解決

ここで脆弱性について問いただされるとは思いませんでした。ですが直す個所は決まっているのでさくっと修正してしまいましょう。

asaba 著者:asaba

【androidJava】LocationManagerで現在位置が取れない時の処理

現在地を取得したい時はLocationManagerで取ることができますが、gpsの情報が不正確だったりgpsの許可が下りていなかった場合は nullで帰ってきてしまい正しい位置情報を取得することができません。しのぐ方法はいくつかあるのですが、自分はまず最初に位置情報を 取得させ、nullだった場合はLocationManager.NETWORK_PROVIDER(基地局からの現在位置の情報)を使いネットワークから取得 させています。

最初からgpsの設定していない場合はSettings.ACTION_LOCATION_SOURCE_SETTINGSを使ってgpsを使うように促して設定ページに移動 させます。これで最小限の設定が出来るので、後は端末のバージョンと相談しながら必要なパーミッションや機能をつければ実装完了です。


Location location = mLocationManager.getLastKnownLocation(LocationManager.GPS_PROVIDER);

if (location != null) {

  System.out.println(location + "there");

  onLocationChanged(location);

  GeoPoint homeposition = new GeoPoint(location.getLatitude(),location.getLongitude());

  mapController.setCenter(homeposition);

} else { location = mLocationManager.getLastKnownLocation(LocationManager.NETWORK_PROVIDER);

  System.out.println(location+ "null");

  onLocationChanged(location);

  GeoPoint homeposition = new GeoPoint(location.getLatitude(), location.getLongitude());

  mapController.setCenter(homeposition);

}
// GPSを設定するように促す
Intent settingsIntent =
        new Intent(Settings.ACTION_LOCATION_SOURCE_SETTINGS);
startActivity(settingsIntent);

 

asaba 著者:asaba

【androidJava】gms:play-services-locationが使えない時の対処法

gmsplay-services-locationのバージョンが古かったので、アップデートしようとしたところでエラーが起きました。当然ですが新機種で使うにはアップデートが必要とのことだったので、渋々インストールしようとしたところ更に次のようなエラーが出た。(二枚目です)

could not findとのことなので、恐らくallprojectsメソッド内でgoogle()を定義し忘れていると思い目を通したら案の定何も無かった。
のでbuildscript内とallprojects内それぞれにgoogle()を定義して解決させました。
buildscript {
  repositories {
     jcenter()
     google()
}
allprojects {
 repositories { 
    jcenter()
    google()
}

google製のライブラリgms:play-services-locationを使うには、google様の名前を付けましょうねということですね。

asaba 著者:asaba

【androidJava】path.xml内で複数のパスを記述するのは避けましょう

fileproviderを使う際に必要なcontentsスキームから成るディレクトリを作るには、pathのxmlファイルが必要になります。

このファイル内にはパスを二つ以上書くこともできるのですが、そうすると下から順番に読み込んでしまい、内部ストレージのパスであるstorage/emulated/0を読み込まなくなるので避けた方が無難です。Android5.0~7.0までは一番上のパスを呼んでくれるのですが、Android8.0は賢くないのか下から順番に探してくるみたいです。なのでAndroid8.0からの新しめのアプリを作る若しくはAndroid8.0向けにアップデートを考えているエンジニアさんは気をつけてくださいね。

これが正しい例↓

<pre><?xml version="1.0" encoding="utf-8"?>
<paths xmlns:android="http://schemas.android.com/apk/res/android">
    <external-path name="storage/emulated/0" path="."/>
</paths>

これが避けた方が良い例↓

<?xml version="1.0" encoding="utf-8"?>
<paths xmlns:android="http://schemas.android.com/apk/res/android">
<external-path name="storage/emulated/0" path="."/>
<external-path name="storage/sd" path="."/>
</paths>

真っ当にリファレンスを読んでいればこんなことには遭遇しないと考えているので、今回は完全に自分向けの話題になってしまいました。まだストレージに関する全ての流れを把握した訳ではないので、しばらくはディレクトリ関係の話題が続きそうです・・・!

asaba 著者:asaba

【androidJava】端末のディレクトリをまとめて取得する方法

機種に依りますが、Environment.getExternalpublicStorageDirectoryでディレクトリを掘り出して中身を見ると、ほとんどの端末は内部ストレージ「storage/emulated/0」に画像を保存しています。ですがandroid5.0からは、撮った画像を自動でSDカードにいれる仕様をもった端末がぞくぞく出てきており、「sdcard」や「storage/sdcard1」など、それぞれが全く違うディレクトリを持っています。

この派生が増えすぎたこともあり、ディレクトリを操作する必要のあるアプリでは機種依存による仕様修正を余儀なくされています。今自分が修正しているアプリも例外でなく、内部ストレージと外部ストレージ(SDカード)の使い分ける処理に四苦八苦しております。2016年からはUUIDが付与された外部ストレージや、そもそも外部ストレージがおおやけに公開されていないOSがリリースされており、アプリのメンテナンスにおける弊害が懸念されます。

今自分が書いているコードは、getExternalFilesDirsAPIを用いて端末における全てのストレージのディレクトリを取得し、その中で(外部ディレクトリ)撮った画像が保存されるディレクトリのみを取り出して共有させるという半ば強引なプロセスを基盤にしています。Environmentメソッドを使わなくともディレクトリを取得できる、しかもSDカードが無いときは自動的に一番先頭の配列(内部ストレージ)を探してくれるのでなかなか柔軟ですね。

File photoFile = null;
try{
    String timeStamp = new SimpleDateFormat("yyyyMMdd_HHmmss").format(new Date());
    String imageFileName = "JPEG_" + timeStamp + "_";
    File[] storageDir = getActivity().getExternalFilesDirs(null);
    File dirs = new File(storageDir[0].getPath());
    if (!dirs.exists()) dirs.mkdir();
    photoFile = File.createTempFile(imageFileName, ".jpg", dirs);
    System.out.println(dirs);

} catch (Exception e) {}

imageUri = FileProvider.getUriForFile(getActivity(), BuildConfig.APPLICATION_ID + ".fileprovider",
        photoFile);

今更なのですが、Environment.getExternalpublicStorageDirectoryってもう古いんですね・・・。2012年ころにリリースされたAPIでもうレガシーだなんて知りませんでした。

asaba 著者:asaba

【androidHava】shouldOverrideUrlLoadingが非推奨になっていた

webViewのリンクをクリックしたときにブラウザの開放を防ぐshouldOverrideUrlLoadingメソッドですが、少し古いコードをいじっていたところ偶然androidDeveloperでこのメソッドが非推奨だということを知りました。

@Override
public boolean shouldOverrideUrlLoading(WebView view, String url) {
  url.startsWith("summerrockfes://showCamera")
  return true;
}

今までは引数をString型で受け取っていましたが、これからはWebResourceRequestを引数に取らなければいけません。

@Override
public boolean shouldOverrideUrlLoading(WebView view, WebResourceRequest request){
  String url = request.getUrl().toString();
  url.startsWith("summerrockfes://showCamera")
 return true; 
}

引数の型が違うのが分かります。startsWithプロパティですが、そのまま使うと型が違うのでエラーになります。startsWithプロパティを今まで通り使うには、事前にStringとして格納する必要があります。書き換えは以上になります。

・・・このメソッドの非推奨の狼煙が上がってから随分立つのですがが、実はそのまま直さなくてもまだ使えることが分かりました。変化が多かったAndroid7.0でも全然使えちゃうのですが、いつ廃止にされるか分からないので早めに書き換えておいたほうがいいかもしれないですね。

参考にさせていただいたページ↓

https://www.jaga.biz/android_dev/shouldoverrideurlloading-deprecated/

asaba 著者:asaba

【androidJava】LounchModeの属性を理解しながら説明してみる

androidのタスクの中のアクティビティを管理するには、LounchModeをうまく使う必要があります。

android:launchMode="singleTop"

この属性を使い分けることによって遷移先のアクティビティで前アクティビティを破棄したり、別のアプリから開いたときのアプリの優先順位を変えたりしてアプリのライフサイクルに変化をつけることができます。ここでは、ACTION_SENDを処理できるActivityAを持っているアプリXとその遷移元のsampleApplyを例にして見ていきます。

sampleApplyアプリで、intentを使ってアプリXに移動します。下は、LounchModeにsingleTopを設定してアプリXに移動した時のタスクの状態です。

—————

| sampleApply アプリX

—————

その後全く違うアプリに移動した時に、再度sampleApplyアプリを起動してみます。すると、タスク上で一番新しい画面のアプリXが表示されます。

図でも判るように、sampleApplyの後にアプリXが格納されていることが分かります。別のアプリに移った後でもまたsampleApplyを起動した場合は、アプリXが表示されます。singleTop適用下では呼び出し元のタスクから順に保持されるため、sampleApplyではなく画面Aが表示される仕組みになっています。つまり、一つのアプリのようにふるまわれる(連結しているような)状態でタスクに保持されます。

intent先でRESULT_CANCELEDを受け取るのを回避したい場合は、このモードを優先して使う必要があります。

次は、singleTask属性で同じことをしてみます。singleTaskモードを設定して別のアプリを起動後に同じようにsampleApplyを起動すると次のようなタスクになります。

—————

| sampleApply | アプリX

—————

さきほどのsingleTop属性と違い、一つ一つのアプリの画面が違うタスクとして分けられています。同じように別のアプリに移った後にホーム画面でsampleApplyを選択します。すると、アプリXに遷移したはずなのにsampleApplyの画面に移動してしまいます。これは、singleTop適用下において、呼び出し元がタスクにとっての最優先アクティビティとして区別されているためです。図で表すと以下のようになります。

—————

| アプリX | sampleApply

—————

ここでは、原点であるsampleApplyがまず呼ばれます。ここで戻るボタンを押した場合は、先ほど先頭に位置していたActivityAが表示されます。一回画面を離れたときに、セキュリティの都合でデータを残したくないアプリを作りたい時に有用そうですね。

asaba 著者:asaba

【android Permission】アプリでカメラ許可をしても落ちてしまう時の対処法

パーミッションを設けたアプリで許可をしても許可されずに強制的に落としてしまう時があります。

androidStudioでキャッシュを消すー>デバイスでインストールしたアプリをアンインストールで再インストールしてみましょう。

現行のandroidで試してみましたがこの方法ならば確実にパーミッションを許可できるのでおすすめです。

 

asaba 著者:asaba

【android-Java】ActivityとContextの違い

fragmentでActivityをいじっている時に、そういえばアプリ開発においてあまり意識していなかったけど、ActivityとContextの
違いってなんだろうと思い調べてみました。意味を調べた結果、そもそも双方とも同じ概念というか、もともとは一つのかたまりのような
ものでした。Contextは、Activityを含んだ全てのオブジェクトを指し、Activityは、Contextの一番新しい層に作られるオブジェクト
のことです。きんちゃく袋と飴ちゃんに例えると、きんちゃく袋がContextで、飴ちゃんがActivityの関係になります。




WebViewを使ったFragmentActivityで元のアクティビティの機能またはアクティビティそのものを取得したい時は、getActivityや
getContextを使います。自分は両方でアクティビティを取得してアプリの挙動を見てみたのですが、どちらも全く変わりない動きでした
ので、どっちのメソッドを使っても支障はないかと感じました。

※fragmentでthisを呼ぶとfragmentはContextを継承していないのでエラーを受けます。(当たり前ですが)

 

asaba 著者:asaba

【androidJava・fileProvider】外部ファイルを参照してくれない時の対処法

android7.0から利用が義務づけられているfileProviderですが、これを使ったファイルの保存方法が少し癖があったので載せておきます。今までのアンドロイド(5.0まで)の場合はEnvironment.getExternalStoragePublicDirectory()の後にDIRECTORY_DCIMを引数にしてファイル名を付けてあげれば自動で保存してくれていたのですが、7.0以降はなぜか全く別のディレクトリを探索する使用になっており、ここの軌道修正に随分と手を焼いてしまいました。ではどうやってファイルを保存したかというと下のpath.xmlを参照してみます。

</pre>
<pre><?xml version="1.0" encoding="utf-8"?>
<paths xmlns:android="http://schemas.android.com/apk/res/android">
    <external-path name="storage/emulated/0" path="."/>
</paths></pre>
<pre>

三行目のname内。ここはandroid23以前でいつも参照されるファイルの保存場所になります。

「/storage/emulated/0/DCIM/Camera/21073354.jpg」<-は、android5.0で保存したファイルのディレクトリの全長になります。本来ならこのように自分でディレクトリを参照して探してくれるのですが、android7.0以降だとnameを適当な名前にしてしまうとその名前のディレクトリを探し始めるのでファイルが存在しないよと言われてしまう仕組みになっていました。

「/hogeFile/DCIM/Camera/21080925.jpg:picFile」では、本来存在しないはずの「hogeFile」を探してしまうのでエラーになります。という訳でpath.xmlファイルのnameには必ず外部ストレージと同じ名前をつけてあげてねという手厳しい指摘でした。というかどこにも書いていないのでものすごく大変でした今回・・・。

もし、fileProviderを使っていてファイルが保存できなかったり読み込めなかったときはxmlファイルのnameを疑ってみてくださいね。