androidからローカルのLaravelファイルにHttpURLConnection()
を使ってアクセスすると
D/NetworkSecurityConfig: No Network Security Config specified, using platform default
W/System.err: java.io.IOException: Cleartext HTTP traffic to 192.168.xxx.xxx not permitted
とエラーを賜った!
192.168.xxx.xxxには、
<network security Config>の指定がない!
cleartextTrafficPermittedがfalseになってるよ!
ってことでした。
Api29以降は、デフォルトでcleartextTrafficPermittedはfalseにしてあって、Https接続でないとエラーになる仕様。
<network_security_config.xml>を作成して、192.168.xxx.xxxに対して、cleartextTrafficPermittedをtrueにして、AndroidManifest.xmlにnetworkSecurityConfigを設定してあげましょう!
■network_security_config.xmlの設定
192.168.xxx.xxxのcleartextTrafficPermittedをtrueにするよ!
androidプロジェクトのapp\resの下に、xmlフォルダを作成し、その中にnetwork_security_config.xmlファイルを作成しましょう!
<?xml version="1.0" encoding="utf-8"?>
<network-security-config>
<domain-config cleartextTrafficPermitted="true">
<domain includeSubdomains="true">192.168.xxx.xxx</domain>
</domain-config>
</network-security-config>
API29以降は上記コードのcleartextTrafficPermitted
がデフォでfalse
になってます。これを上記のコードのようにtrue
に直してあげて、Http接続でもOkにしてあげましょう。
<domain-config>は必要なだけ追記しましょう^^!
ここはドメインですから、`http://www.@@@.@@@'の@@@.@@@を指定だね!
■AndroidManifest.xmlの設定
<network_security_config.xml>の設定をAndroidManifest.xmlに記述しよう!
<?xml version="1.0" encoding="utf-8"?>
<manifest ... >
<application android:networkSecurityConfig="@xml/network_security_config"
...>
...
</application>
</manifest>
■Laravelサイトに接続するコード
LaravelはLocalhostではなく、IPアドレスで接続します。
webサイトですが、タグが全く書かれていないとnullが返ってくる。例えばファイルにhelloだけ書いてる場合など。read.readLine()は
public class MainActivity extends AppCompatActivity {
TextView textView;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
// オブジェクトを取得するよ!
Button button1 = findViewById(R.id.button1);
Button button2 = findViewById(R.id.button2);
textView = findViewById(R.id.textView);
// ボタン1はローカルにあるLaravelサイトに接続
button1.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
String site = "http://192.168.xxx.xxx:8000";
new httpConnectionAsync().execute(site);
}
});
// ボタン2はグーグル様に!
button2.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
String site = "https:www.google.co.jp";
new httpConnectionAsync().execute(site);
}
});
}
// 非同期通信でHttpURLConnection()で接続する!
private class httpConnectionAsync extends AsyncTask<String,Void,String> {
StringBuffer buffer;
@Override
protected String doInBackground(String... string) {
String site = string[0];
buffer = new StringBuffer();
try {
HttpURLConnection connection = (HttpURLConnection) new URL(site).openConnection();
BufferedReader reader = new BufferedReader(new InputStreamReader(connection.getInputStream()));
while(reader.readLine() != null){
buffer.append(reader.readLine());
}
reader.close();
connection.disconnect();
} catch (IOException e) {
e.printStackTrace();
}
return buffer.toString();
}
@Override
protected void onPostExecute(String stringBuffer){
textView.setText(stringBuffer);
}
}
}
■LaravelからAndroidにCookieを渡してみる
ちょっとだけ データ形式
Laravelには
$request = json_decode($request,true);
っていう文字列を連想配列に変換する便利なメソッドが使えるので、androidとlaravelでデータをやり取りする場合にはjsonが使えるよな形式で!
ちなみにandroidでは、
senddata.put("key1","value1");
senddata.put("key2","value2");
などとして
HttpURLConnectionで
connection.addRequestProperty("senddata",String.balueoOf(senddata);
で送信すればJson形式の文字列で送れる
ではCookie!
AsyncTaskを使います!
Laravelでsetcookieを設定すると、%エンコードされる
なので、 setrawcookieを使ってcookieを送る
Laravel Route
Route::get('/sample',function(){setrawcookie("param","laravel");});
Android
public class MyAsyncTask extends AsyncTask<Void, Void, Map<String,List<String>>> {
@Override
protected Map<String,List<String>> doInBackground(Void... aVoid) {
try {
HttpURLConnection connection = (HttpURLConnection) new URL("https://www...").openConnection();
connection.connect();
Map<String,List<String>> header = connection.getHeaderFields();
connection.disconnect();
} catch (Exception e) {}
return header;
}
@Override
protected void onPostExecute(Map<String,List<String>> m) {
super.onPostExecute(m);
String param = m.get("Set-Cookie").get(0);
Log.d("------>", param);
}
}
LaravelでHeaderをVarDumpするとAndroidで正しく取れない
public function sample(Request $request){
var_dump($_SERVER);
}
これだとAndroid側では$_SERVERのキー値のみ取得できて、値は取得できない。
(var_dump($_SERVER['DOCUMENT_ROOT']が取得できない
)
なぜか、先にvar_dump()するとandroid側でValueのみ取得できる。
なぜ?
public function sample(Request $request){
var_dump("");
var_dump($_SERVER);
これだとvalue値を表示してる。
var_dump($_SERVER['DOCUMENT_ROOT']でルートは取得できる。
うーむ・・・
超時間かかった。辿り着くまで3日。でも一歩前進。いつも通り亀の歩みだね!