カテゴリーアーカイブ Android

村上 著者:村上

【Cordova】アプリがオフラインになったことを検知する方法

タイトル通り、今回はアプリ(というより、アプリが実行されている端末?)がオフラインになったことを検知する方法についてです。
現在開発中のアプリは、当然ながらデータ通信が行われているので、アプリ利用時は常にオンラインである必要があるのですが、何らかの原因でオフラインになったときに、それを通知して、ネットワーク環境の確認を促すようにしたかったためです。

 

今回は、下記のCordovaのページを参考にしました。

オフライン – Apache Cordova
https://cordova.apache.org/docs/ja/3.1.0/cordova/events/events.offline.html

実装方法はとても簡単で、プラグインの追加なども不要!
私の環境では、index.js ファイル内に、下記のコードを追加するだけでした。

document.addEventListener("offline", onOffline, false);

function onOffline() {
    // オフラインの時に実行したい処理
}

サンプルコードを見ると、追加ファイルは index.html である場合もあるようです。
こちらは、開発環境に合わせて変更してください。

あとは、onOffline() 内に実行したい処理を記述すればOKです。
私は、Toast でエラーメッセージを表示しています。

なお、iOS の初回起動時、最初の オフラインイベントは少なくとも起動に 1秒かかりますとのこと。
こちらは仕様のようなので、諦めて受け入れるのが良さそうです。
また、Android や iOS は問題ありませんが、Windows Phone 7 など、端末によっては、オフラインが検知できないこともあるようなので、対応しているか十分注意してください。
…Android と iOS が対応していたら、ほぼほぼ大丈夫だとは思いますけどね。

 

以上、アプリがオフラインになったことを検知する方法でした。
プラグインも不要なので、実装しておいても良いと思います。

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

【Cordova】アプリにステータスバーを追加する方法

設定したのがずいぶん前だったので忘れていました…。
今回は、Cordova で開発しているアプリにステータスバーを追加する方法についてご紹介します。
Android なら、特に意識せずに開発ができるのですが、iOS で、特にヘッダーが固定されているデザインの時にデザインが少々崩れます。
ステータスバーのエリアまで、アプリの画面になるので、ヘッダー固定で、それ以外の要素がスクロールになったとき、ヘッダーを突き抜けてスクロールしてしまいます。
スクリーンショットを取り忘れてしまったので文章で書いておりますが、わかりにくいですね…。
発生した現象については、下記の記事が参考になります。

cordova-plugin-statusbarの使い方。 – Qiita
https://qiita.com/nagao_norihiro/items/2e6189c147098dc63ab9

そのため、iOSを対象としているときや、どうしても必要ない!という場合以外は、念のため導入しておくことをおすすめします。

 

さて、ステータスバーを設定する方法ですが、cordova-plugin-statusbar というプラグインを使用します。
GitHub のページは下記から。

GitHub – apache/cordova-plugin-statusbar: Apache Cordova
https://github.com/apache/cordova-plugin-statusbar

プラグインのインストールは、下記のコマンドを実行します。

cordova plugin add cordova-plugin-statusbar

インストールが終わったら、config.xmlpreference で設定します。
まず、ステータスバーを有効にする場合は、下記を追加します。

<preference name="StatusBarOverlaysWebView" value="false" />

次に、ステータスバーの背景色を下記で指定します。

<preference name="StatusBarBackgroundColor" value="#000000" />

なお、色の指定は16進数 6文字で指定してください。
白色だからと、うっかり #FFF と書いたところ…青になりました。
きっちり 6文字で記載してください。

あとは、iOS でよくある、ステータスバーとタップすると上までスクロールするという処理を追加したい場合は下記を追加ます。

<preference name="StatusBarDefaultScrollToTop" value="true" />

デフォルト値は false なので、ステータスバータップでスクロールをさせたい場合は、true に設定します。

最後に、私は使いませんでしたが、ステータスバーのスタイルを指定するときは、下記を使用します。

<preference name="StatusBarStyle" value="lightcontent" />

設定できるオプションは、default, lightcontent, blacktranslucent, blackopaque があるようです。
デフォルト値は lightcontent です。

 

以上、Cordova アプリにステータスバーを追加する方法でした。
Android のみであれば任意でOKだと思いますが、iOS で利用するのであれば、導入しておくことをおすすめします。

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

【Cordova】アプリにスプラッシュスクリーンを追加する方法

先日の記事で、アプリの画面を iPhoneX に対応させる方法について紹介しましたが、その中で取り上げた「cordova-plugin-splashscreen」というプラグインについてしっかりとしたご紹介をしていなかったので、今回はそちらのプラグインについて。
名前のとおり、アプリにスプラッシュスクリーンを追加するためのプラグインです。
なお、スプラッシュスクリーンとは、アプリを起動した時に表示される画面のことです。
LINE を思い出してもらえれば分かりやすいかと思います。

GitHubのページはこちらから。

GitHub – apache/cordova-plugin-splashscreen: Apache Cordova Plugin splashscreen
https://github.com/apache/cordova-plugin-splashscreen

 

では、実装方法です。
まず、下記のコマンドを実行してインストールします。

cordova plugin add cordova-plugin-splashscreen

もしくは、下記でも可です。

cordova plugin add https://github.com/apache/cordova-plugin-splashscreen.git

インストール後は、/res/screen ディレクトリを作成し、その中に各プラットフォーム名のディレクトリを作成します。
例えば、Android、iOS であれば、/res/screen/android/res/screen/ios ディレクトリを作成します。
各プラットフォームのファイル内に、表示したいスプラッシュスクリーンの画像を置きます。

あとは、config.xml に下記のようにスプラッシュページの設定を追加します。
なお、ファイル名は適宜変更してください。

<platform name="android">
    <splash src="res/screen/android/splash-land-hdpi.png" density="land-hdpi"/>
    <splash src="res/screen/android/splash-land-ldpi.png" density="land-ldpi"/>
    <splash src="res/screen/android/splash-land-mdpi.png" density="land-mdpi"/>
    <splash src="res/screen/android/splash-land-xhdpi.png" density="land-xhdpi"/>
    <splash src="res/screen/android/splash-port-hdpi.png" density="port-hdpi"/>
    <splash src="res/screen/android/splash-port-ldpi.png" density="port-ldpi"/>
    <splash src="res/screen/android/splash-port-mdpi.png" density="port-mdpi"/>
    <splash src="res/screen/android/splash-port-xhdpi.png" density="port-xhdpi"/>
</platform>
<platform name="ios">
    <splash src="res/screen/ios/Default~iphone.png" width="320" height="480"/>
    <splash src="res/screen/ios/Default@2x~iphone.png" width="640" height="960"/>
    <splash src="res/screen/ios/Default-Portrait~ipad.png" width="768" height="1024"/>
    <splash src="res/screen/ios/Default-Portrait@2x~ipad.png" width="1536" height="2048"/>
    <splash src="res/screen/ios/Default-Landscape~ipad.png" width="1024" height="768"/>
    <splash src="res/screen/ios/Default-Landscape@2x~ipad.png" width="2048" height="1536"/>
    <splash src="res/screen/ios/Default-568h@2x~iphone.png" width="640" height="1136"/>
    <splash src="res/screen/ios/Default-667h.png" width="750" height="1334"/>
    <splash src="res/screen/ios/Default-736h.png" width="1242" height="2208"/>
</platform>

以上で設定は終了です。
なお、Android は、下記の設定を追加することで、スプラッシュスクリーンの表示時間を変更することもできるとのこと。

<preference name="SplashScreenDelay" value="10000" />

こちらも config.xml に追加してください。
変更前のデフォルト値は 3000 です。
私はやった事がないのでわかりませんが…もし、表示時間を変更する必要がある場合はご活用ください。

 

以上、Cordova アプリにスプラッシュスクリーンを追加する方法でした。
スプラッシュスクリーンを追加すると、一気にアプリらしくなるのでおすすめです。
また、iPhoneX の画面レイアウトにも対応できるので、是非導入をご検討になってはいかがでしょうか。

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

【Cordova】プラットフォームごとにCSSファイルを切り替える方法

今回はタイトル通り、CordovaアプリでプラットフォームごとにCSSを切り替える方法について。
デザインにもよるかもしれませんが、覚えておくと意外と便利です。

今回参考にさせていただいた記事はこちら。

第3回:Apache Cordovaでプラグインを使ってみよう (1/5):連載:Visual Studio+Apache Cordovaで始めるiOS/Androidアプリ開発 – @IT
http://www.atmarkit.co.jp/ait/articles/1605/23/news032.html

こちらの2ページ目に記載されている内容です。

 

こちらの設定はそれほど難しくなく、まずは大元となるCSSを作成し、アプリ内で読み込みます。
ここでは仮に style.css としておきます。
次に、プロジェクトのルートディレクトリ直下に merges ディレクトリを作成し、更にそのフォルダ内に、android、ios など、プラットフォーム名のディレクトリを作ります。
最後に、各プラットフォーム内にcssディレクトリを作成し、その中に、上で作成した style.css ファイルをコピー&ペーストします。
イメージとしてはこんな感じ。

merges
 ┗ android
   ┗ css ― style.css
 ┗ ios
   ┗ css ― style.css

あとは、各プラットフォームの style.css ファイルを変更すればOKです。

なお、大元の CSS から変更がない場合は、そのプラットフォームのディレクトリを作成する必要はありません。
例えば、iOS はデザインを追加もしくは変更したいけど、Android はそのままでOKという場合は、ios ディレクトリ以下のみを作成するだけで、変更が反映されます。

注意点というか推奨ですが、こちらを実装する場合は、切り替える必要のある記述のみを 別ファイルに抜き出すことをおすすめします。
一度こちらの方法でCSSを切り替えたとき、CSSファイルをそっくりそのままコピーして各プラットフォームごとに配置してしまったので、CSS ファイルの内容を把握するのが若干大変でした。
是非、私と同じわだちを踏まないようにしてください…。

また、JavaScript や画像でも上記の方法を用いれば、同様にプラットフォームごとに処理を変更することができます。
が、私は試したことがないので…興味やその必要性のある方は、是非実際にお試しください。

 

以上、プラットフォームごとにCSSを切り替える方法でした。
もし以前の私のように、同じことにお悩みの方がいらっしゃいましたら、参考にしていただければ幸いです。

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

【Android】ActivityのメソッドをAdapterで呼び出す方法

ちょっと悩んだので、今後のためにまとめ。
Adapter内で、Activity に記述したメソッドを呼び出す方法です。
Interface を使用しています。

なお、今回参考にしたのはこちらのサイトです。

Android – Call Activity method from adapter – Stack Overflow
https://stackoverflow.com/questions/12142255/call-activity-method-from-adapter

2つ目のアンサーに書かれている内容を参考にしました。

 

では早速コードを書いていきます。
まず、インターフェースを作成します。
で、Adapter で呼び出したい& Activity に追加するメソッドを定義します。

public interface [インターフェース名] {
    void test();
}

なお、この時指定するのは、メソッド名・引数・戻り値のみで、処理内容は記述しません。

次に、Activityに、上で作成したインターフェースを、下記のように implements で実装します。

public class [アクティビティ名] extends AppCompatActivity implements [インターフェース名] {

Android Studioを使用している場合、上記のようにインターフェースを追加すると、メソッドをオーバーライドして!というエラーになるので、Alt+Enter で言われるがままにメソッドを追加します。
なお、追加するメソッドは下記のとおりです。
最初に @Override が付くのにお気を付けください。

@Override
public void test() {
    // メソッド内で行いたい処理
}

そして Adapterに、下記を追加します。

public [アダプター名] extends BaseAdater{
    private [インターフェース名] listener;

    public [アダプター名]([インターフェース名] listener){
        this.listener = listener;
    }
}

で、あとは下記のように使いたいタイミングでメソッドを呼び出すだけです。

listener.test();

 

で、私がハマったのが、Adapterでの定義で、継承しているのが BaseAdapter ではなかったので、上記の記述では動かなかったんですよね…。
なので、下記のように修正。
まず、Adapter。

private int mResource;
private List<EntryListItem> mItems;
private LayoutInflater mInflater;
private Context mContext;
private ListViewInterface listener;

public [アダプター名](Context context, int resource, List<EntryListItem> items, [インターフェース名] listener) {
    super(context, resource, items);

    this.mContext = context;
    mResource = resource;
    mItems = items;
    mInflater = (LayoutInflater)context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
    this.listener = listener;
}

一部必要ないものも混じっていますが、それはスルーしてください。

次は、このままでは、Activitiy でエラーになるので Adapter を new している所を修正します。

[アダプター名] adapter = new [アダプター名](getBaseContext(), R.layout.[レイアウトファイル名], item, this);

最後の this がインターフェースを指しています。
ここが分からず、少し悩みました…。

 

以上、Activity内のメソッドをAdapterで呼び出す方法でした。
もしかしたら、ListViewを扱うときなどに使うことがあるかもしれませんので、その際は是非ご活用ください。

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

【Android】ListView要素にボタンを追加すると要素自体のクリックイベントが呼ばれない

長いタイトルですみません。
Android アプリでカスタム ListView を利用しているとき、List の要素に Button(ImageButton)を追加したところ、要素自体のクリックイベントが呼ばれなくなったので、その対処法について。
実はこれ、以前も経験していて対処法があることは覚えていたのですが、その内容は失念していたので、備忘録としてまとめ。

なお、参考にさせていただいたサイトはこちらから。

ボタン付きのListViewを実装してみる – Qiita
https://qiita.com/maromaro3721/items/6ac3cba4f090662adabf

 

で、対処法ですが、ListViewItem のレイアウトを記述しているXMLファイルに、下記の一行を追加するだけ。

android:descendantFocusability="blocksDescendants"

具体的には下記のとおりです。

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:descendantFocusability="blocksDescendants">

    <TextView
        android:id="@+id/title"
        android:layout_width="match_parent"
        android:layout_height="wrap_content" />
    <ImageButton
        android:layout_width="50dp"
        android:layout_height="match_parent"
        android:src="@drawable/icon"
        android:scaleType="fitCenter"
        android:id="@+id/btn"
        android:layout_alignParentRight="true"/>
</RelativeLayout>

5行目に記述しています。
これを指定し忘れると、ListViewItem のボタンは反応するのに、ListViewItem 自体がクリックできなくなるのでご注意ください。
ちなみに、それ以外の指定等はなにもなく、これだけです。

なお、ListViewItemに指定したボタンのクリック検知は、ListAdapter の getView関数内で行います。
抜粋するとこんな感じ。

@Override
public View getView(int position, View convertView, ViewGroup parent) {
    View view;

    if (convertView != null) {
        view = convertView;
    } else {
        view = mInflater.inflate(mResource, null);
    }

    // ボタンのクリックイベント
    ImageButton btn = view.findViewById(R.id.btn);
    btn.setOnClickListener(view1 -> {
        // ボタンクリック時に行いたいたい処理
     });

     return view;
}

 

以上、カスタムしたListView にボタンを追加した際、ListViewItem自体のクリックイベントが呼ばれなくなる現象とその対処法についてでした。
同じことでお困りの方は、是非お試しください。

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

行儀の悪いAndroidアプリには眠ってもらおう。 アプリのバックグラウンド動作を制御できるアプリ”Greenify”

Androidを長期間使っていると悩まされるのが端末の動作の低速化。
動作がサックサクなフラグシップモデルのスマホを買ったはずなのに、いつの間にか常にCPUをフル稼働させ、一つの動作に数秒かかり、スクロールすらままならない状態に…なんてことになってしまうことがあります。

その原因に、バッテリーや内部部品の経年劣化とか、そもそもアプリが要求するスペックが上がってきた…とかいうどうしようもない場合(そもそもAndroidの仕組み上どうしても重くなりやs…ゲフンゲフン)もあるのですが、大抵の場合、一度端末を初期化すると嘘のように改善したりすることもよくあります。

初期化すれば治るということはソフトウェア的な原因…つまり端末を購入してから今までにインストールしたアプリにある…という可能性を考える必要が出てきます。

実際、Androidのアプリは権限が比較的自由なこともあり、一見常駐する必要のなさそうなアプリがガンガン常駐してることもあります。

特にスーパーや飲食店、衣料品店などの会員アプリは広告をだしたり、何か情報を取得するために常駐してたりします。他にも”まさかこのアプリが…?”っていうようなアプリが常駐してることも結構あるようです。

そんな常駐アプリに対して、前はタスクキラー系のアプリが有効とのことで一時期よく使われてましたが、最近のアプリはタスクキルしてもすぐに再起動する”ゾンビアプリ”が多く、タスクキラーでは再起動が走る分却って重くなってしまう状況でした。

そこで、”そもそもアプリが勝手に起動しないようにブロックしてしまおう”という発想から出てきたのが、今回紹介するGreenifyというアプリです。

Greenify
Greenify
開発元:Oasis Feng
posted withアプリーチ

Greenifyは、現時点でバックグラウンドで動作しているアプリを一覧化して表示してくれ、停止させたいアプリを個別に停止させることができるようになっています。

右上の+をタップすると

このように、現在バックグランドで動作中のアプリが一覧で表示されます。

今回は例で、LINEを自動起動させないようにしてみたいと思います。
LINEの項目を選択して、右下の✔ボタンをタップすればOK。

休止リストに追加されました。

これで、自分で明示的に起動しない限り、LINEがバックグラウンドで動かなくなりました。

実際に自分のスマホにGreenifyを入れて使っていますが、体感そこそこ端末の動作が軽くなりました。

一部アプリはGreenifyで対処できないのもありますが、リストアップされることでどのアプリが負荷を与えているかを知ることができるので、それだけでもかなりありがたいですね。

スマホが重くて悩んでいる方は是非一度試してみてください。

  • この記事いいね! (1)
村上 著者:村上

【HTML】Android4ではinput type=”file”で画像選択時にカメラかギャラリーかを選べない

同僚さんに以前、相談というかこんな現象が起こっているとの報告を受けていたのですが、ようやく多少時間が取れたので確認中。

なんでも、Android 4以降の端末では、HTML の <input type="file" />で画像を選択する際、カメラもしくはギャラリーのどちらか一方でしか画像を選べないとのことでした。
試してみましたが、確かにその通りの挙動に!

 

で、調査している中、こちらの記事を発見。

Androidの input type=”file” accept=”image/*” 事情 – みかづきブログ その3
http://kimizuka.hatenablog.com/entry/2016/12/01/215013

全く同じことにお悩みの方がいらっしゃいました…!

記事内では、「Android4.4.2でも再現する機種としない機種があるのが謎で、Chromeのバージョンに依存するバグなのか、機種依存のバグなんだと判断しました。」とのこと。
ということは、Androidのバージョンは関係ないのかな?

どうにかならないか、と調べたところ、inputタグのcapture属性を使うとカメラを起動できるようでした。

/* リアのカメラを起動 */
<input type="file" accept="image/*" capture="environment" />

この機能を使って、それぞれ「ギャラリーから選択」と「カメラで撮影」を分けて用意するしかないのかなと考えています。
この辺は、要検討です。

 

以上、HTML の <input type="file" /> の挙動についてでした。
参考にした記事では、カメラの起動をあきらめる。とのことだったので、それも検討したほうが良いのかも知れません。

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

【Android】文字列をMD5でハッシュ化する方法

使用される場所が大分限定的かもしれませんが…今回、分け合って調べたので備忘録としてまとめ。
JavaでMD5ハッシュを行う方法です。

今回参考に…というか、コードをまるっとコピーさせていただいたサイトはこちらから。

後ろ向きに全力疾走: AndroidでMD5ハッシュを使う
http://taiwanology.blogspot.com/2012/06/androidmd5.html

参考にさせていただいた記事って、こうでもしないとすぐにどこかにやってしまうので…ご紹介という形で保存します。

 

コード自体はこちら。

public String md5(String s) {
    try {
        // Create MD5 Hash
        MessageDigest digest = java.security.MessageDigest.getInstance("MD5");
        digest.update(s.getBytes());
        byte messageDigest[] = digest.digest();

        // Create Hex String
        StringBuffer hexString = new StringBuffer();
        for (int i=0; i<messageDigest.length; i++)
            hexString.append(String.format("%02x", messageDigest[i] & 0xff));
        return hexString.toString();

    } catch (NoSuchAlgorithmException e) {
        e.printStackTrace();
    }
    return "";
}

関数化されているので、そのままコピーして使うことができました。
なお、上で紹介した記事内では、11行目が

hexString.append(Integer.toHexString(0xFF &amp; messageDigest[i]));

になっていますが、コメント欄で、「この書き方では0埋めされない」とのことで、

hexString.append(String.format("%02x", messageDigest[i] & 0xff));

上記の記述があったので、こちらに書き換えました。
記事のコードをコピーした時は、11行目でエラーが発生していましたが、こちらに修正したところ、エラーもなく動作しました。

 

以上、Javaで文字列をMD5ハッシュ化する方法でした。
今回はマルコピしたコードの紹介でした…。
が、私としては凄く便利で助かったので、是非ご活用ください。

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

【androidJava】READ_EXETERNAL_STORAGEは必要なかった

ギャラリーから画像を読み込む機能を開発していてパーミッション関係のエラーで躓いたのでメモします。

ペイントの動きが悪かったのでそのまま抜粋してきました。

java.lang.SecurityException: Permission Denial:

writing com.android.providers.media.MediaProvider uri content://media/external/images/media from pid=19325, uid=10589

requires android.permission.WRITE_EXTERNAL_STORAGE, or grantUriPermission()

 

ストレージを読み込むにはREADだけでなくWRITE_EXETERNAL_STORAGEのほうも必要だったみたいなので追加して解決。

<pre><uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" /></pre>

このWRITE_EXETERNALSTORAGEは、READ_EXETERNAL_STORAGEの役割である読み込みも兼業しているので、実際に

マニフェストに書くのはこのWRITEのほうだけでも問題ないみたいですね。

このエラー、というかただ追加するだけの作業だったのですが、自分の備忘録を兼ねての投稿なのでそんなの知ってるよっていう

かたも多いかもしれませんがご容赦ください。

 

これでパーミッションの設定も無事にできたことなので近日にギャラリーから画像の名前を取得するコードを

載せようかと考えています。

画像を扱ったコードを正しく書ければ大分できることが増えますね~。

 

以下、参考にさせていただいたサイトです。

[Android] 外部ストレージにファイルを保存する WRITE_EXTERNAL_STORAGE

Android:KitkatのREAD_EXTERNAL_STORAGEと外部記憶領域

Androidアプリ開発「外部ストレージアクセスのパーミッション」

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