20190415のAndroidに関する記事は8件です。

VisualStudioでNativeActivityを使ってAPKを作ってみる - ver.01 assetsフォルダからファイルを読む

はじめに

今回はassetsフォルダからファイルを読み込むところを作ろうと思います。
前回の開発環境をそのまま使用します。

前回のリンク

ソリューションの構成

大きく分けて2つのプロジェクトで構成されています。

  • AndroidApplecation.NativeActivity

    • ダイナミックライブラリ(soファイル)を生成するためのプロジェクト。
    • 主要なプログラムコードはこちらに配置します。
  • AndroidApplecation.Packaging

    • APK内に含めるファイルを配置するプロジェクト。
    • アセット用のフォルダはこちらに配置します。

アセットフォルダの準備

早速アセット配置用のフォルダを作成していきます。
1. 「ソリューション エクスプローラー」->「AndroidApplecation.Packaging」を右クリックし、「追加(D)」->「新しいフォルダー(D)」を選択します。
1.PNG

  1. フォルダ名は「assets」にしてください。
    2.PNG

  2. 作成した「assets」フォルダで右クリックし、「エクスプローラーでフォルダーを開く(X)」を選択し、今回テストで使用する「testlist.txt」を配置して下さい。
    3.PNG

  3. 「testlist.txt」の中身は下記のようにして下さい。

textlist.txt
abcdefghijklmnopqrstuvwxyz
  1. プロジェクトにtestlist.txtを追加します。Visual Studioに戻り、「ソリューション エクスプローラー」->「すべてのファイルを表示」を選択します。
    4.PNG

  2. 「AndroidApplecation.Packaging」->「assets」->「testlist.txt」を右クリックし、「プロジェクトに含める(J)」を選択します。
    5.PNG

  3. 再度「すべてのファイルを表示」を選択します。
    6.PNG

  4. 「AndroidApplecation.Packaging」->「assets」以下に「testlist.txt」が追加されていることを確認します。
    7.PNG

これでassetsフォルダの準備は完了です。

C++言語の設定

今回の開発ではC++11を使用したいと考えています。
そのためC++11を使用するための設定を行います。

  1. 「ソリューション エクスプローラー」->「AndroidApplecation.NativeActivity」を右クリックし、「プロパティ(R)」を選択します。
    「AndroidApplecation.NativeActivity プロパティページ」というウィンドウが立ち上がります。
    8.PNG

  2. 「構成(C)」を「すべての構成」に変更し、「プラットフォーム(P)」を「すべてのプラットフォーム」に変更します。
    その状態で「構成プロパティ」->「C/C++」->「言語」内の「C++ 言語標準」という項目を「C++11 (-std=c++11)」に変更します。
    9.PNG

これでプログラムを組む準備ができました。

テキストを読み込む関数を実装

それでは早速「testlist.txt」を読み込んでみようと思います。
「ソリューション エクスプローラー」->「AndroidApplecation.Packaging」->「main.cpp」を開き、リソースを読み込む下記ソースコードを記載します。

main.cpp
#include <assert.h>

/// <summary>
/// リソースを読み込む
/// </summary>
/// <param name="manager">アセットマネージャー</param>
/// <param name="filePath">ファイルパス</param>
/// <param name="fileSize">ファイルサイズ</param>
/// <returns>成功:読み込んだデータ</returns>
/// <returns>失敗:nullptr</returns>
void* LoadResource(AAssetManager* manager, const char* filePath, unsigned int* fileSize)
{
    AAsset* asset = AAssetManager_open(manager, filePath, AASSET_MODE_BUFFER);
    assert(asset);

    void* data = nullptr;
    if (asset)
    {
        size_t size = AAsset_getLength(asset);
        data = malloc(size);

        // データを読み込む
        AAsset_read(asset, data, size);
        AAsset_close(asset);

        if (fileSize)
        {
            *fileSize = static_cast<unsigned int>(size);
        }
    }

    return data;
}

AndroidNDKには、AAssetManagerというassetsフォルダにアクセスするための仕組みが用意されています。
今回はこの仕組みを使ってファイルアクセスの部分を作ってきます。
簡単にそれぞれの用途を説明しますと、

  • AAssetManager_open関数:ファイルを開く
  • AAsset_getLength関数:ファイルサイズを取得する
  • AAsset_read関数:ファイルをメモリに読み込む
  • AAsset_close関数:ファイルを閉じる

となります。

logcatを表示

LoadResource関数を実際に使ってみる前に、動作確認するための準備をします。
今回は簡単に確認するためにログを出力して行こうと思いますので、「logcat」を表示していきます。
「ツール(T)」->「Android ツール」->「logcat」を選択するだけです。
10.PNG
これで準備完了です。

LoadResource関数を使ってみる

それでは実際にLoadResource関数を使って実際にリソースを読み込んでテキストの文字列をlogcatに出力してみようと思います。

android_main関数がmain.cppにあると思いますので、そちらに記載していきます。
下記の記載を参考にソースコードを追記してみて下さい。

main.cpp(一部抜粋)
/**
* これは、android_native_app_glue を使用しているネイティブ アプリケーション
* のメイン エントリ ポイントです。それ自体のスレッドでイベント ループによって実行され、
* 入力イベントを受け取ったり他の操作を実行したりします。
*/
void android_main(struct android_app* state) {

    /* 省略 */

    // ループはスタッフによる開始を待っています。

    // 動作チェック before
    unsigned int fileSize = 0;
    void* fileData = LoadResource(state->activity->assetManager, "textlist.txt", &fileSize);
    if (fileData)
    {
        char textStr[fileSize + 1];
        strncpy(textStr, (const char*)fileData, fileSize);
        textStr[fileSize] = '\0';
        LOGI("%s", textStr);
    }
    free(fileData);
    // 動作チェック after

    while (1) {
        /* 省略 */
    }
}

これであとは実行するだけです。

結果

logcat上にtestlist.txtに記載されている内容が表示されたでしょうか?
表示されていればファイル読み込みが正常に実装できたことになります。
11.PNG

まとめ

これでassetsフォルダ上のファイルにアクセスできるようになりました。
次回はlibpngを使って何かしら絵を表示する仕組みを実装していければと思っています。

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

Android エミュレータ (AVD) で hosts による名前解決をさせるメモ

AVD にぱっと DNS で名前解決できない開発用とかのサーバーへの名前解決をさせるためのメモ。

まず方法としましては以下がぱっと浮かびます:

  1. ローカルに Proxy サーバーを立ててそこを経由する
  2. Chrome の Developer Tools の Remote Devices からポートフォワードする
  3. /etc/hosts を設定する。

(1) ですが。まず、頻繁に変えるなら Proxy サーバーを立てて設定しておくと、変更時の反映が楽そうです。

(2) について。Chrome には Developer Tools にポートフォワード機能があり、
AVD 側の localhost の任意のポートを、
ホスト側からアクセスできる任意のポートにポートフォワードしてつなげることができます。

Settings.png

なので、この例では localhost:9999dev.api.org:80 につながるようになります。

ただ仮想ホストへのアクセスの場合は、
Host ヘッダーを自分で指定する必要があります。
(もしコードに変更を加えられるのであれば、Retrofit2 の Interceptor でヘッダーを指定するとかできますが、ちょっとめんどうですね)。

(3) の /etc/hosts/ は、ホストと IP の対応を手軽に自分のマシン内で名前解決するのに便利ですね。今回はこれを使います:

まず AVD を書き込み可能にする

${SDK_PATH}/emulator/emulator -writable-system -avd "${AVD_NAME}" &

SDK_PATH は Android SDK ホームへのパス。
mac だったら ${HOME}/Library/Android/sdk/ とかですね。

AVD_NAME は起動したい AVD の名前です。
スペースは _ に置き換えます。
(例: Pixel 2 XL API 28Pixel_2_XL_API_28)

これで AVD が書き込み可能で起動します。
(Play Store が有効だと無理っぽいです)。

ホストの hosts を AVD に push する

cd ${PLATFORM_TOOLS}
./adb root
./adb remount
./adb pull /system/etc/hosts /tmp
cat /etc/hosts >> /tmp/hosts
./adb push /tmp/hosts /system/etc/hosts

で、今起動中の AVD に対して adb 経由で hostspush します。
(PLATFORM_TOOLS${HOME}/Library/Android/sdk/platform-tools とかです)

これで hosts での名前解決できるようになりました。

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

java kotlin IntとIntの除算(割り算)にご注意

なんでこんな簡単なことにハマったのでしょう?
私と同じようにハマって時間を無駄にする方がいないように備忘録

下記は当然の如く0.25と出ると思っていましたが...

        var rate: Double = 0.0
        rate = 1 / 4
        Log.v("TEST:", "rate:${rate}")

下記のようなコンパイルエラーがでる。

Type mismatch: inferred type is Int but Double was expected

google翻訳様:「型が一致しません:推定型はIntですがDoubleが必要です」

そんなことわかっておるワイ!!!

ん? あっ Σ(゚д゚;) ,,,, そういう事か。
IntとIntの計算なので計算結果の型の判定がIntになっていたんですね...
俺よ、なぜ気づかなかった。。。

ということで解決策。どっちか、もしくは両方をDoubleに合わせてやればよい。

        val num1 = 1.toDouble()
        val num2 = 4.toDouble()

        val aaa = num1 / num2

        Log.v("TEST:", "rate = ${aaa}")
V/TEST:: rate = 0.25

はい。想定どおりの結果が返ってきました。
自分の頭の悪さに涙が止まらんです。

補足

ちなみに...

        val aaa = (1/4).toDouble()
        Log.v("TEST:", "rate = ${aaa}")
V/TEST:: rate = 0.0

こうすると 計算結果がIntで来てそれをDoubleに変換しているみたいになるから
想定する結果が返ってきません。
10 / 4 とかだと 2.0 になるから注意。

では、よい kotlin 生活を!

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

BottomSheetDialogFragmentで全画面表示だけ有効にしたい

目的

BottomSheetDialogFragmentで全画面表示だけ有効にしたい

コード

override fun onCreateDialog(savedInstanceState: Bundle?): Dialog {

    val dialog = super.onCreateDialog(savedInstanceState) as BottomSheetDialog

    dialog.setOnShowListener { dialog ->
        val d = dialog as BottomSheetDialog

        val bottomSheet = d.findViewById(com.google.android.material.R.id.design_bottom_sheet) as FrameLayout?
        val behavior = BottomSheetBehavior.from(bottomSheet)
        behavior.state = BottomSheetBehavior.STATE_COLLAPSED

        behavior.setBottomSheetCallback(object : BottomSheetBehavior.BottomSheetCallback() {
            override fun onSlide(bottomSheet: View, slideOffset: Float) {
                //何もしない
            }

            override fun onStateChanged(bottomSheet: View, newState: Int) {
                //この条件分岐追加しないと画面が消えた後モーダルの半透明黒マスクだけが残る
                if (newState == BottomSheetBehavior.STATE_HIDDEN) {
                    dismiss()
                    behavior.state = BottomSheetBehavior.STATE_COLLAPSED
                }
                //途中で止まろうとするので強制的に全画面表示する
                else if (newState == BottomSheetBehavior.STATE_COLLAPSED) {
                    behavior.state = BottomSheetBehavior.STATE_EXPANDED
                }
            }
        })

        //下から出てきて全画面表示されるようにする
        behavior.state = BottomSheetBehavior.STATE_EXPANDED
    }
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

Androidのビルド時にファイル更新が反映されない時、キャッシュをクリアする方法

./gradlew clean cleanBuildCache
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

Flutterウィークリー #54

Flutterウィークリーとは?

FlutterファンによるFlutterファンのためのニュースレター
https://flutterweekly.net/

この記事は#54の日本語訳です
https://mailchi.mp/flutterweekly/flutter-weekly-54

※Google翻訳を使って自動翻訳を行っています。翻訳に問題がある箇所を発見しましたら編集リクエストを送っていただければ幸いです。

読み物&チュートリアル

2019年のFlutterの最初のユーザー調査からの洞察

https://medium.com/flutter-io/insights-from-flutters-first-user-survey-of-2019-3659b02303a5


Flutter UXリサーチチームによるQ1ユーザー調査に関するFlutter使用に関する新しいレポート。

なぜそしてどのように私はFlutterを学んでいますか?

https://medium.com/flutter-community/why-and-how-am-i-learning-flutter-2652c15c8113


Wilton RibeiroはFlutterに関する彼の学びの道と彼がそれを学び始めた理由を共有します。

Flutterコーディングインタビューをクラックする:Call Centerを設計する

https://medium.com/@DmytroGladkyi/cracking-the-coding-interview-in-flutter-design-the-call-center-45919a6a4fc9


Dmytro Gladkyiは、 Flutterを使用して典型的なコールセンターのインタビューテストを解決します。

WidgetGigs - Flutterジョブボード

https://widgetgigs.com/


Flutter関連の仕事のための新しい求人掲示板。履歴書をアップグレードしましょう。

Reduxを使ってFlutterでアニメーションを作成する方法

https://medium.com/flutter-community/how-to-create-animations-in-flutter-with-redux-e04ec70afbc9


Paulina Szklarskaが、アプリでReduxを使用しながらアニメーションを処理する方法を説明します。

Flutter :ゴールデンテスト - ウィジェットとスナップショットの比較

https://medium.com/flutter-community/flutter-golden-tests-compare-widgets-with-snapshots-27f83f266cea


ゴールデンテストは、 Flutterテストシステムではあまり知られていない機能の1つです。カタリーナシェレメットはそれらをマスターする方法を紹介します。

Flutter不変ビジネスロジック

https://medium.com/flutter-community/immutable-business-logic-in-flutter-5135333f39c4?sk=1d397e65802d5af810332837d0bf31ab


David Leybovichが、 Reduxビジネスロジックにおける不変性について説明します。

Flutter :クイズゲームの作り方

https://medium.com/flutter-community/flutter-how-to-build-a-quiz-game-596d0f369575


Flutterクイズゲームを作成するためのFrancesco Mineoによる完全なチュートリアル。

FlutterアニメーションI:背景色の変化

https://medium.com/flutter-community/flutter-animation-i-background-color-transition-39dcbada7335


Divyanshu Bhargavaが、トゥイーンアニメーションを使用してアプリの背景色を変更する方法を説明します。

Flutterエラーメッセージが改善されました

https://medium.com/@eibaan_54644/better-errors-messages-for-flutter-a21c53982a99


Amigaシステムを覚えていますか? Stefan Matthias AustがFlutterの古い "達人瞑想"エラーメッセージを再現します。

Flutter UIをフェードインする

https://medium.com/@felixblaschke/fade-in-your-uis-in-flutter-c81b1c345f70


Felix Blaschkeは、自分のライブラリsimple_animationsを使用して画面内の要素をフェードインさせます。

Flutterレイアウトの基本

https://medium.com/@seenickcode/the-basics-of-flutter-layout-88339a4d2cd2


基本に立ち返って。 Nick ManningがFlutterレイアウトを紹介します。

InheritedWidgetを使用したFlutterでの「依存性注入」

https://medium.com/flutter-community/dependency-injection-in-flutter-with-inheritedwidget-b48ca63e823


FlutterよるFlutter依存関係を注入するための賢い方法

Flutter派手な背景アニメーション

https://medium.com/@felixblaschke/fancy-background-animations-in-flutter-4163d50f5c37


Felix Blaschkeによる面白い背景アニメーション

Flutter :ネットワーク要求(HTTP)

https://medium.com/@lawrey/flutter-network-request-http-6ae5667fff73


Lawrence TanがFlutter httpリクエストを行うための完全な紹介をします。

Flutterビデオプレーヤー - Chewie Tutorial

https://resocoder.com/2019/04/13/flutter-video-player-chewie-tutorial/


より良いビデオ処理のためのChewieライブラリでビデオプレーヤーを作成することに関するチュートリアル。

Flutter - MobXによる状態管理

https://diveintoflutter.blogspot.com/2019/04/flutter-state-management-with-mobx.html


MobX状態処理ライブラリの紹介

ビデオ&メディア

6分でFlutterナビゲーション - ナビゲータのみを使用

https://www.youtube.com/watch?v=DlArCl8jvlo&feature=youtu.be


この短いフラッターチュートリアルでは、ナビゲーションを含む現実世界のシナリオについて説明します。

Flutterチュートリアル-とFirestore Flutter

https://www.youtube.com/watch?v=R12ks4yDpMM


FlutterアプリケーションにFirebaseを統合する方法についてのビデオ。

Flutterテキスト、フォントおよびThemeData

https://www.youtube.com/watch?v=ePLhVrT4au0


TextTheme、カスタムフォント、およびTextStyleを使った基本的なマテリアルデザインテーマを使用してテキストをスタイルする方法を学びます。

Flutter :sqlite(sqflite)| CRUD操作

https://www.youtube.com/watch?v=9D1VX6uGylU&feature=youtu.be


Flutterデータベースを処理するためのsqfliteライブラリの使用法の紹介。

FlutterとGoogle Mapsを使ってモバイルアプリを構築する(Cloud Next '19)

https://www.youtube.com/watch?v=RpQLFAFqMlw


Brett MorganとMatthew Sullivanによる、Cloud Next '19イベントのFlutter Mapsの使用に関する講演。

フラッターアニメーションを使用してボタンを上下にアニメートする

https://www.youtube.com/watch?v=d-yx0F2FoaA&feature=youtu.be


このチュートリアルでは、クリックしたときにボタンを上下に移動させるためのアニメーションの作成方法を説明します。

ライブラリ&コード

flutter_movie_ui

https://github.com/sergiandreplace/flutter_movie_ui

先週の土曜日、私は上にあったFlutterでUIの作成について話チューリッヒミートFlutter 。ここにはソースコード(便利なステップバイステップのコミット)とプレゼンテーションへのリンクがあります。

ジデグル/素材について

https://github.com/JideGuru/material-about

モバイルアプリで使用する画面について。

olexale / arkit_flutter_plugin

https://github.com/olexale/arkit_flutter_plugin

ARKit Flutterプラグイン

luigi-rosso / sequenced_loader

https://github.com/luigi-rosso/sequenced_loader

Flareコントローラを使用してFlutterローディングアニメーションを駆動する方法の例。

nonybrighto / flutter_firebase_tic_tac_toe

https://github.com/nonybrighto/flutter_firebase_tic_tac_toe

バックエンドとしてflutterとfirebaseを使って作られたシンプルなマルチレイヤ三目並べアプリケーション

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

ローカル実行でAndroidアプリの課金をテストする

debug証明書を使用したビルドでは課金のテストはできませんが、release証明書を使用すればAndroid Studioのローカル実行で課金をテストすることができます。
Google Play アプリ署名を有効にしている場合でも、アップロード証明書で署名すれば課金をテストできます。

以下にGUIを使用した手順を紹介します。

  1. Android StudioでBuild Variantrelease に設定しておく
    f1.png

  2. File -> Project Structure -> appモジュール -> signing でアップロード証明書の情報を入力する
    f2.png

  3. Build Typesタブに移動し、Signing Configに↑で作成したものを設定する
    必要に応じて debuggabletrue に設定する。
    f3.png

  4. Android Studioからアプリを実行する
    f4.png

もちろんreleaseビルドの証明書の設定などはbuild.gradleを手動で修正しても構いません。

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

[Android]ShareCompatを使ってシェア(共有)する場合の画像の渡し方、コールバックの受け取り方

↓これの事

わりとたくさん情報がありそうな気がしたが、意外と出てこなかったので、メモ書き。

ライブラリ

  • com.android.support:support-compat:28.0.0

実装

SomeActivity.java
// アクティビティ内から実行する前提のコード
private void showShareChooser() {
    File tempFile = new File(getApplicationContext().getExternalCacheDir(), tempImgFilePath);

    // ファイルをシェアするためにURIを取得する場合は、FileProviderを通じて、後述するオーソリティの名前を指定して取得する必要がある
    Uri uri = FileProvider.getUriForFile(getApplicationContext()
            , getApplicationContext().getPackageName() + ".provider"
            , tempFile);

    ShareCompat.IntentBuilder builder = ShareCompat.IntentBuilder.from(this);
    builder.setChooserTitle(chooserTitle) // シェアする時のタイトル
            .setSubject(subject) // 件名。使われ方はシェアされた側のアプリによる
            .setText(text) // 本文。使われ方はシェアされた側のアプリによる
            .setStream(uri) // ファイルをシェアする時は、そのURIを指定
            .setType("image/jpeg"); // ストリームで指定したファイルのMIMEタイプ

    // URIに対する読み取り権限を付与する
    Intent intent = builder.createChooserIntent().addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);

    // コールバックを受け取りたい場合は、そのインテントを使ってアクティビティを開始する
    if (intent.resolveActivity(getPackageManager()) != null) {
        startActivityForResult(intent, SNS_SHARE);
    }

    // 結果を受け取らなくても良い場合は、ビルダーからそのまま開始できる
    // builder.startChooser();
}

戻りを受け取る場合は、 通常どおり onActivityResult で受け取れる。

@Override
public void onActivityResult(int requestCode, int resultCode, Intent data) {
    switch (requestCode) {
        case SNS_SHARE:
            // 戻りを受け取って何らか処理する
            // resultCode は必ずゼロになるので、 RESULT_OK で判定しない
            doSomething();
            break;

        default:
            super.onActivityResult(requestCode, resultCode, data);
            break;
    }
}

ファイルを共有する場合

画像などを共有する場合は、Bitmapをそのまま共有したりできないため、一旦ファイルに保存する必要がある。
また、以下のように保存先からの読み出しを許可する必要がある。

まず、パスをXMLで指定する。

src/main/res/xml/provider_paths.xml
<?xml version="1.0" encoding="utf-8"?>
<paths xmlns:android="http://schemas.android.com/apk/res/android">
    <external-cache-path name="cache" path="." />
</paths>

external-cache-path などは保存先に応じて変わる。
英語だけどFileProviderの公式リファレンスを参照。
次に、そのプロバイダを AndroidManifest.xml で指定する。

AndroidManifest.xml
<manifest
    package="com.example"
    xmlns:android="http://schemas.android.com/apk/res/android">
:
        <provider
            android:name="android.support.v4.content.FileProvider"
            android:authorities="${applicationId}.provider"
            android:exported="false"
            android:grantUriPermissions="true">
            <meta-data
                android:name="android.support.FILE_PROVIDER_PATHS"
                android:resource="@xml/provider_paths"/>
        </provider>
:
    </application>
:
</manifest>

参考

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む