Androidアプリからブラウザを起動してWEBサイトに飛んで、ログイン処理などをした後、またアプリに戻ってくる方法のメモです。アプリ側はいろんなactivityからブラウザを起動できて、最後に元のactivityに戻ってくることを想定します。
#AndroidManifest.xmlの設定
<activity android:name=".MainActivity" android:launchMode="singleTask">
<intent-filter>
<action android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.DEFAULT" />
<category android:name="android.intent.category.BROWSABLE" />
<data android:scheme="myappmain" android:host="callback" android:path="/param" />
</intent-filter>
</activity>
<activity android:name=".SubActivity" android:launchMode="singleTask">
<intent-filter>
<action android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.DEFAULT" />
<category android:name="android.intent.category.BROWSABLE" />
<data android:scheme="myappsub" android:host="callback" android:path="/param" />
</intent-filter>
</activity>
-
activityが複数、MainActivityとSubActivityがあると仮定します。
-
intent-filter
にandroid.intent.category.BROWSABLE
を入れてアプリをブラウザから起動できるようにします。 -
activity毎に違うscheme名を付けておきます。
-
最初にブラウザを開いたactivityに戻ってきたいので、
android:launchMode="singleTask"
を入れます。これを入れないと同名のactivityが二重に開いてしまいます。singleTaskの設定を入れた場合はactivityにonNewIntentを入れます(後述)。
#MainActivityでブラウザを起動
//ランダム文字列(code)を作成して保存
CodeGenerator codeGenerator = new codeGenerator();
String code = codeGenerator.getRandomCode();
SharedPreferences sharedPreferences = PreferenceManager.getDefaultSharedPreferences(getApplicationContext());
SharedPreferences.Editor editor = sharedPreferences.edit();
editor.putString("CODE",code);
editor.apply();//またはeditor.commit()
//ブラウザ起動 codeとschemeをパラメータに入れておく
Uri uri = Uri.parse("https://hoge.jp/login/?code=" + code + "&scheme=myappmain");
Intent intent = new Intent(Intent.ACTION_VIEW,uri);
startActivity(intent);
- 上で作成しているcodeはワンタイムパスワードの役割です。ブラウザを起動する度に毎回ランダム文字列を作成してcodeに入れて渡します。このcodeはSharedPreferenceなどアプリ内にも保存しておきます。
- scheme名は、MainActivityからブラウザを起動して、またここに戻ってきたいので、AndroidManifestに設定したmyappmainを入れます。
#WEBサイト側の設定
- /login/index.phpでcodeとschemeを受け取ります。idとパスワードを入れてログイン処理などをします(詳細は省略)。成功したらcomplete.phpに遷移してURLスキームでアプリに戻ってきます。complete.phpにはcodeとschemeを引き続き渡します。
<?php
//前のページからもらう
$code = $_POST["code"];
$scheme = $_POST["scheme"];
?>
//<head>部分
<script type="text/javascript">
window.onload = function(){
//標準ブラウザ用URLスキーム
location.href="<?=$scheme?>://callback/param?code=<?=$code?>"
/*
必要ならこの辺にiPhone用、Chromeブラウザ用にURLスキームを用意する
*/
}
</script>
//<body>部分
//location.hrefが効かなかった時のために、ボタンを残しておく
<form method="get" action="<?=$scheme?>://callback/param?code=<?=$code?>">
<input type="submit" value="自動的にログインしない場合はこちら" />
</form>
- scheme名で戻りたいactivityを指定できます。他のアプリとscheme名が重ならないような名前にする必要があります。
- Chromeブラウザ用のURLスキームを用意するなら、location.hrefを
"intent://callback/param?code=<?=$code?>#Intent;scheme=<?=$scheme?>;package=パッケージ名;end";
にします。 -
location.href
でURLスキームを指定して、アプリを再起動します。location.href
効かない場合のためにbody内にボタンを残しておきます(ボタンを残さないで、ページを強制的に閉じても問題ないかもしれない)。
#MainActivityに戻ってくる
//アプリに戻ってきた時にonResumeが呼ばれるので、そこでcodeなどを取得します
@Override
public void onResume(){
super.onResume();
Intent intent = getIntent();
String action = intent.getAction();
if (Intent.ACTION_VIEW.equals(action)) {
Uri uri = intent.getData();
if (uri != null) {
String param1 = uri.getQueryParameter("code");
String code = sharedPreferences.getString("CODE","ERROR");
//さっき送り出したcodeと合っていれば任意の処理を入れます
if(param1.equals(code)){
/*
アプリ側の任意の処理
アクセストークンなどを保存するとか
*/
}
}
}
}
//AndroidManifestのactivityのlaunchModeをsingleTaskにした場合は、onNewIntentを入れてgetIntent()できるようにします
@Override
public void onNewIntent(Intent intent){
super.onNewIntent(intent);
setIntent(intent);
}
- アプリに戻ってくると、onResumeが動きます。ここでgetIntent()でcodeなどを受けます。AndroidManifestに
android:launchMode="singleTask"
を設定している場合はonNewIntent
を書き加えておきます。これ入れないとデータが受け取れない模様。 - ブラウザ起動時に送り出したcodeと、返ってきたcodeが同じだったら、アプリ内の任意の処理をします。処理後は場合によりますが、sharedPreferencesのcodeをremove(削除)します。
#SubActivityの場合
- scheme名をAndroidManifestで指定したmyappsubにすると、SubActivityに戻ってこられます。
##参考
▼AndroidアプリをURLから起動(まこちの技術情報覚え書き)
http://wavetalker.blog134.fc2.com/blog-entry-72.html