Qiita Teams that are logged in
You are not logged in to any team

Log in to Qiita Team
Community
OrganizationAdvent CalendarQiitadon (β)
Service
Qiita JobsQiita ZineQiita Blog
122
Help us understand the problem. What is going on with this article?
@f-aoyama

Androidアプリ→ブラウザ起動→WEBサイトでログイン処理→URLスキームでアプリを再起動、そして指定したActivityに戻ってくる方法

More than 5 years have passed since last update.

 Androidアプリからブラウザを起動してWEBサイトに飛んで、ログイン処理などをした後、またアプリに戻ってくる方法のメモです。アプリ側はいろんなactivityからブラウザを起動できて、最後に元のactivityに戻ってくることを想定します。

AndroidManifest.xmlの設定

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-filterandroid.intent.category.BROWSABLEを入れてアプリをブラウザから起動できるようにします。

  • activity毎に違うscheme名を付けておきます。

  • 最初にブラウザを開いたactivityに戻ってきたいので、android:launchMode="singleTask"を入れます。これを入れないと同名のactivityが二重に開いてしまいます。singleTaskの設定を入れた場合はactivityにonNewIntentを入れます(後述)。

MainActivityでブラウザを起動

MainActivity.java
//ランダム文字列(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を引き続き渡します。
complete.php
<?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に戻ってくる

MainActivity.java
//アプリに戻ってきた時に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

122
Help us understand the problem. What is going on with this article?
Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
f-aoyama

Comments

No comments
Sign up for free and join this conversation.
Sign Up
If you already have a Qiita account Login
122
Help us understand the problem. What is going on with this article?