AndroidStudio と、Dxライブラリ(DxLib) をつかって、Android / Chromebook アプリを作る方法を初心者向けに解説。スマホアプリを作ってみたい人、ゲームを作ってみたい人におすすめ。
このアニメが作れる 9VAeきゅうべえ Android版 もDxライブラリで開発しています。ほかの解説動画はこちら
Android Studio
- Android / Chromebook 用アプリの開発環境です
- ダウンロードはこちら
Dxライブラリとは
- C++用ゲーム用ライブラリ。本家サイトはこちら
- Windows / Android / Chromebook / iPhone / iPad / Playstation / Switch で同じように動作します。
- 日本で開発されている歴史のあるライブラリで、実際のゲームにも使用されているみたいです。プログラミング初心者向き。
- DxLibサンプルプロジェクトはこちら
Android Studioのインストールとテスト実行
- 以下は、Windows版の画面ですが、Mac版AndroidStudioでもできます
- AndroidStudio のダウンロードはこちら
- ダウンロードしたAndroidStudio を起動。「Next」
- 「Standard」にチェック。「Next」
- 背景の色を選ぶ。「Next」2回
- ライセンスを3項目選び、それぞれ「Accept」。「Finish」
これでインストールが行われます。まず、DxLibのサンプルを読み込んでみましょう。
- AndroidStudioの起動画面で、「More Actions」をクリック(上図14)。メニューから「Import Project(Gradle Eclipse ADT etc)」
- ダウンロードしたDxLibを展開、中にある「RunSampleFolder_AndroidStudio」を選ぶ。
- プロジェクトを信用するか聞かれるので「TrustProject(信用する)」(上図15)をクリックすると読み込みが始まります。
- 実機があれば、次の項目を参考にして、実機をUSBケーブルで接続して、USBデバッグを許可してください。エミュレータより軽いです。正しく接続されると(上図1)No Devices の表示が実機の機種名に変わります(上図2)実機のリセット、ケーブルの抜き差しを試してみてください。
- DxLibのサンプルプログラムを表示するには、左側「app」(「src」「main」)「cpp」「native-lib.cpp」をクリックすると、右側にソースコードが表示されます。
- アプリ作成は「Build」メニュー>「Rebuild Project」で作り直します(上図6)
- 下のBuild タブ(上図7)でビルド結果を表示。ここではエラー(Javaのバージョンが違う)が表示されました。ほかのエラーが出るかもしれません。
- Javaのバージョンは、File メニュー>Project Structureで設定します
- 左側 SDK Location>Gradle Setting
- 「Gradle JDK」を「11 Version」に変更。「OK」をクリック
- 「File>Close Project」してプロジェクトを開きなおします
- 「Build」メニュー>「Make Project」を実行。今度は「BUILD SUCCESSFUL(成功)」となりました。
- 右上のデバッグボタン(上図15)を実行
- 実機の上に四角形が描画されたら成功です。
- 下にはデバッグ用のタブが表示されます。ソースコードにブレークポイントを設定し、そこからステップ実行させたり、変数の中をみたりできます。
Android 実機デバッグ
- Android Studio にはエミュレータがあり、パソコンだけでもデバッグできますが、高性能なパソコンでない場合は、実機デバッグがおすすめです。
- SIMのない中古端末でも、USBケーブルを接続して実機デバッグができます。Wi-Fi でストアプリのテストもできます。
- Windows11、メモリ8GB以上なら、Windows Subsystem for Android(TM) が実機として使えます。
- 各バージョンとAPIレベルの特徴
機種 | AndroidOS | APIレベル |
---|---|---|
Nexus 5 | 6.0.1 | API23 |
Nexus 5X | 8.1.0 | API26 |
Pixel 3a | 12 | API31 |
Pixel 6a | 13- | API33- |
Windows11 WSA | 13- | API33- |
- Android実機で「設定」を実行。「デバイス情報」
- 「ビルド番号」を7回タッチ。これで「開発者向けオプション」が追加されます
- 「設定」メニューに戻って「システム」「開発者向けオプション」
- 「USBデバッグ」をONにする
この設定で、実機をパソコンとUSBケーブルで接続します。実機上に「パソコンを信頼するか」という表示がでたら「信頼する」または「許可する」をタッチします。
WSAは Windows11 の Android 環境です。
プログラムを作ってみよう
このサンプルプロジェクトに、新しい機能を追加してみましょう。
- DxLibのプログラムは、AndroidStudio 左側「app」「cpp」「native-lib.cpp」です。
元のコード
#include "DxLib.h"
// プログラムは android_main から始まります
int android_main( void )
{
if( DxLib_Init() == -1 ) // DXライブラリ初期化処理
{
return -1 ; // エラーが起きたら直ちに終了
}
DrawBox( 220, 140, 420, 340, GetColor( 255,255,255 ), TRUE ) ; // 四角形を描画する
WaitKey() ; // キー入力待ち
DxLib_End() ; // DXライブラリ使用の終了処理
return 0 ; // ソフトの終了
}
- DrawBox で、白(GetColor( 255,255,255 ))の四角形を書き、WaitKey でキー入力待ちをしています。DxLibで使える関数はここにあります。
機能追加 その1
次の機能を追加してみましょう。
- 四角形の中をタッチすると赤い線が引ける
- 外側をタッチすると黄色い線が引ける
- 左上すみをタッチすると終了
- 線をひくと同じ色でかける
#include "DxLib.h"
int penDown; //1=前回ペンダウン、0=前回ペンアップ -1=終了
int penColor; //ペンの色
// プログラムは android_main から始まります
int android_main( void )
{
if( DxLib_Init() == -1 ) // DXライブラリ初期化処理
{
return -1 ; // エラーが起きたら直ちに終了
}
DrawBox( 220, 140, 420, 340, GetColor( 255,255,255 ), TRUE ) ; // 四角形を描画する
penDown = 0;
penColor = GetColor( 255,255,255 ); //白色
DrawBox( 0, 0, 50, 50, penColor, FALSE ) ; // 左上すみの四角
//イベントループ
while( ProcessMessage() == 0)
{
TOUCHINPUTDATA tid;
TOUCHINPUTPOINT tip;
int ii,xx,yy;
// if(GetTouchInputLogNum()==0) continue;//ログの個数
tid=GetTouchInputLogOne( FALSE ) ; //ログを読み出す。FALSEは削除
if(tid.PointNum == 0)
{
penDown = 0; //ペンアップ検出
}
for(ii=0; ii < tid.PointNum; ii++) //座標入力あり
{
tip = tid.Point[ii];
xx = tip.PositionX; //X 座標
yy = tip.PositionY; //Y 座標
if( penDown==0 ){ //タッチ検出(前回がペンアップ)
if( xx < 50 && yy < 50 ) //左上すみタッチ
{
penDown = -1;
break;
}
if( xx >= 220 && xx <420 && yy >= 140 && yy <340 ) penColor = GetColor( 255,0,0 ); //内側赤
else penColor = GetColor( 255,255,0 ); //外側 黄色
}
DrawCircle( xx , yy , 10 , penColor , TRUE ); //TRUEは塗りつぶし
penDown = 1;
}
if(penDown < 0) break; //終了
}
DxLib_End() ; // DXライブラリ使用の終了処理
return 0 ; // ソフトの終了
}
- TOUCHINPUTPOINT の説明はこちら にあります
デバッグの仕方
- 上のプログラムをそのまま入力して実行すると、指が四角形の中から外にかわるときに、色が赤から黄色に変わってしまいます。(下図)
- 上のプログラムでは、penDown が0(指が離れている)から1(タッチ)に変わったときだけ penColor を変更します。
- 指が離れているのは、tid.PointNum == 0 (座標値がないからはなれている)で検出しているのですが、これが毎回検出されているかもしれません。
- それを確かめるために、「penDown = 0; //ペンアップ検出」の行頭をクリックし、ブレークポイントを設定します。(〇が行頭につきます)
- デバッグ実行ボタン(虫マーク)をクリック
- ブレークポイントで停止します
- ステップ実行ボタンを押すと1行すすみます
- 実行ボタン(左側三角)を押すと、毎回、ブレークポイントで止まることがわかります。
- 停止ボタン(左側■)で終了
- 実は、GetTouchInputLogNum()が0より大きい値でないとき、GetTouchInputLogOneは正しい値を返しません。if(GetTouchInputLogNum()==0) continue;のまえの「//」を削除してください。// はコメント行の意味でこの右側のコードを無視します。continue;は、while や for ループの中で、後ろの処理をやめて次のループに移る命令です。つまり、GetTouchInputLogNum()が0のときは、下の処理をしないという意味になります。
- デバッグ実行。何回かブレークポイントで止まりますが、その後「実行」ボタンで止まらなくなります。
- 画面を指でなぞると、指をタッチしている間は色がかわらなくなりました。
機能追加 その2
上のプログラムに次の機能を追加してみましょう。
- 筆圧ペンの圧力によって線の太さを変える
#include "DxLib.h"
int penDown; //1=前回ペンダウン、0=前回ペンアップ -1=終了
int penColor; //ペンの色
int penSize; //ペンサイズ
// プログラムは android_main から始まります
int android_main( void )
{
if( DxLib_Init() == -1 ) // DXライブラリ初期化処理
{
return -1 ; // エラーが起きたら直ちに終了
}
DrawBox( 220, 140, 420, 340, GetColor( 255,255,255 ), TRUE ) ; // 四角形を描画する
penDown = 0;
penColor = GetColor( 255,255,255 ); //白色
penSize = 10;
DrawBox( 0, 0, 50, 50, penColor, FALSE ) ; // 左上すみの四角
//イベントループ
while( ProcessMessage() == 0)
{
TOUCHINPUTDATA tid;
TOUCHINPUTPOINT tip;
int ii,xx,yy;
if(GetTouchInputLogNum()==0) continue;//ログの個数
tid=GetTouchInputLogOne( FALSE ) ; //ログを読み出す。FALSEは削除
if(tid.PointNum == 0)
{
penDown = 0; //ペンアップ検出
}
for(ii=0; ii < tid.PointNum; ii++) //座標入力あり
{
tip = tid.Point[ii];
switch (tip.ToolType) {
case DX_TOUCHINPUT_TOOL_TYPE_STYLUS://ペン
case DX_TOUCHINPUT_TOOL_TYPE_ERASER://消しゴム
penSize = tip.Pressure * 20; //ペンサイズ
if(tip.Pressure==0) //ペンが離れた
{
penDown = 0;
continue;
}
break;
case DX_TOUCHINPUT_TOOL_TYPE_FINGER://指
penSize = 10;
break;
case DX_TOUCHINPUT_TOOL_TYPE_MOUSE://マウス
default: continue;
}
xx = tip.PositionX; //X 座標
yy = tip.PositionY; //Y 座標
if( penDown==0 ){ //タッチ検出(前回がペンアップ)
if( xx < 50 && yy < 50 ) //左上すみタッチ
{
penDown = -1;
break;
}
if( xx >= 220 && xx <420 && yy >= 140 && yy <340 ) penColor = GetColor( 255,0,0 ); //内側赤
else penColor = GetColor( 255,255,0 ); //外側 黄色
}
DrawCircle( xx , yy , penSize, penColor , TRUE ); //TRUEは塗りつぶし
penDown = 1;
}
if(penDown < 0) break; //終了
}
DxLib_End() ; // DXライブラリ使用の終了処理
return 0 ; // ソフトの終了
}
- build メニュー「Make Project」で上のプログラムを実行すると「error: no member named 'ToolType' in 'DxLib::tagTOUCHINPUTPOINT'」エラーが出た場合、筆圧ペンに対応していない DxLibrary が使われているからです。
- 筆圧ペンに対応した DxLibrery はこちら(DxLibAndroidTest.zip)にあります。
- DxLibrary をダウンロードして解凍すると。「arm64-v8a, armeabi-v7a, x86, x86_64」という4つのフォルダがはいっています。これがDxLibの ARM32bit/64bit版、Intel32bit/64bit版の4種類のライブラリです。DxLibrary のプロジェクトの中には、「DxLib_Android/Lib_Android/」の中に同じ4つのフォルダがあるので、ここに上書きします。フォルダを比較するとどこが変わったかわかります。
- ライブラリを入れ替えるとビルドに成功します。
アプリへの署名
アプリを公開するには、署名つきの APK、または AAB を作る必要があります。
- buildメニュー「Generate Signed Bundle / APK…」の中で「Create new...」で作成することができます。
- 署名キーがはいったファイルがキーストアです。このファイルが開発者が誰かを証明するものになるため大切に保管します。
- キーストアの保管場所、パスワードを入力します。
- エイリアス名は(デフォルト key0)ですが好きな名前をつけてかまいません。エイリアスにもパスワードを入力します。署名時に、ファイル名、パスワード、エイリアス名、パスワードが必要になります。
- そのあと、次の情報を入力します。これが署名の中に記録され、アプリを誰が作ったかわかるようになります。
名前
部署名
所属名
市町村
府県
国名(JP)
- デバッグ用とリリース用の2種類を作成できます。
- 出力結果にエラーが表示された場合、下の説明をよんで対応します。
パッケージ作成のデバッグ
- エラーの内容を知るには「lint」を入れよとあるので、Gradle.Scripts > build.gradle(Module を開きます
- android {}の中に、下の「lint{」を入れます。
- buildメニュー「Generate Signed Bundle / APK…」でエラー終了します
- 下の「Problems」を見ると「Target Version が 最近の Androidとあっていない」と表示されます。
- 記事作成時には、API30 以上でないとストアに登録できません。 Gradle.Scripts > build.gradle(Module を開いて 「compileSdkVersion」と「targetSdkVersion」 を、29から30に変更します。これで署名つきAPKの作成に成功しました。
lint {
baseline = file("lint-baseline.xml")
}
VisualStudio から DXlib プログラムを移植するには
- DXLib 付属の AndroidStudioプロジェクトに、VisualStudioソースを追加する方法が簡単です。
- ソースは UTF-8 にします(VisualStudio は ShiftJIS が多い)。プログラム中に日本語が書かれている場合、修正が必要になるかもしれません。DxLibのドキュメントも参考。
- プロジェクトの中に自分のソースフォルダを作成し、app/src/main/cpp/CMakeLists.txt の中にある native-lib.cpp の下にソースファイルを相対パスで全部追加します。
- コンパイルオプションは、build.gradle(Module:Packaging.app) に以下のように書きます。
- 2023年 targetSdkVersion 33への対応が必要になりました。
android {
compileSdkVersion 33
defaultConfig {
applicationId "com.自分のアプリのIDに変更"
minSdkVersion 27
targetSdkVersion 33
versionCode 1
versionName "1.0"
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
externalNativeBuild {
cmake {
cppFlags "-std=c++11" // C++11 例外 動的キャスト等
arguments "-Dユーザー定義"
}
}
}
- Warningを減らす方法:ソースの先頭に以下のように書けば、種類別に出さなくできます。Warnigを指定する文字列はこちら
#pragma clang diagnostic ignored "-Wdeprecated-declarations"
#pragma clang diagnostic ignored "-Wmacro-redefined"
targetSdkVersion 31 以上にするとビルドできなくなった
- app > manifests の中にある AndroidManifest.xml の<activity に「android:exported="true"」を追加するとビルドできるようになります。
- 2023年 targetSdkVersion 33への対応が必要になりました。
<activity android:name="android.app.NativeActivity"
android:exported="true"
>
...
</activity>
Unable to execute Clang-Tidy: clazy-standalone is not found エラーが出てデバッグできない。
SAF(StorageAccessFramework)対応
Android はセキュリティが強化され、ファイルアクセスが従来のパスをつかう方法から、Uriというユーザーが許可したファイル、フォルダ情報にしかアクセスできないようになってます(Android対象別ストレージ)。DXライブラリは、パスをつかったアクセスしかできないので、Javaプログラムで、Uriを取得し、そのデータをDXライブラリで読み書きできる場所(アプリがある場所)にコピーし、DXライブラリから読み書きする必要があります。めんどうですが、この方法を使うと、アプリ側はなにも変更せずに、ユーザーが指定したGoogleドライブなどに読み書きできるようになります。
Uri を取得するには、Intentを使います。以下は、9VAeきゅうべえで使っているプログラムをすこし修正したものです。こちらを参考にしました
状態変数(DXライブラリとやりとり)
int InputEnd; // 状態
String InputString; //入力結果
Uri Create_File_Uri; //保存Url
ファイルを開く Intent
ファイルの型を指定して、開くファイルを選択します。型の記述(MIME type)はこちら
private static final int PICK_OPEN_FILE = 1;
private void openFile(Uri pickerInitialUri, String fType) {
Intent intent = new Intent(Intent.ACTION_OPEN_DOCUMENT);
intent.addCategory(Intent.CATEGORY_OPENABLE);
intent.setType(fType);//開きたいファイルタイプ "image/*"など
intent.putExtra(DocumentsContract.EXTRA_INITIAL_URI, pickerInitialUri);
InputEnd = -1; // まだ入力されていない
Create_File_Uri=null;
startActivityForResult(intent, PICK_OPEN_FILE);
}
ファイル保存の Intent
private static final int PICK_CREATE_FILE = 2;
private void createFile(Uri pickerInitialUri, String orgName, String fType) {
Intent intent = new Intent(Intent.ACTION_CREATE_DOCUMENT);
intent.addCategory(Intent.CATEGORY_OPENABLE);
intent.setType(fType);
intent.putExtra(Intent.EXTRA_TITLE, orgName);
InputEnd = -1; //まだ入力されていない
Create_File_Uri=null;
intent.putExtra(DocumentsContract.EXTRA_INITIAL_URI, pickerInitialUri);
startActivityForResult(intent, PICK_CREATE_FILE);
}
Intent の結果処理
- PICK_OPEN_FILEが開くの結果、PICK_CREATE_FILEが保存の結果
- どちらの場合も結果の Uri からファイル名を取得します。
- 開くの場合、DXライブラリで読み込める場所に内容を複製し、そのパスを InputStringにいれます。
- 保存の場合は、DXライブラリで保存処理を行なったあと、結果を、取得したUrl に複製します。
@Override
public void onActivityResult(int requestCode, int resultCode,
Intent resultData) {
if ((requestCode == PICK_OPEN_FILE || requestCode == PICK_CREATE_FILE)
&& resultCode == Activity.RESULT_OK) {
Uri uri; String path;
if (resultData != null) {
uri = resultData.getData();
path=uri.getPath();
if(requestCode == CRET_X_FILE){
Create_File_Uri = uri;//保存後に転送
}
Context context = this.getApplicationContext();
String scheme = uri.getScheme();
String name = null;
path = null;
if ("file".equals(scheme)) {
name = new File(uri.getPath()).getName();
} else if("content".equals(scheme)) {
String[] projection = {MediaStore.MediaColumns.DISPLAY_NAME};
Cursor cursor = context.getContentResolver().query(uri, projection, null, null, null);
if (cursor != null) {
if (cursor.moveToFirst()) {
name = cursor.getString(0);
}
cursor.close();
}
}
// Input Stream 読み込み
try {
InputString = sdPath9VAe()+"/"+name;
String newName = getNewFile(InputString);
if (newName!=null) InputString=newName;
if (requestCode == PICK_OPEN_FILE) {
InputStream strm = context.getContentResolver().openInputStream(uri);
DataInputStream daIn = new DataInputStream(strm);
DataOutputStream daOut = new DataOutputStream(
new BufferedOutputStream(
new FileOutputStream(InputString)));
byte[] b = new byte[4096];
int rByte = 0;// Read Data
while (-1 != (rByte = daIn.read(b))) {
daOut.write(b, 0, rByte);
}
daIn.close();
daOut.close();
}
InputEnd = -1;// 入力された
}catch (Exception e) {
e.printStackTrace();
InputEnd = -2 ;InputString = "Exception";
}
}
}
}
sdPath9VAe() は9VAeのアプリフォルダ。getNewFile(InputString)は同じ名前のファイルがあって転送できない場合(1)などをつけて別名を返します。
Java と DXライブラリのやりとりは、JNI という仕組みを使います。難しいです。以下参考資料
- DXライブラリサンプルコード
- Android開発者のためのJNI入門 JNIの基本 | TechBooster
- JNIコーディングメモ(Hishidama's Java native interface coding Memo)
ひとコマ解説動画の作り方
この記事の解説動画(ひとコマ解説)は、無料9VAeきゅうべえ で作成しています。
- Youtube動画より短く、静止画の羅列より見やすいのが特長。
- キャプチャー画面の上に、矢印、説明を加え「ひとコマ」設定するだけで作れます。
- 後から自由に修正でき、メンテ、複製が簡単です。動画も作れます。
1. 画面キャプチャする
各OSでスクリーンキャプチャする方法をまとめました。
OS | 画面キャプチャ方法 | 保存先 |
---|---|---|
Windows | Print Screen キー Shift + Windows + S 無料ソフト「kioku」 |
クリップボード |
Mac | Shift + Command + 4 | デスクトップ |
Android | 電源 + 音量Down adbコマンド (開発者向け) adb shell screencap -p /sdcard/screen.png adb pull /sdcard/screen.png |
フォトアプリ> スクリーンショット |
iPhone / iPad | ホームボタン + 電源ボタン サイドボタン + 音量UP |
写真> アルバム> スクリーンショット(Screenshots) |
Linux Mint | Print Screen キー | クリップボード |
2. キャプチャ画像を9VAeに読みこむ
- 画像入力ボタン「山」でキャプチャ画像を読み込む
- 画像の中心の「+」をクリック。メニューから「ステージの大きさにする」
- 画像の中心の「+」をクリック。メニューから「ページを画像に合わせる」
3. 文字、矢印を入れる
- 文字入力ボタン「A」で数字を入力
- 角の■をドラッグでサイズ変更。
- 中心の「+」または枠線のドラッグで移動
- 線の種類ボタンをクリック。メニューから「→」で矢印に設定
- 折れ線ボタンをクリック
- 開始点
- 終了点
- 選択ボタンで入力終了
- 太さ設定ボタン。メニューから「太くする」で太くできます。
- 文字入力ボタン「A」で説明文章を入力
- 背景の色を設定
- 線の種類メニューの「ー」で枠線がつきます
- 太さ設定ボタン。メニューから「太くする」で太くできます。
4. 文字の色、縁、影をつける
- 文字を選ぶ
- 文字タブ2をクリック
- 文字の色をクリック
- 赤に設定
- 文字と矢印をドラッグして選ぶ
- 図形タブ1をクリック
- 線の種類から「縁をつける」
- 線の種類から「影をつける」、線の種類から「広く」
- 線の色「赤」
5. ひとコマアニメーションにする
- ページ時間をクリック。メニューから「ひとコマ」を設定。これでアニメーションができます。
- プレイボタンで再生してみましょう。入力した順番に文字、矢印がでてきます。
- これで1ページ完成です。続きを作りたい場合は、ページの右側の「+」をクリックし「続きのページを作る」で、2ページ目が作成できます。
6. アニメGIF、動画出力
- ファイルメニュー>アニメGIF出力」または「動画出力」で、好きなサイズのアニメGIF または MP4動画 が作成できます。
- Win / RaspberryPi / Linux版 でMP4動画を作るには FFmpeg が必要です
- スマホの場合、端末内の「9VAe」フォルダの中に出力されます。フォトアプリで、「端末内の写真>9VAe」で見ることができます。
- アニメGIFは、背景を透明にできます。音がいれられません。
- MP4動画には音が入れられます。Youtubeに投稿できます。Youtubeに投稿する場合、1秒30コマ、高さ720 または 1080 で出力するとよいでしょう。
関連記事
9VAeきゅうべえ のご紹介
9VAeきゅうべえ 初級編
- 9VAe チュートリアル(1)-画面の説明
- 9VAe チュートリアル(2)-図形入力、選択、移動、サイズ変更
- 9VAe チュートリアル(3)-アニメキャストを作る、時間調整
- 9VAe チュートリアル(4)-アニメキャストの修正、往復
- 9VAe チュートリアル(5)-動きグラフ、ページコピー、GIF作成
9VAeきゅうべえ 中級編
9VAeきゅうべえ 上級編
- 動くLINEスタンプのAPNG作成:無料ソフト9VAeきゅうべえ
- 萌えキャラ デジたんを目ぱちさせるまで:APNGアニメの作り方
- openclipartの無料イラストをアニメ化する6つの手順
- イラストから動くLINEスタンプのようなアニメを簡単に作る方法
- Openclipart の 無料SVG をアニメにするテクニック
- 無料アニメソフト9VAeきゅうべえの裏技集