投稿

ラベル(Android)が付いた投稿を表示しています

Google Playでアプリケーションの公開申請がRejectされた場合の対応

イメージ
先日Google Playでアプリケーションの公開のための申請を行ったところ、リジェクトされてしまったので、その際に対応した内容です。 リジェクトされる理由はいくつかあると思いますが、今回のケースは「 Reviewを行うためには認証情報が必要 」と行った内容でした。 リジェクト内容 結果はメールで以下のような内容で返ってきました。 App status: Rejected Your app has been rejected and wasn't published due to this policy issue. If you submitted an update, the previous version of your app is still available on Google Play. Need login credentials for app review In order for us to review your app for compliance with Developer Program Policies, we will need you to provide valid login credentials for your app. If users need credentials to access your app, please provide all appropriate credentials via Play Console. 最近ではGoogle Playでもアプリケーションの新規・更新時にレビューが行われ、ポリシーに準拠しているかどうかが確認されます。しかしアプリケーションが認証を伴うものの場合、確認用(やデモ用)の認証情報を一緒に申請しなくてはなりません。 なので確認用の認証情報を一緒に申請すればこの問題は解決します。 確認用の認証情報の設定 アプリのアクセス権を設定 ポリシー > アプリのコンテンツ > アプリのアクセス権 > 管理 を開きます。 デフォルトで「すべての機能が特別なアクセス権を必要とすることなく利用できる」にチェックが入っていますので、「すべてまたは一部の機能が制限される」をチェックします。 「+新しい手順の追加」をクリッ

【Android】ListViewで最終行までスクロールしたことを判定する

ListViewにデータの一部を表示し、最終行までスクロールした際に追加で読み込み処理を入れたいときに判定するためのロジックです。 以前作成した ListViewアプリケーション がありますので、これを使って最終行までスクロールしたときに処理を入れてみたいと思います。 https://www.s-watanabe.work/2020/12/androidcheckbox.html 実装 方法としてはsetOnScrollListenerのonScrollメソッド内で引数の値を確認して判定します。onScrollメソッドの引数は以下です。 AbsListView absListView - スクロール中のView (今回は使用しない) int firstVisibleItem - 先頭のindex int visibleItemCount - 見えている件数 int totalItemCount - ListViewのItem総件数 ※公式ドキュメントは以下です。 https://developer.android.com/reference/android/widget/AbsListView.OnScrollListener#public-methods_1 onScrollメソッドで最終行まで到達したことを判定する // メンバー変数 Boolean isLastLine = false; (省略) listView.setOnScrollListener(new AbsListView.OnScrollListener() { @Override public void onScrollStateChanged(AbsListView absListView, int i) { // } @Override public void onScroll(AbsListView absListView, int firstVisibleItem, int

[Android]簡単なTwitter Client Applicationを開発する

イメージ
Androidで、自分のTwitterアカウントと連携し、リツイートした一覧を表示するだけの簡単なアプリケーションを開発してみようと思います。 事前準備 まず事前準備としてTwitterアカウントとTwitter Deceloperアカウントの2つが必要です。Twitterアカウントに関してはほとんどの人が持っていると思うので割愛します。 Twitter Developerアカウントを作成する Twitter DeveloperのページからDeveloperアカウントの登録を行います。長いので読み飛ばしてもらっても大丈夫です。 Twitter Developerにアクセス https://developer.twitter.com/en メニューからApplyを選択 Apply for developer accountを押す 用途を選択する ここでは自分自身についてのことと、Twitter Developerアカウントをどのように使用するかといったことを選択します。 Hobbyist (趣味でやっている)、 Build Tooles for Twitter users (Twitterユーザー向けのビルドツール)、を選択しました。 ユーザーの基本情報を入力する Twitter APIの使用用途を明確に記載する ここではどのようにAPIを使用するかを、英字(200文字以上)で記述します。 簡単なアプリケーションを開発する旨を、Google先生に翻訳してもらい設定しました。 アプリケーションに関する質問 アプリケーションに関していくつか質問されます。今回は分析する予定はなし、ReadOnlyのアプリケーションなのですべてNoを選択しました。 Twitterデータを分析する予定があるかどうか アプリケーションからツイート、リツイート、DM送信などを実装するかどうか Twitter以外のコンテンツを表示するかどうか 政府機関が利用できるようにするかどうか 入力内容の確認 開発者契約、ポリシーの確認 登録用のEメールが届く Eメールの完了ボタンを押して登録完了 Developer portalのダッシュボードが開くのでここをブックマークし

【Android】動画プレイヤーのコードを利用して音楽プレイヤーを作る

イメージ
以前作成した動画プレイヤーのソースコードをほぼそのまま使って今度は音楽プレイヤーを作ってみました。 ※動画プレイヤーについては以下の記事を参考 【Android】VideoViewを使って動画再生アプリを作る① -- ストレージへのアクセス権限を取得 -- 【Android】VideoViewを使って動画再生アプリを作る② -- 内部ストレージのファイル検索 -- 【Android】VideoViewを使って動画再生アプリを作る③ -- カスタムリストビュー -- 【Android】VideoViewを使って動画再生アプリを作る④ -- 全画面で動画再生 -- 【Android】VideoViewを使って動画再生アプリを作る -- 不具合修正、軽微な修正 -- 概要 アプリケーションの特徴 アプリケーションの特徴は以下のとおりで、1-2は動画プレイヤーのコードほぼそのままです。 内部ストレージからmp3ファイルを検索してリスト表示する。 チェックボックスで複数選択し、選択アイテムを連続再生する。 再生中画面では音量調節を可能にする。 再生画面でどのファイルを再生中かわかるようにする。 再生中にホーム画面へ戻ってもアプリケーション実行中はバックグラウンドで再生し続ける。 再生中のイメージ 実装 いくつかこのアプリケーションで新たに対応した内容を記載します。 音量調節 レイアウト 音量調節はSeekBarを使って行います。 <SeekBar android:id="@+id/seekBar" android:layout_width="match_parent" android:layout_height="wrap_content" /> Mp3Activity.java Activity側ではOnSeekBarChangeListenerを設定して、SeekBarのつまみを変更したイベントで音量調節を実行します。 SeekBar seekBar = findViewById(R.id.seekBar); audioManager = (AudioManager)get

【Android】VideoViewを使って動画再生アプリを作る
-- 不具合修正、軽微な修正 --

【Android】VideoViewを使って動画再生アプリを作る で作成したアプリを使っていたところ使いにくい点を発見したのでいくつか改修を入れました。 対応した内容 再生中にスリープモードにしない ファイルサイズを動画の総再生時間に変更 チェックボックスを付けて複数ファイルの再生に対応 再生中にスリープモードにしない この対応は簡単で動画再生するActivityで以下1行入れるだけです。 getWindow().addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON); ファイルサイズを動画の総再生時間に変更 これはトップ画面のファイルリストでファイルサイズを表示していましたが、あまり意味が無いので再生時間を取得して表示するようにしました。以下のようにメソッド化したのでFileオブジェクトを渡してやれば秒数が返ってきます。 /** * 動画ファイル再生時間取得 * @return int */ public static int getDuration(File audioFile) { try { MediaPlayer mediaPlayer = new MediaPlayer(); FileInputStream inputStream = new FileInputStream(audioFile);; FileDescriptor fileDescriptor = inputStream.getFD(); mediaPlayer.setDataSource(fileDescriptor); mediaPlayer.prepare(); int length = mediaPlayer.getDuration(); mediaPlayer.release(); return length / 1000; } catch (Exception e) { return 0; } } これで取得した再生時間をAdapterでListViewにセットするときに以下のように分と秒で分けてやり表示

【Android】カスタムリストビューにCheckBoxを追加したとき別の行までチェックされる事象の対応

AndroidでCheckBox付きのカスタムListViewを実装し、動作確認したところチェックした行以外の行までチェックされてしまう謎現象が発生しました。 カスタムListViewの実装については以下参照 【Android】VideoViewを使って動画再生アプリを作る③ -- カスタムリストビュー -- 今回は単純にチェックボックスと単純な名前を一つだけ持ったListを表示しています。 問題のあるコード Adapterクラス public class ListAdapter extends ArrayAdapter<String> { private int resource; private List<String> items; private LayoutInflater inflater; public ListAdapter(Context context, int resource, List<String> items) { super(context, resource, items); this.resource = resource; this.items = items; this.inflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE); } @Override public View getView(int position, View convertView, ViewGroup parent) { View view; if (convertView != null) { view = convertView; } else { view = inflater.inflate(resource, null); } TextView itemName = view.findViewById(R.id.item_name)

【Android】VideoViewを使って動画再生アプリを作る④
-- 全画面で動画再生 --

イメージ
いよいよVideoViewを使って動画ファイルを再生する部分です。 実装 アプリケーションのタイトルバーを消す まずは全画面で表示させるために、アプリケーションのタイトルバーを消します。これにはAndroidManifest.xmlのActivityのテーマ指定を以下のようにします。 AndroidManifest.xml <activity android:name=".Mp4Activity" android:theme="@style/Theme.AppCompat.Light.NoActionBar.FullScreen" /> ナビゲーションバーを消す 次に下段のナビゲーションバー(戻るボタンやホームボタンのバー)を消します。これはActivity内のコードで以下のように制御します。 View decorView = getWindow().getDecorView(); decorView.setSystemUiVisibility( View.SYSTEM_UI_FLAG_FULLSCREEN | View.SYSTEM_UI_FLAG_HIDE_NAVIGATION ); 動画再生 Intentで受け取ったファイルパスをVideoViewに読み込みます。 読み込みの完了をOnPreparedListnerより受け取り、再生を開始します。その際に動画縦幅と横幅を比べて横長の動画の場合、画面の向きを変えて最大サイズで再生できるようにしています。 String path = getIntent().getStringExtra("path"); videoView = findViewById(R.id.videoView); videoView.setVideoPath(path); videoView.setOnPreparedListener(new MediaPlayer.OnPreparedListener() { @Override public void onPrepared(MediaPlayer mediaPlayer) { if (mediaPlayer.getVideoWidt

【Android】VideoViewを使って動画再生アプリを作る③
-- カスタムリストビュー --

イメージ
ListViewコントロールをカスタマイズして、1つのレコードに様々な情報を表示する方法です。 実装 アイテムクラス まずはListViewの1レコードを表すアイテムクラスの定義です。次の属性を持ちます。 ファイル名 ディレクトリ サイズ 最終更新日 Item.java import java.util.Date; public class Item { private String name; private String path; private long size; private Date lastModified; public void setName(String name) { this.name = name; } public String getName() { return name; } public void setPath(String path) { this.path = path; } public String getPath() { return path; } public void setSize(long size) { this.size = size; } public long getSize() { return size; } public void setLastModified(Date lastModified) { this.lastModified = lastModified; } public Date getLastModified() { return lastModified; } } レイアウト 1レコード分のレイアウトを定義します。 layout/list_item.xml <?xml version="1.0" encoding="utf-8"?> <LinearLay

【Android】VideoViewを使って動画再生アプリを作る②
-- 内部ストレージのファイル検索 --

イメージ
内部ストレージのファイル検索について実装します。またファイルの検索中はプログレスダイアログを表示して操作できない状態にします。 実装 プログレスダイアログを表示 後述しますが、ファイル検索は並列処理(マルチスレッド)で行い、プログレスダイアログの表示をメインスレッドで行います。こうしておかないと画面の更新ができないためです。 final ProgressDialog progressDialog = new ProgressDialog(MainActivity.this); progressDialog.setTitle("ファイル検索中"); progressDialog.setMessage("---"); progressDialog.setProgressStyle(ProgressDialog.STYLE_SPINNER); progressDialog.setCancelable(false); progressDialog.show(); 内部ストレージのパスを取得 まずは検索する場所、内部ストレージのパスは以下で取得できます。また、これはマルチスレッドの中で使うのでfinalで宣言しておきます。 final String path = Environment.getExternalStorageDirectory().getPath(); 並列処理の実装 並列処理は Thread クラスを使用します。なお、通常はスレッド内からメインスレッドのUI (ここではプログレスダイアログ) へのアクセスはできません。これを解決するために Handler クラスを利用します。メインスレッドで定義した Handler クラスの run メソッドによりメインスレッドのUIの操作が可能になります。ここではファイル検索が終了したらメインスレッドのプログレスダイアログを閉じています。 final Handler handler = new Handler(); new Thread(new Runnable() { @Override public void run() { // ファイル検索開始 searchFiles(path);

【Android】VideoViewを使って動画再生アプリを作る①
-- ストレージへのアクセス権限を取得 --

イメージ
小さい子供に動画を見せていると、画面を触って停止してしまったりホーム画面へ戻ってしまったりということがあるので、これを防止した単純な動画再生アプリを作ってみます。 要件 はじめにざっくりとした要件をまとめます。 内部ストレージからmp4ファイルを検索 ※SDカードなどの外部ストレージは今回対象外 動画ファイル名をリスト表示 (できれば動画のイメージを取得してリスト上に表示したい、どうやって取得するんだろう...) ファイル名タップで全画面表示で動画再生 再生中に画面をタップしても何もしない 最後まで再生したら最初に戻って繰り返す 実装については以前作った Json Viewer の大部分が流用できると思うのでこれを改修していく形になります。 https://github.com/s-watanabe-apps/json-viewer.git こちらの実装についての詳細を、次回リスト編と再生編に分けて解説していこうと思います。 実装 内部ストレージからファイルを検索するので、アプリケーションにストレージへのアクセス権限が必要です。 通常権限を取得する場合、Android OSにより以下右のダイアログを出してユーザーに許可を求めます。しかし何のために該当の権限を利用するかこのダイアログだけではわかりません。左画像のように権限の利用目的を明示してあげるのが親切な設計です。 ※アプリケーションから権限の取得方法には以前 記事 にしましたが、今回は以下のように利用目的の表示を明示するようにしました。 権限設定 AndroidManifest.xml AndroidManifest.xmlに以下を追加します。 <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" /> 権限の確認と利用目的の説明 まずは権限が許可されているかをチェックし、許可されていない場合(もしくは初回起動のとき)に利用目的をユーザーに明示します。そこでOKを押してもらったときに requestP

【Android】Dialog(画面)をスライドして表示する

イメージ
Androidアプリケーションで画面をスライドして表示させる方法のまとめです。 アニメーション定義 まずはスライドアニメーションを定義します。 resディレクトリ配下にanimディレクトリを作成し、以下ファイルを用意します。 res/anim/slide_in.xml <?xml version="1.0" encoding="utf-8"?> <translate xmlns:android="http://schemas.android.com/apk/res/android" android:duration="500" android:fillAfter="false" android:fromXDelta="100%" android:fromYDelta="0" android:toXDelta="0" android:toYDelta="0" /> res/anim/slide_out.xml <?xml version="1.0" encoding="utf-8"?> <translate xmlns:android="http://schemas.android.com/apk/res/android" android:duration="500" android:fillAfter="false" android:fromXDelta="0" android:fromYDelta="0" android:toXDelta="100%" android:toYDelta="0" /> durationでスライドの速さを調整します。 スライドインするときはX座標

【Android】Realmの基礎 - 検索・追加・更新・削除 -

イメージ
Androidアプリケーションで、Realmを使ったデータの取り扱いについてまとめました。 Realmとは モバイルデバイス向けのデータベースです。Realmが登場するまではSQLiteなどが一般的でした。 もっと詳しくという人は、こちらの記事が分かりやすいと思います。 https://mynavi-agent.jp/it/geekroid/2015/03/realm-realm-tech-talk-.html 実装 ライブラリを追加 app/build.gradle dependenciesに以下の2行を追加して同期します。 implementation 'io.realm:realm-android:+' annotationProcessor 'io.realm:realm-android:+' データ型の定義について データ型はRealmObjectを継承したクラスによって定義します。 これはデータベースで言うところのテーブルに当たります。 ここではIDと名前の2項目を持った単純なテーブルを作ります。 import io.realm.RealmObject; public class Item extends RealmObject{ private int id; private String name; public void setId(int id) { this.id = id; } public int getId() { return id; } public void setName(String name) { this.name = name; } public String getName() { return name; } } Realmインスタンスを取得 インスタンスの取得は以下で行います。 以降このインスタンスを使って検索・追加・更新・削除を行います。 Realm realm = Realm.getInstance(this); データの検索 // 登録データ全件を取得する RealmResults

【Android】LocationListenerで位置情報を取得する

イメージ
GPSから位置情報を利用したアプリがよくありますが、LocationListenerを使えば緯度・経度や、高度などが取得できます。 ということでここでは、AndroidでLocationListenerを使った位置情報の取得についてまとめてみます。 実装 権限を追加 AndroidManifest.xml 以下の権限を追加します。なお、アプリケーションから権限のについては備考にまとめた記事のリンクをご確認ください。 <uses-permission android:name="android.permission.INTERNET" /> <uses-permission android:name="android.permission.ACCESS_GPS" /> <uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" /> <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" /> ACCESS_COARSE_LOCATIONはネットワーク経由で位置情報を取得するのに必要な権限です。 そのためINTERNETの権限も必要になります。 ACCESS_GPSとACCESS_FINE_LOCATIONは、GPSを使用した位置情報を取得するのに必要な権限です。 位置情報の取得処理 MainActivity.java Activityで実装した場合の単純な例が以下になります。 public class MainActivity extends AppCompatActivity implements LocationListener { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activ

【Android】アプリケーションから権限の取得方法

イメージ
Androidアプリケーションがデバイスの機能へアクセスする場合、利用者に権限を許可してもらう必要があります。 デバイスの機能とは以下のようなものです。 連絡先 位置情報 内部ストレージ カメラ etc ・・・ ここでは連絡先を利用するアプリケーションを作ると想定して、どのように実装するのかをまとめます。 実装 対象権限の追加 AndroidManifest.xml AndroidManifest.xmlに取得したい権限を追加します。 <uses-permission android:name="android.permission.READ_CONTACTS" /> 権限を貰うための処理 MainActivity.java public class MainActivity extends AppCompatActivity { /** * onCreate * @param savedInstanceState */ @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); // このアプリケーションに連絡先にアクセスする権限が許可されているかチェック if (PermissionChecker.checkSelfPermission(this, Manifest.permission.READ_CONTACTS) != PackageManager.PERMISSION_GRANTED) { ActivityCompat.requestPermissions(this, new String[]{Manifest.permission.READ_CONTACTS,}, 0); } else{ ((TextView) findV

【Android】アノテーション @SharedPref を使う

Androidアプリケーションで設定などの値を保存する際に、アノテーションを利用して簡単に読み書きする方法をまとめてみます。 まずは通常の SharedPreferences クラスを利用する例が以下です。 SharedPreferencesクラスを使った例 // SharedPreferencesクラスを実体化 SharedPreferences preferences = getSharedPreferences("data", Context.MODE_PRIVATE); // IDを読み込み int id = preferences.getInt("id", 0); // IDを書き込み SharedPreferences.Editor editor = preferences.edit(); editor.putInt("id", 123); editor.apply(); これをアノテーション @SharedPref を使って書くと次のようになります。 @SharedPrefを使った例 // ※これはメンバー変数 @Pref static MyPreference_ preference; // IDを読み込み int id = preference.id().get(); // IDを書き込み preference.id().put(123); Editorを作ったり、keyを指定したりしなくていいのでだいぶすっきりします。 保存する設定値が多くなればなるほど、使いやすさが実感できると思います。 ただしこれを利用するにはもちろん前準備が必要になるので説明します。 前準備 ライブラリを追加 app/build.gradle dependencies { … } に以下の2行を追加します。 annotationProcessor "org.androidannotations:androidannotations:+" implementation "org.androidannotations:androidannotations-api:+" SharedPrefインターフェースを作成 以下のようなインタ

【Android】アプリケーションの開発で環境を切り替えてビルドする方法

イメージ
クライアントサーバー型のアプリケーションを開発していると、開発/ステージング/本番でそれぞれビルドを用意しなくてはならないときがあります。 ほとんどの開発現場でこのようなサーバー構成を取っているのではないかと思います。 今回は環境毎に用意されたstring.xmlを読み込む方法をまとめてみました。 環境の切り替え Build Variants 切り替えは Android Studio の左下の Build Variants をクリックします。 すると Build Variants のウィンドウが出ますので、ここで切り替えを行います。 しかし、初期状態では debug と release の二つしかありません。 これはビルドする際のオプションのことで、今回やろうとしている環境ごとのビルドとは関係ありません。 ここに冒頭の「3つの環境」×「オプションの2つ」の計6個の Build Variants を表示する方法が次の手順になります。 Build Variantsの修正 環境を追加 app/build.gradle productFlavors に各環境を定義します。 // フレーバーディメンション flavorDimensions "default" // プロダクトフレーバー productFlavors { develop { applicationId = '[パッケージ名].dev' } staging { applicationId = '[パッケージ名].stg' } product { applicationId = '[パッケージ名]' } } applicationId にはパッケージ名を指定しますが、ここを環境ごとに変えておくことで、一つのデバイスに全てのバージョンをインストールすることが可能になります。 flavorDimensions は productFlavors が複数あるとき優先順位を決めなくてはいけないので一旦 default とし

【Android】Fragmentを使う② - ActivityとFragmentの相互呼び出し -

イメージ
前回 の記事でFragmentの簡単な実装について書きました。今回はそれの応用編です。 Fragmentに定義したメソッドをActvity側から呼び出したり、FragmentからAcitivityのメソッドを呼び出す方法をまとめます。 ActivityからFragmentのメソッドを実行する まずは親レイアウトであるMainActivity側から、それぞれのFragmentに定義してあるメソッドを実行してみます。この場合Fragment側に特別な処理は必要なく、呼び出し元のMainActivityのみで完結します。 メインのレイアウトにボタンを追加する activity_main.xml <LinearLayout android:id="@+id/llButton" android:gravity="center_horizontal" android:orientation="horizontal" android:layout_below="@id/mainText" android:layout_width="match_parent" android:layout_height="wrap_content"> <Button android:id="@+id/buttonTest1" android:text=" Fragment 1 -> TEST " android:padding="5dp" android:layout_margin="5dp" android:textAllCaps="false" android:layout_width="wrap_content" android:layout_height="wrap_content" /> <Button