diadia

興味があることをやってみる。自分のメモを残しておきます。

Kotlin Android KeyStoreをについて調べる

KeyStoreの有用性

バイスからキー抽出を難しくする。

KotlinでのKeyStoreインスタンス(AndroidKeyStore)の取得する方法。インスタンスの生成は以下のようにする。 KeyStore.getInstance("AndroidKeyStore")

https://www.jssec.org/dl/20160323_Akira_Ando.pdf

https://qiita.com/f_nishio/items/485490dea126dbbb5001

Kotlin Android Studio ライブラリの追加方法について

android studioでライブラリの追加方法について記述する。
Projectタブを押すと、appとGradle Scriptsが表示される。このGradle Scriptsの中にbuld.gradle(Module: app)がある。
このファイルを開き、dependencies{}にライブラリ情報を記述する。そして右上のSync Nowという文字を押せばライブラリをプロジェクトにインストールすることができる。

例:
dependencies {
    implementation 'com.squareup.okhttp3:okhttp:3.11.0'
}

dependeciesに追加する文言について

android studioはバージョンによってライブラリ追加の文言に変化があったようだ。例えば、以下のurlでは

dependencies {
compile 'com.squareup.okhttp3:okhttp:3.11.0'
}

と記述してある。Android Kotlin 實作 Day 12:GithubStars(下)(OkHttp)しかしこれはバージョン2系の記述方法であるらしい。バージョン3系の記述方法は

dependencies {
implementation 'com.squareup.okhttp3:okhttp:3.11.0'
}

上記の様に書くようだ。これについて書いてある記事は以下。
Android Studio3 OkHttp3クライアントアプリを作ろう

Kotlin Android Studio OkHttpについて

HttpUrlConnectionについて

Androidアプリケーションを開発するにいたり、最初に本で学習した。その時にAsncTaskとHttpUrlConnectionを使ってHTTP通信をすることを学んだ。
しかしながらpostメソッドを使う際に情報が不足していたため調べた結果OkHttpの方が使いやすいとわかった。

 

HttpUrlConnectionは古い事もあってより良く改良されたOkHttpの方がよいと判断した。

下記の記事が参考になりました。ありがとう。
Androidの通信ライブラリの歴史を振り返る
AndroidでHTTP通信したいときの手段まとめ

OkHttpサンプルコード

アンドロイドの画面上で同期通信を行うとエラーが出てしまう。だからOkHttpでは非同期通信を行わなければならない。

class SignUpActivity : AppCompatActivity() {

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_sign_up)

        val emailAddress = findViewById(R.id.et_emailAddress)
        val password1 = findViewById(R.id.et_password1)
        val password2 = findViewById(R.id.et_password2)


        val btn_sendSignUpInfo = findViewById

非同期通信ではclient.newCall(request).enqueue()を使う。

Responseの内容を取得することについて

まず、非同期処理を行うclient.newCall(request).enque(...中略...)において、リクエストの結果はresponseである。
そしてこのresponseにJSONデータが入っている場合にはprintln(response)としてもJSONデータは表示することができない。
データを表示する場合にはresponseをJSONデータに戻してあげる必要がある。

val json_data = JSONObject(response.body().string())

参考:
https://medium.com/@rohan.s.jahagirdar/android-http-requests-in-kotlin-with-okhttp-5525f879b9e5

curlについて

curl -X GET http://127.0.0.1:8000/api/example/ -H 'Authorization: Token 9944b09199c62bcf9418ad846dd0e4bbdfc6ee4b'

これの意味を調べる。

参考:https://www.django-rest-framework.org/api-guide/authentication/#tokenauthentication

https://www.setouchino.cloud/blogs/99#post-x-post-d

-XオプションはHTTPメソッドを定めるものである。-Xの値はPOST や GETを設定する。

-Hオプションはリクエストヘッダーに格納したい場合に使うものである。値がヘッダーに格納される。

-d (--data)オプションはデータを送る時に使うものでる。例えばwebサービスでnameというフォームが有り、"hajime"と入力し送信する場合には、curlでは以下のように送信されることになる。

curl -X POST -d 'name=hajime' example.com/send_info

データが複数ある場合には以下のように複数の方法で送信できる。

#①データとデータの間を&でつなぐ方法
curl -X POST -d 'name=hajime&age=23' example.com/send_info/

#②各データを-dオプションを使う方法
curl -X POST -d name=hajime -d age=23 example.com/send_info/

-dオプションの参考url:https://ec.haxx.se/http/http-post

メモ

webviewのOAAUTHのログインも問題についての記事

https://techracho.bpsinc.jp/hachi8833/2016_09_01/25471

ロームカスタムタブについて

https://developer.chrome.com/multidevice/android/customtabs

スタートアップの5つの失敗理由

https://techstricks.com/5-reasons-startups-fail/

Developing Android Client app with Django rest Framework

https://medium.com/@hassanabid/developing-android-client-app-with-django-rest-framework-8d5961a49619

Django Rest Frameworkでソーシャルログインを実装する 

https://blog.sky-net.pw/article/150

Django REST Frameworkでユーザ認証周りのAPIを作る 

https://qiita.com/xKxAxKx/items/60e8fb93d6bbeebcf065

 Django REST frameworkについての雑記

https://qiita.com/yuizho/items/4d4b8495d6170fb519c2

django-rest-frameworkのユーザー認証を実現させる

https://www.django-rest-framework.org/api-guide/authentication/

https://blog.sakaki333.com/blog/view/78

はじめに

この記事はdjnagoをバックエンドとしてandroidアプリケーションを作成することを前提としている。
そしてandroidアプリケーションのユーザー認証周りについてどのように実装していけばよいかについて書く。djangoをバックエンドにandroidのアプリを作成する記事をあまり見つけることができなかったのでこの記事が誰かの力になれば幸いである。

Basic認証のサンプル

from rest_framework.views import APIView
from items.models import Item
from .serializers import ItemSerializer
from .serializers import ItemSerializer
from rest_framework.authentication import BasicAuthentication
from rest_framework import permissions



class TestAPIView(APIView):

	authentication_classes = (BasicAuthentication,)
	permission_classes = (permissions.IsAuthenticated,)

	def get(self, request, *args, **kwargs):
		

		item_objects = Item.objects.all()
		serializer = ItemSerializer(item_objects, many=True)
		return Response(serializer.data)
		

上記のコードでrequestを送ると、データが表示されずにログインフォームが表示された。

https://grandbig.github.io/blog/2016/02/07/android-login-activity/

時間がある時にこの続きを書く。

別の方法でユーザー認証を実現させる

django-rest-authを利用する方法

まずユーザー周りのエンドポイントを実装する

https://django-rest-auth.readthedocs.io/en/latest/index.html

上記はdjango-rest-framwork用のユーザー認証等を実現させるためにあるライブラリである。django-allauthのようにpipでインストールするとエンドポイントが自動的に決定される。このdjango-rest-authで決められたエンドポイントにアクセスすることで、ログイン認証ができたり、ユーザー登録など実装の手間を省くことができる。
django-rest-authでエンドポイントを設定したら後はアンドロイドアプリで指定のエンドポイントを記述すれば認証周りの仕組みを実装できそうだ。

具体的な例として、ユーザー登録の実装方法を考える。

f:id:torajirousan:20200125172645p:plain

http://localhost:8000/rest-auth/registration/にアクセスすると上記の画面を表示する事ができる。(django-rest-authをインストールすることが前提である。)
画像下部のUsername, Email, Password1, Password2フォームを埋めてPOSTボタンを押すとトークンが返ってくる。

f:id:torajirousan:20200125173600p:plain

送信内容に誤りがなければ、トークンが返されることを上記の画像で確認できる。このトークンを使って次回からログイン認証を行うことになる。
ちなみにdjango-rest-frameworkにはベーシック認証とトークンを使った認証が準備されており、この例ではトークンを使った認証を採用している。
参考:https://www.django-rest-framework.org/api-guide/authentication/#api-reference
このトークン認証の設定にはINSTALLED_APPSに'rest_framework.authtoken'を追加することと、settings.pyにTokenAuthenticationを追加すれば良い。

これらを確認できたらユーザー認証周りのエンドポイントは準備できたことになる。

エンドポイントにwebではない方法でHTTPで接続してみる

先程作成したユーザー登録するエンドポイント/rest-auth/registration/にはKotlinでアクセスすることになる。だからdjango-rest-frameworkのユーザーインターフェースを使わず、純粋なHTTPプロトコルでユーザー登録ができるか確認するべきである。その手段としてcurlを用いる。
curlについては必要最低限ここにまとめた。

curl -X POST -d 'username=&email=testmyga@gmail.com&password1=1234tweet&password2=1234tweet' http://127.0.0.1:8000/rest-auth/registration/ 

上記のように入力すると、ターミナルには{"key":"b2fa2985300735de965fe2ec80cb0247e2f7bccf"}のような形で返される。このように返されたらHTTPプロトコルでユーザー登録を実行することができた証拠なので、この形式をKotlinのアクティビティ(.ktファイル)で記述すれば良いと判断できる。なお、curlのコマンドの例ではusernameを入力不要の設定にしてる。

レイアウトファイルのエラー原因

LinearLayout

自分がよく起こすレイアウトファイルのエラーはLinearLayoutに/をつけることが問題であった。

<LinearLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:orientation="vertical">

省略


</LinearLayout>

これが正しい書き方であるが、最初のタグに"/>"を書くとエラーが出てしまう。

TextViewやImageView等

TextViewやImageViewなどの閉じタグが必要ない一つで完結するタグにおいては、"/>"にするのが正しい記法である。
一方で"/"無しでタグを閉じるとエラーが出てしまうので注意すること。

Multiple root tags エラー

参考:https://teratail.com/questions/45822

レイアウトファイルの構成ではルートになるタグが複数あってはいけないようだ。これはxmlの決まりなのかもしれない。
https://stackoverflow.com/questions/5042902/xml-error-there-are-multiple-root-elements

kotlin : 画面遷移先でintentに格納データを取り出す方法

Intentで画面遷移したデータを取得する

intentインスタンスにデータが格納されているので、getStringExtra()メソッドを使って取り出す。なおintentは遷移先のアクティビティで特にintentを取り出さなくてもそのまま使えるようだ。

NextActivity : AppCompatActivity() {
    override fun onCreate(savedInstanceState : Bundle?){
    
        val country_name = intent.getStringExtra("country_name")
    
    
    }

}

エラー対処:Exception android.util.AndroidRuntimeException: Calling startActivity() from outside of an Activity context requires the FLAG_ACTIVITY_NEW_TASK flag.

参考:
https://www.lanches.co.jp/blog/9776

要するにIntent.FLAG_ACTIVITY_NEW_TASKを設定すれば良いみたい。

このsetFlagsについてはまだ理解していないので次回の機会で。。。

intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK)

コーディングイメージ

val context = SingletonContext.applicationContext()
val intent = Intent(context, DetailActivity::class.java)
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
context.startActivity(intent)

AsyncTaskのonPostExecuteメソッドから画面遷移させる方法

参考

これが参考になった。
https://xbuba.com/questions/51962885

https://stackoverflow.com/questions/51962885/how-to-change-activity-from-onpostexecute-method-using-kotlin?rq=1