以前のリビジョンの文書です
var list:MutableList<Map<String,String>> = mutableListOf() var map:Map<String,String> = mapOf("name" to "お味噌汁" ,"price" to "100") list.add(map) map= mapOf("name" to "お寿司","price" to "2000") list.add(map) map= mapOf("name" to "カレー","price" to "600") list.add(map) val from:Array<String> = arrayOf("name","price") val to:IntArray = intArrayOf(android.R.id.text1,android.R.id.text2 ) val adpter:SimpleAdapter= SimpleAdapter(this ,list,android.R.layout.simple_expandable_list_item_2,from,to) list1.adapter=adpter
list1.setOnItemClickListener { adapterView, view, i, l -> val item:Map<String,String> = adapterView.getItemAtPosition(i) as Map<String, String> var intent:Intent=Intent(this,ThanksActivity::class.java) //javaのクラスはこのようにかく intent.putExtra("menuName",item["name"]) intent.putExtra("menuPrice",item["price"]) startActivity(intent) }
↓
val intent = getIntent() menu.text="あなたの注文は ${intent.getStringExtra("menuName")} で ${intent.getStringExtra("menuPrice")} 円です!"
val intent = getIntent() val ban:Bundle?=intent.extras for (k in ban?.keySet()!!){ Log.d("TagName", "key=${k} val=${ban[k] as String}") }
override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) //この1行追加 supportActionBar?.setDisplayHomeAsUpEnabled(true) } override fun onOptionsItemSelected(item: MenuItem): Boolean { val id = item.itemId if(id == android.R.id.home) finish() return super.onOptionsItemSelected(item) }
E/AndroidRuntime: FATAL EXCEPTION: DefaultDispatcher-worker-1 Process: com.nekotype.ips.api, PID: 22804 android.view.ViewRootImpl$CalledFromWrongThreadException: Only the original thread that created a view hierarchy can touch its views. ↓ ・・・ GlobalScope.launch { val apidata = URL("http://weather.livedoor.com/forecast/webservice/json/v1?city=130010").readText() async(Dispatchers.Main) { //UIスレッドでコルーチンを実行する text.text=apidata } ・・・
E/AndroidRuntime: FATAL EXCEPTION: DefaultDispatcher-worker-1 Process: com.nekotype.ips.api, PID: 22981 java.io.IOException: Cleartext HTTP traffic to weather.livedoor.com not permitted
step1:xmlフォルダを作り、network_security_config.xmlを作成する。
<?xml version="1.0" encoding="utf-8"?> <network-security-config> <domain-config cleartextTrafficPermitted="true"> <domain includeSubdomains="true">livedoor.com</domain> </domain-config> </network-security-config>
AndroidManifest.xmlに作成したnetwork_security_configへの参照を追加する。
<?xml version="1.0" encoding="utf-8"?> <manifest xmlns:android="http://schemas.android.com/apk/res/android" package="com.nekotype.ips.api"> <uses-permission android:name="android.permission.INTERNET"/> <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/> <application android:allowBackup="true" android:icon="@mipmap/ic_launcher" android:label="@string/app_name" android:roundIcon="@mipmap/ic_launcher_round" android:supportsRtl="true" android:theme="@style/AppTheme" android:networkSecurityConfig="@xml/network_security_config"> //←ここ <activity android:name=".ResultActivity"></activity> <activity android:name=".MainActivity"> <intent-filter> <action android:name="android.intent.action.MAIN" /> <category android:name="android.intent.category.LAUNCHER" /> </intent-filter> </activity> </application> </manifest>
E/AndroidRuntime: FATAL EXCEPTION: DefaultDispatcher-worker-1 Process: com.nekotype.ips.api, PID: 23831 javax.net.ssl.SSLPeerUnverifiedException: Hostname weather.livedoor.com not verified:
証明書エラーを無視するようにしてみたが、なぜか301が帰ってきてしまう。
<html> <head><title>301 Moved Permanently</title></head> <body bgcolor="white"> <center><h1>301 Moved Permanently</h1></center> <hr><center>nginx</center> </body> </html>
一応やってみた2パターンの対応
fun myTask(id:String){ GlobalScope.launch { disableSSLCertificateChecking() //証明書の無効処理呼び出し val urlStr = "https://weather.livedoor.com/forecast/webservice/json/v1?city=${id}" //val urlStr = "https://chargen-api.herokuapp.com/" //val urlStr = "https://www.google.co.jp/" val url= URL(urlStr) val con=url.openConnection() as HttpsURLConnection con.requestMethod="GET" con.connect() val stream=con.getInputStream() val response=streamToString(stream) async(Dispatchers.Main) { text.text=response } } } private fun streamToString(stream: InputStream?): String { val reader=BufferedReader(InputStreamReader(stream,"UTF-8")) val sb=StringBuilder() val b = CharArray(10240) var line:Int val result = reader.read(b).let { sb.append(b,0,it) } return result.toString() } // 証明書の無効処理 @Throws(Exception::class) fun disableSSLCertificateChecking() { println("[WARN] *** SSLCertificate Checking DISABLED ***") // ホスト名の検証を行わない val hv = HostnameVerifier { s, ses -> println("[WARN] *** HostnameVerifier DISABLED *** ") true } HttpsURLConnection.setDefaultHostnameVerifier(hv) // 証明書の検証を行わない val km: Array<KeyManager>? = null val tm = arrayOf<TrustManager>(object : X509TrustManager { @Throws(CertificateException::class) override fun checkClientTrusted(arg0: Array<X509Certificate>, arg1: String) { } @Throws(CertificateException::class) override fun checkServerTrusted(arg0: Array<X509Certificate>, arg1: String) { } override fun getAcceptedIssuers(): Array<X509Certificate>? { return null } }) val sslcontext = SSLContext.getInstance("SSL") sslcontext.init(km, tm, SecureRandom()) HttpsURLConnection.setDefaultSSLSocketFactory(sslcontext.socketFactory) }
色々試しているとそもそも動かなくなった…
// ↓ val tm = arrayOf<TrustManager>(object : X509TrustManager { override fun getAcceptedIssuers(): Array<X509Certificate>? { return null } override fun checkClientTrusted(xc: Array<X509Certificate>, type: String) {} override fun checkServerTrusted(xc: Array<X509Certificate>, type: String) {} }) val ctx = SSLContext.getInstance("SSL") ctx.init(null, tm, SecureRandom()) // ↑ val urlStr = "https://weather.livedoor.com/forecast/webservice/json/v1?city=${id}" val url= URL(urlStr) val con=url.openConnection() as HttpsURLConnection // ↓ con.doOutput = true con.sslSocketFactory=ctx.socketFactory // ↑ con.requestMethod="GET" con.connect()
val reader=BufferedReader(InputStreamReader(stream,"UTF-8")) val sb=StringBuilder() val b = CharArray(10240) var line:Int // javaの場合は下。これはそのまま流用できな。 // while(0 <= {line = reader.read(b)}) { // sb.append(b, 0, line); // } val result = reader.read(b).let { sb.append(b,0,it) } return result.toString()
read(b)をreadline()に修正
private fun streamToString(stream: InputStream?): String { val reader=BufferedReader(InputStreamReader(stream,"UTF-8")) val sb=StringBuilder() var line:Int val result = reader.readLine().let { sb.append(it) } return result.toString() }
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical"> <TextView android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_marginBottom="10dp" android:gravity="center" android:text="@string/tv_winfo_title" android:textSize="25sp"/> <LinearLayout android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_marginBottom="10dp" android:orientation="horizontal"> <TextView android:id="@+id/tvCityName" android:layout_width="wrap_content" android:layout_height="wrap_content" android:textSize="20sp"/> <TextView android:id="@+id/tvWeatherTelop" android:layout_width="0dp" android:layout_height="wrap_content" android:textSize="20sp" android:layout_weight="1"/> </LinearLayout> <!--TextViewをScrollViewで囲む--> <ScrollView android:layout_width="match_parent" android:layout_height="match_parent"> <TextView android:id="@+id/tvWeatherDesc" android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_marginBottom="30dp" android:textSize="15sp"/> </ScrollView> </LinearLayout>
val urlStr = "http://weather.livedoor.com/forecast/webservice/json/v1?city=${id}" val url= URL(urlStr) val con=url.openConnection() as HttpURLConnection con.requestMethod="GET" con.connect()
val apidata = URL("http://weather.livedoor.com/forecast/webservice/json/v1?city=${id}").readText()