●SSLで通信

まず、権限をアプリに追加しないと始まりません。
そこで、インターネットのアクセス権限を与える為に、
MyApplication?\app\src\main\AndroidManifest.xml
この場所にある、AndroidManifest.xmlファイルを開きます。

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="mail.myapplication">
    <uses-permission android:name="android.permission.INTERNET" />
    <application
        android:theme="@style/AppTheme">
        <activity android:name=".MainActivity">
            <intent-filter>

            </intent-filter>
        </activity>
    </application>
</manifest>
赤文字の部分を追加することによりインターネットのアクセス権限をアプリに追加する事が出来ます。


■クライアント側の通信

androidでSSLで通信するにはjavaのSSLSocketを使います。
ウェブサーバーのSSL通信では、ポート443番に接続します。

相手先のアドレスのポートに接続するソケットを用意して、
javax.net.ssl.SSLSocketFactory sslSocketFactory = (javax.net.ssl.SSLSocketFactory) javax.net.ssl.SSLSocketFactory.getDefault();
javax.net.ssl.SSLSocket sslSocket = (javax.net.ssl.SSLSocket) sslSocketFactory.createSocket("アドレス",ポート番号);

データを取得するストリーム
java.io.InputStream in = sslSocket.getInputStream();

データを送信するストリーム
java.io.OutputStream out = sslSocket.getOutputStream();

により基本的に通信を行います。

しかし、SSLの場合には受け取った証明書が接続先サーバーの物か確認する必要があります。
確認しないのならば、証明書が接続先サーバーの物でなくてもかまいません。
別に確認しなくても暗号化して通信できますが、悪意ある第三者に悪用される恐れがあります。
javax.net.ssl.HostnameVerifier hv = javax.net.ssl.HttpsURLConnection.getDefaultHostnameVerifier();
javax.net.ssl.SSLSession s = sslSocket.getSession();
if (!hv.verify("証明書に書いてあるはずのアドレス", s)) {
	return (Object)("証明書が一致しません "+s.getPeerPrincipal());
}

次のプログラムではグーグルのhttpsサーバーであるポート443番にアクセスして返ってきた文字を表示します。
インターネットの通信はメインスレッドでは出来ない仕様になっているため、何らかの形でThreadを立てる必要があります。

androidらしく通信をAsyncTaskで行いました。
別に、通常のThreadを立てて通信しても問題なく行けます。

public class MainActivity extends AppCompatActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        ((android.widget.Button)findViewById(R.id.button))
                .setOnClickListener(new android.view.View.OnClickListener() {
                    public void onClick(android.view.View view) {
                        asyncTask a=new asyncTask();
                        a.execute((Object)"www.google.com",(Object)443,new Object()) ;
                    }
                });
    }
    private class asyncTask extends android.os.AsyncTask{
        @Override
        protected Object doInBackground(Object... obj){
            //この関数は別スレッドで実行されるため、画面周りに関わる処理は出来ない。
            //また、戻り値はonPostExecuteの引数に渡され、そこで画面周りの処理ができる。
            try
            {
                javax.net.ssl.SSLSocket sslSocket = null;
                javax.net.ssl.SSLSocketFactory sslSocketFactory = (javax.net.ssl.SSLSocketFactory) javax.net.ssl.SSLSocketFactory.getDefault();
                sslSocket = (javax.net.ssl.SSLSocket) sslSocketFactory.createSocket((String)obj[0],(int)obj[1]);

                //証明書が該当ホストと一致するか確認
                javax.net.ssl.HostnameVerifier hv = javax.net.ssl.HttpsURLConnection.getDefaultHostnameVerifier();
                javax.net.ssl.SSLSession s = sslSocket.getSession();
                if (!hv.verify((String)obj[0], s)) {
                    return (Object)("証明書が一致しません "+s.getPeerPrincipal());
                }

                java.io.InputStream in = sslSocket.getInputStream();
                java.io.OutputStream out = sslSocket.getOutputStream();
                java.io.BufferedReader br = new java.io.BufferedReader( new java.io.InputStreamReader(in, "UTF-8")  );
                java.io.BufferedWriter bw = new java.io.BufferedWriter( new java.io.OutputStreamWriter(out, "UTF-8")  );

                bw.write("GET / HTTP/1.0\n\n");
                bw.flush();

                String  pos,str="";
                while((pos = br.readLine()) != null){
                    str+=pos;
                }

                in.close();
                out.close();
                sslSocket.close();
                return (Object)str;
            }
            catch( Exception e )
            {
                return (Object)e.toString();
            }
        }
        @Override
        protected void onPostExecute(Object obj) {
            //doInBackgroundの戻り値が引数に渡される
            //メインスレッドで実行されるため、画面周りの処理ができる。

            //画面にメッセージを表示する
            android.content.Context context = getApplicationContext();
            android.widget.Toast t=android.widget.Toast.makeText(context,(String)obj, android.widget.Toast.LENGTH_LONG);
            t.show();
        }
    }
}

画面にボタンを張り付けてこのプログラムを実行すると、次の様になります。



グーグルのサーバーが送り返してくるHTMLコードが表示されているのが見えます。


▲トップページ > android