ニフクラ mobile backend(mBaaS)お役立ちブログ

スマホアプリ開発にニフクラ mobile backend(mBaaS)。アプリ開発に役立つ情報をおとどけ!

KotlinでNCMBを使う:ファイルストアに写真をアップロードする

AndroidではJavaの他、Kotlinも公式言語としてサポートされています。KotlinはJVM上で動作する静的な型付け言語で、言語体系がSwiftに似ています。そのため、Swiftに慣れた開発者であればすぐに習得できるかと思います(似ているので逆に戸惑う部分もあるのですが)。

今回はAndroid Studio 3系を使い、KotlinでNCMBを利用する方法を解説します。今回はカメラで撮影したデータをファイルストアにアップロードする方法を解説します。

Android Studioでプロジェクトを作成する

Android Studio 3系からKotlinプラグインをインストールせずにKotlinプロジェクトを作成できるようになりました。まずは新しいプロジェクトを作成します。

f:id:mbaasdevrel:20181207094347p:plain

新しいプロジェクトを作成する際にInclude Kotlin Supportをチェックします。これでKotlinベースのコードが生成されます。

f:id:mbaasdevrel:20181207094507p:plain

他はデフォルトのままです。Phone and Tabletを対象にし、 APIはある程度新しいもの(今回は23)を選択します。

f:id:mbaasdevrel:20181207094525p:plainf:id:mbaasdevrel:20181207094525p:plain

さらにベースは何もなし、Empty Activityを選択します。

f:id:mbaasdevrel:20181207094536p:plain

Activity NameはMainActivity、Layout Nameはactivity_mainというのもデフォルトのままです。

f:id:mbaasdevrel:20181207094555p:plain

NCMBを追加する

プロジェクトが作成されたらファイルツリーを右クリックして、Open Module Settingsを選択します。

f:id:mbaasdevrel:20181207094605p:plain

開いたウィンドウで、上にあるプラスアイコンをクリックします。

f:id:mbaasdevrel:20181207094652p:plain

そしてImport .JAR/.AAR Packageを選択します。

f:id:mbaasdevrel:20181207094710p:plain

次のダイアログでNCMB.jarを選択します。NCMB.jarはこちらからダウンロードし、解凍します。

f:id:mbaasdevrel:20181207094721p:plain

追加すると、左側のメニューでappの下にNCMBが追加されます。ついでDependenciesをクリックします。

f:id:mbaasdevrel:20181207094843p:plain

下にあるプラスアイコンをクリックし、Module dependencyを選択します。

f:id:mbaasdevrel:20181207094859p:plain

モジュールの選択でNCMBを選びます。

f:id:mbaasdevrel:20181207094908p:plain

一覧にNCMBが追加されたら完了です。

f:id:mbaasdevrel:20181207094941p:plain

セキュリティ設定を変更する

AndroidManifest.xml を開いて設定を追加します。 android.permission.INTERNET はインターネット接続を用いる設定です。 android.permission.CAMERA はカメラにアクセスするための設定です。

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="jp.moongift.ncmbupdatedatastore">
    <!-- 以下の uses-permission を追加 -->
    <uses-permission android:name="android.permission.INTERNET" />
    <uses-permission android:name="android.permission.CAMERA" />
    <application
      :
    />
</manifest>

これで準備完了です。

SDKをインポートする

まずNCMBを利用する画面のKotlinファイルを開きます。今回は MainActivity.kt を編集します。今回は基礎になる NCMB クラスと、データストアで用いる NCMBObject クラスを読み込んでいます。

import com.nifcloud.mbaas.core.NCMB
import com.nifcloud.mbaas.core.NCMBObject

そして override fun onCreate の内容を編集します。 APPLICATION_KEYCLIENT_KEY はそれぞれのキーに書き換えてください。

override fun onCreate(savedInstanceState: Bundle?) {
    super.onCreate(savedInstanceState)
    setContentView(R.layout.activity_main)
    // 初期化
    NCMB.initialize(applicationContext, "APPLICATION_KEY", "CLIENT_KEY")

カメラが利用できるか確認

これはNCMBとは直接関係ありませんが、カメラ機能が利用できるか(許可も含めて)確認します。

var btnCamera: Button = findViewById(R.id.btnCamera)
btnCamera.setOnClickListener {
    // カメラ機能を実装したアプリが存在するかチェック

    Intent(MediaStore.ACTION_IMAGE_CAPTURE).resolveActivity(packageManager)?.let {
        if (checkCameraPermission()) {
            takePicture()
        } else {
            grantCameraPermission()
        }
    } ?: Toast.makeText(this, "カメラを扱うアプリがありません", Toast.LENGTH_LONG).show()
}

private fun checkCameraPermission() = PackageManager.PERMISSION_GRANTED ==
        ContextCompat.checkSelfPermission(applicationContext, Manifest.permission.CAMERA)

private fun grantCameraPermission() =
        ActivityCompat.requestPermissions(this,
                arrayOf(Manifest.permission.CAMERA),
                CAMERA_PERMISSION_REQUEST_CODE)

カメラを起動する

これもNCMBには直接関係しませんが、ボタンを押したタイミングでカメラを起動します。

private fun takePicture() {
    val intent = Intent(MediaStore.ACTION_IMAGE_CAPTURE).apply {
        addCategory(Intent.CATEGORY_DEFAULT)
    }
    startActivityForResult(intent, CAMERA_REQUEST_CODE)
}

写真撮影後

写真を撮影したら onActivityResult が呼び出されます。

override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
    if (requestCode == CAMERA_REQUEST_CODE && resultCode == Activity.RESULT_OK) {
        photoUpload(data)
    }
}

そしてIntentとして渡される data を使ってファイルストアにアップロード処理を行います。データはビットマップにキャストし、さらにByteArrayに変換します。今回は写真データをPNGにしていますが、JPEGにすることも可能です。

fun photoUpload(data: Intent?)  = GlobalScope.launch(Dispatchers.Main) {
    try {
        var bm = data?.getExtras()?.get("data") as Bitmap
        val byteArrayStream = ByteArrayOutputStream()
        bm.compress(Bitmap.CompressFormat.PNG, 0, byteArrayStream);
        var dataByte = byteArrayStream.toByteArray()
        val acl = NCMBAcl()
        acl.publicReadAccess = true
        acl.publicWriteAccess = true
        var file = NCMBFile("photo.jpg", dataByte, acl)
        async(Dispatchers.Default) {file.save()}.await()
        Log.d("[DEBUG]", "done.")
    } catch (e: NCMBException) {
        // cameraImage.setImageBitmap(it as Bitmap)
    }

}

このような処理によって、写真アップロード処理が実現できます。

f:id:mbaasdevrel:20190222161047j:plain

まとめ

カメラで撮影したデータをアップロードしたいというニーズはよくあります。Androidの場合はByteArrayへの変換が肝になります。ぜひチャレンジしてみてください!

中津川 篤司

中津川 篤司

NCMBエヴァンジェリスト。プログラマ、エンジニアとしていくつかの企業で働き、28歳のときに独立。 2004年、まだ情報が少なかったオープンソースソフトの技術ブログ「MOONGIFT」を開設し、毎日情報を発信している。2013年に法人化、ビジネスとエンジニアを結ぶDXエージェンシー「DevRel」活動をスタート。