カテゴリーアーカイブ Java

村上 著者:村上

【Android】WebViewでLeafletのアイコンが表示されない【未解決】

タイトルにもある通り、未解決です…。
Android の WebView で地図が含まれている Web ページを表示しているのですが、何故かアイコンが表示されません。
Web ページをブラウザで表示してみると、正しく表示されるので、恐らく Android の設定かな?と思い、調べています。

 

で、試してみたのが WebSettings での設定変更です。

WebSettings|Android Developers
https://developer.android.com/reference/android/webkit/WebSettings.html

JavaScript を有効にする setJavaScriptEnabled メソッドは指定されていたので、それ以外を調査。
で、他の記事を参考にしながら、下記の 3つを追加しました。

webSettings.setAllowFileAccessFromFileURLs(true);
webSettings.setAllowUniversalAccessFromFileURLs(true);
webSettings.setMixedContentMode(WebSettings.MIXED_CONTENT_ALWAYS_ALLOW);

上記の設定では、file スキームによるアクセスを許可にし、https/http 混在コンテンツを表示できるようにしています。
…が、これでもダメでした…。

ブラウザ上では発生しない、「Uncaught ReferenceError: jQuery is not defined.」エラーがあったので、てっきり何かがブロックされているのが原因かと思ったのですが…。
次は jQuery のエラーから攻めてみたいと思います。

 

以上、Android の WebView で地図が含まれている Webページを表示できないエラーでした。
引き続き調査し、解決出来たら改めて紹介したいと思います。

  • この記事いいね! (0)
asaba 著者:asaba

【android WebView】webViewに被せたアクションバーに処理を実装する方法

最近になってまたWebViewを触り始めました。webViewってjavascriptとかのイメージが強いですがandroidでも頑張れば実装できるみたい

ですね。しかもこっちはネイティブだから処理速度も安定しているときたので使いこなせれば開発の引き出しが増えそうですね。

今回はそのwebviewを使っていて、アクションバーの中のアイコンをタップしたときに何らかの処理をするメソッドを載せていきます。

 

タップしたアイコンに応じて処理を切り分けるには、onOptionsItemSelected(MenuItem item)メソッドを使う必要があります。

このメソッドは、ヘッダーに当たるアレ。即ちアクションバーに配置したアイコンに応じて処理をswitchで分岐させる役割を

担っています。

例えば、switchの引数idの中身がhomeだった場合は、finish();で終了させてホームボタンにバックさせます。

 

<pre>@Override
public boolean onOptionsItemSelected(MenuItem item) {
    
    int id = item.getItemId();
    WebView webView = (WebView) findViewById(
            R.id.webView);
    switch (id) {
        case android.R.id.home:
            finish();
            break;
        case R.id.menu_share:
            ShareCompat.IntentBuilder builder = ShareCompat.IntentBuilder.from(this);

            String url = webView.getUrl();
            
            builder.setText(url);
            builder.setType("text/plain");
            
            builder.startChooser();
            break;
        case R.id.reload:
            webView.clearCache(true);
            webView.reload();
            break;
    }
    return super.onOptionsItemSelected(item);
}</pre>

 

このように、一般的なアプリのアクションバーにあるページ更新やシェア機能も切り分けて実装することができます。

 

  • この記事いいね! (0)
asaba 著者:asaba

【androidJava】ads.MobileAdsInitProvider(ADMOB)を使おうとしてはまったこと

MobileAdsInitProviderは、アプリに広告を表示させることができるライブラリで、ブログやショッピングサイトを取り扱うアプリではよくお目にかかります。

今回はこのライブラリが必要になったので導入してみたのですが、下のエラーを出した後に落ちてしまいました。

 


java.lang.RuntimeException: Unable to get provider com.google.android.gms.ads.MobileAdsInitProvider: java.lang.IllegalStateException

 

どうやら、今までのライブラリと違い単にグレイドルにいれただけでは使えないもよう。

調べてみるとMobileAdsInitProviderを使うには、マニフェストへの記述が必要みたいです。アプリケーションタグを閉じる前に

こんな感じでいれてあげれば解決できます。

 


<meta-data
android:name="com.google.android.gms.ads.AD_MANAGER_APP"
android:value="true"/>

 

こちらの記事のurlを参考にしました

グレイドル関係のエラーが出るたびにこのブログに載せている気がします。ですがグレイドル関係の記事は数が少ないのに対して同じよう

なエラーで困っている人が多くいるので少しでも助けになれたらなと思っております。

なお、日本語版の公式ではこの記事の対策方法が書いていないので注意してください。(見るなら英語版で)

  • この記事いいね! (0)
asaba 著者:asaba

【androidGradle】minSDKVersionの重要性

前にも似たような話題を振ったような・・・グレイドル系の記事って何回出したか分からないので記憶が曖昧になっております。

問題のエラーはこちらです。↓


Error:Execution failed for task ':processDebugManifest'.
> Manifest merger failed : uses-sdk:minSdkVersion 1 cannot be smaller than version 8 declared in library [com.twitter.sdk.android:twitter:1.4.0] C:\Users\swift0910\.gradle\caches\transforms-1\files-1.1\twitter-1.4.0.aar\54bb48e8e15821fe4455ab493a1ff43e\AndroidManifest.xml as the library might be using APIs not available in 1
Suggestion: use a compatible library with a minSdk of at most 1,
or increase this project's minSdk version to at least 8,
or use tools:overrideLibrary="com.twitter.sdk.android" to force usage (may lead to runtime failures)

 

見かたはシンプルで、今のままではminSdkVersionのレベルが1になっており、バージョン8以上のライブラリを使うことはできませんという感じです。

もしmisSDKVersionが現存のライブラリよりバージョンが低かった場合は、そのライブラリより上の数字で設定するとビルドできると

思うので試してみてください。何も設定していない場合はデフォルトでnullになるので当然ライブラリも使えません。なので

minSDKVersionは、仕様が変わってくるAndroid5.0・API21辺りで設定しておきましょう。

 

参考サイトー>http://y-anz-m.blogspot.com/2015/09/minsdkversion.html

 

  • この記事いいね! (0)
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);

 

  • この記事いいね! (0)
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>

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

  • この記事いいね! (0)
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でもうレガシーだなんて知りませんでした。

  • この記事いいね! (0)
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が表示されます。一回画面を離れたときに、セキュリティの都合でデータを残したくないアプリを作りたい時に有用そうですね。

  • この記事いいね! (0)
asaba 著者:asaba

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

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

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

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

 

  • この記事いいね! (0)
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を疑ってみてくださいね。

 

  • この記事いいね! (0)