質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
87.20%

解決済

Android開発でネットワーク通信がうまくいかない。

mokimokio
mokimokio

総合スコア53

1回答

0評価

0クリップ

278閲覧

投稿2022/04/27 02:31

編集2022/04/28 13:07

助けて欲しいです。何日もkotlinでネットワーク通信をしたいと取り組んでいるのですがうまくいきません。
参考にしているサイトは
https://qiita.com/naoi/items/5036adc8d33638911deb#buildgradleapp%E3%81%B8%E3%81%AE%E8%BF%BD%E8%A8%98

です。

やりたいことは
Android画面でボタンを押したらその時の時刻と、IDを送信する。
⬇️
ネットワーク上でphpを組んで、そこでIDと時刻をデータベースに登録する。
⬇️
そしてデータベースで登録ができたら、phpで「〇〇様登録完了」と出す。
⬇️
phpの「OO様登録完了」文字をAndroidのtextviewに表記させる。

といった流れです。いろいろ試しに試してコードがぐちゃぐちゃになったので一度スッキリさせてここにまとめておきます。

もはや組み方が分かりません。可能であれば上記の流れを達成するためのコードを下記コードに正解のコードを書き足していただけませんか?それ見て勉強していきたいです><

自分のわからないところをピックアップしました。(これで足りているか不安ですが、、、)
①そもそもサイトには【GETメソッドでHTTP通信する実装方法】のところにMyService.ktと書かれているがPOSTの場合でもこれが必要なのか。
②(上記が必要な場合)MyService.ktの定義の中身を今回の実装したいものではどのように組めばいいのかわからない。
③val postの中身の組み方がわからない。(わからないのでval post内はサイトからコピペした状態のままにしている)、そしてval postを非同期の中で宣言してみたが、この場所でいいのかわからない
④⭐️部分は非同期処理内でネットワーク通信を終えた後にTV.textに呼び出したいのだが、なんて書けばいいのかわからない。

MainActivity.kt

import android.os.Build import androidx.appcompat.app.AppCompatActivity import android.os.Bundle import android.util.Log import android.widget.Button import android.widget.TextView import android.widget.Toast import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.Job import kotlinx.coroutines.delay import kotlinx.coroutines.withContext import retrofit2.Retrofit import java.time.LocalDateTime class MainActivity : AppCompatActivity() { // Retrofit本体 private val retrofit = Retrofit.Builder().apply { baseUrl("http://10.0.2.2:3000/") }.build() val get = service.getRawResponseForPosts() override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContentView(R.layout.activity_main) val TV : TextView = findViewById(R.id.TextView1) // ボタンを押した時の処理 val btn : Button = findViewById(R.id.button1) // ボタンを連打したときに何度も処理してしまうのを防ぐため。jobを設定する var job: Job? = null btn.setOnClickListener { var nowTime = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { LocalDateTime.now() } else { TODO("VERSION.SDK_INT < O") } TV.text = nowTime.toString() //下記にすることで連打したときに何度も処理されることを防げる。coroutinesが複数起動しなくなるということ。 if (job?.isActive == true) return@setOnClickListener job = lifecycleScope.launch {       //result内のスコープがIOスレッドで実行される withContext(Dispatchers.IO) { val post = service.getRawResponseForPosts().also { it.enqueue(object : Callback<List<Post>> { override fun onFailure(call: Call<List<Post>>, t: Throwable) { Toast.makeText(this@MainActivity, "通信エラー", Toast.LENGTH_SHORT).show() Log.e("TEST", "通信エラー", t) } override fun onResponse(call: Call<List<Post>>, response: Response<List<Post>>) { myViewModel.result.value = response.body().toString() } }) } }        //Main内のスレッドがIOスレッド内でメインスレッドも実行可能となる。 withContext(Dispatchers.Main) { TV.text = ⭐️ } } } } }

AndroidManifest.xml

<?xml version="1.0" encoding="utf-8"?> <manifest xmlns:android="http://schemas.android.com/apk/res/android" package="com.example.myapplication"> <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/Theme.MyApplication"> <activity android:name=".MainActivity" android:exported="true"> <intent-filter> <action android:name="android.intent.action.MAIN" /> <category android:name="android.intent.category.LAUNCHER" /> </intent-filter> </activity> </application> </manifest>

activity_main.xml

<?xml version="1.0" encoding="utf-8"?> <androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" tools:context=".MainActivity"> <TextView android:id="@+id/TextView1" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="Hello World!" app:layout_constraintBottom_toBottomOf="parent" app:layout_constraintLeft_toLeftOf="parent" app:layout_constraintRight_toRightOf="parent" app:layout_constraintTop_toTopOf="parent" /> <Button android:id="@+id/button1" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="Button" app:layout_constraintBottom_toBottomOf="parent" app:layout_constraintEnd_toEndOf="parent" app:layout_constraintStart_toStartOf="parent" app:layout_constraintTop_toBottomOf="@+id/TextView1" /> </androidx.constraintlayout.widget.ConstraintLayout>

build.gradle(:app)

dependencies { implementation 'androidx.core:core-ktx:1.7.0' implementation 'androidx.appcompat:appcompat:1.4.1' implementation 'com.google.android.material:material:1.5.0' implementation 'androidx.constraintlayout:constraintlayout:2.1.3' testImplementation 'junit:junit:4.13.2' androidTestImplementation 'androidx.test.ext:junit:1.1.3' androidTestImplementation 'androidx.test.espresso:espresso-core:3.4.0' def retrofit_version = "2.9.0" implementation "com.squareup.retrofit2:retrofit:$retrofit_version" implementation "com.squareup.retrofit2:converter-moshi:$retrofit_version" implementation "com.squareup.okhttp3:logging-interceptor:4.9.0" implementation "androidx.lifecycle:lifecycle-viewmodel-ktx:2.1.0" testImplementation 'junit:junit:4.13.2' androidTestImplementation 'androidx.test.ext:junit:1.1.3' androidTestImplementation 'androidx.test.espresso:espresso-core:3.4.0' }

これより下3つのファイルは冒頭のサンプルURLを参考にして作成したファイルです。どう使うのか、そして今回僕がしたいことに必要なのか僕には理解が届きませんでしたがとりあえず作成しました。

MyService.kt

import android.telecom.Call import okhttp3.RequestBody import okhttp3.ResponseBody import retrofit2.http.* import retrofit2.Call as Call1 //URLのサブディレクトリやパスの設定 interface MyService{ @GET("posts") fun getRawResponseForPosts(): Call<ResponseBody> @POST("posts") fun postRawRequestForPosts(@Body body:RequestBody):Call<ResponseBody> @PUT("posts/{id}") fun putRawRequestForPosts(@Path("id") id:String, @Body body:RequestBody):Call<ResponseBody> @DELETE("posts/{id}") fun deletePathParam(@Path("id") id:String ):Call<ResponseBody> }

自分が送信したい情報はIDと時間なのでここは書き換えました。⬇️

Post.kt

data class Post( val id: Int = 1111, val time: String )

Util.kt

object Util { fun createJson(id:Int,time:String):String ="{" + " \"id\": \"${id}\"," + " \"time\": \"${time}\"," + "}" }

最後にAPI接続先のphpファイルです。これはここではざっくりとこんな感じという風に書かせていただきます。try catch やデータベース情報などこの質問に不必要なものは外しています。

php

<?php $id=$_POST['id']; $time=$_POST['time']; データベース接続の処理 データベース登録の処理 登録成功なら echo'〇〇様登録完了';

以上です。
長々とした質問ですみません。数日戦っても組み方に見当がつかないのでどなたかご教授よろしくお願いします。

なお、自分の質問にミスがあればすぐに訂正致しますので気軽にコメント下さい。

良い質問の評価を上げる

以下のような質問は評価を上げましょう

  • 質問内容が明確
  • 自分も答えを知りたい
  • 質問者以外のユーザにも役立つ

評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

気になる質問をクリップする

クリップした質問は、後からいつでもマイページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。

  • プログラミングに関係のない質問
  • やってほしいことだけを記載した丸投げの質問
  • 問題・課題が含まれていない質問
  • 意図的に内容が抹消された質問
  • 過去に投稿した質問と同じ内容の質問
  • 広告と受け取られるような投稿

評価を下げると、トップページの「アクティブ」「注目」タブのフィードに表示されにくくなります。

jimbe

2022/04/27 04:20 編集

何が分からないのでしょうか。「いろいろ試しに試してコードがぐちゃぐちゃになったので一度スッキリ」させ過ぎて何も無くなっています。「うまくいきません」では何も分かりません。 どこかでエラーになるのでしょうか。それともプログラムが終了しないとかでしょうか。 ぐちゃぐちゃになったら一旦今のコードは何処かにしまって、2~3日このプログラムのことは一切考えないで休憩してから一から考え直す・作り直すのもテかと思います。
mokimokio

2022/04/27 04:58

Hoshi-takanori様 Logcatにエラーはたくさん出ていますが、そもそも組み方がわかっていないのでそれ以前の問題だと思うんです。。。(汗 AndroidManifestの内容も本文に追加しました。あっているか確認していただけますか?😭
mokimokio

2022/04/27 05:01

jimbe様 本来のままのコードを追記しました。 そして、自分のわからないところをピックアップしました。(これで足りているか不安ですが、、、) ①そもそもサイトには【GETメソッドでHTTP通信する実装方法】のところにMyService.ktと書かれているがPOSTの場合でもこれが必要なのか。 ②(上記が必要な場合)MyService.ktの定義の中身を今回の実装したいものではどのように組めばいいのかわからない。 ③val postの中身の組み方がわからない。(わからないのでval post内はサイトからコピペした状態のままにしている)、そしてval postを非同期の中で宣言してみたが、この場所でいいのかわからない ④⭐️部分は非同期でネットワーク通信を終えた後にTV.textに呼び出したいのだが、なんて書けばいいのかわからない。 いっぱいあってすみません。
hoshi-takanori

2022/04/27 05:06

AndroidManifest は大丈夫そうですね。 Logcat は確かにいっぱい出てきて最初は意味不明だと思いますが、必ず必要になるので、早めに見方を覚えることをお勧めします。 そして、確認ですが、サーバーはちゃんと動いてますか? Android から繋ぐ前に、ブラウザから繋がることを確認すると良いでしょう。
mokimokio

2022/04/27 05:53

hoshi-takanori様 分かりましたLog catもしっかり見て覚えていきます。 サーバーは動いています!iOSアプリでは接続できているのでそれは間違い無いです!
jimbe

2022/04/27 06:51 編集

http のリクエストは get でしょうか post でしょうか。 サーバからの戻りの Json はどうなっているのでしょうか。
mokimokio

2022/04/27 06:54

jimbe 戻りと言いますか、 phpから帰ってくるのは文字列で '〇〇様登録完了'のみです! jsonで返した方がいい場合は戻しのやり方変更します!
dodox86

2022/04/27 06:59

最初から完成させようとするから分からなくなります。一つ一つやれば良いのに。
mokimokio

2022/04/27 07:06

jimbe様すみません!一つ回答できてませんでした!やりたいのはpostです!
mokimokio

2022/04/27 07:06

dodox86様 ありがとうございます!もうちょっと細分化してやってみます!

まだ回答がついていません

会員登録して回答してみよう

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
87.20%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問

同じタグがついた質問を見る