I want to make an app that will connect to my python server using sockets.
When I press the connect button it does not even print the got connection on my PS, please help. Thank you
I have this basic code in kotlin:
//Kotlin Code
import android.support.v7.app.AppCompatActivity
import android.os.Bundle
import android.view.View
import android.widget.Toast
import java.io.DataOutputStream
import java.net.Socket
class MainActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.start_page)
fun connect(v : View) {
try{
val soc = Socket("192.168.1.5", 1419)
val dout = DataOutputStream(soc.getOutputStream())
dout.writeUTF("1")
dout.flush()
dout.close()
soc.close()
}
catch (e:Exception){
e.printStackTrace()
}
}
}
The connect function is activated when clicked on a button, this is the xml code for my start screen
<?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.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">
<Button
android:id="#+id/connect"
android:layout_width="108dp"
android:layout_height="50dp"
android:layout_marginBottom="127dp"
android:layout_marginEnd="228dp"
android:layout_marginStart="256dp"
android:onClick="connect"
android:text="#string/connect"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent" />
</android.support.constraint.ConstraintLayout>
and this is my code in python server:
#Python code
import socket
s = socket.socket()
s.bind(('0.0.0.0', 1419))
s.listen(5)
c, addr = s.accept()
print ('Got connection from', addr)
code_encoded = c.recv(1024)
code_decoded = code_encoded.decode('utf-8')
print(code_decoded)
c.close()
s.close()
I fixed it by implementing asynctask in my function and used java instead of kotlin but it should work similarly in kotlin as well.
The function is now, like this,
class ServerConnection extends AsyncTask<MainActivity.ConnParams, Void, Void> {
#Override
protected Void doInBackground(MainActivity.ConnParams... params)
{
String ip = params[0].ip;
int port = params[0].port;
String message = params[0].message;
try
{
Socket socket = new Socket(ip, port);
PrintWriter printWriter = new PrintWriter(socket.getOutputStream());
printWriter.write(message);
printWriter.flush();
printWriter.close();
socket.close();
} catch (IOException e){
e.printStackTrace();
}
return null;
}
}
Although asynctask is not good for tasks where you need it to be in background for longer periods of time, at which time I would recommend using android services.
Related
I got the following Room database and want to output the name of a random user in a textview. Unfortunately running the code yields the output: kotlin.unit inside the textview. My files look like that:
MainActivity.kt
class MainActivity : AppCompatActivity() {
private lateinit var mNameViewModel: NameViewModel
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
mNameViewModel = ViewModelProvider(this).get(NameViewModel::class.java)
val btn = findViewById<Button>(R.id.btn_addName)
val tv = findViewById<TextView>(R.id.tv_showName)
btn.setOnClickListener {
val text = findViewById<EditText>(R.id.et_enterName)?.text.toString()
val name = Name(0, text)
// Add Data to Database
mNameViewModel.addName(name)
Toast.makeText(applicationContext, "Successfully added $text.", Toast.LENGTH_LONG).show()
val randomName = mNameViewModel.getRandomName()
// Without .toString() I get an error, with it it displays kotlin.unit
tv.text = randomName.toString()
}
}
}
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/tv_showName"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Hello World!"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintHorizontal_bias="0.498"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintVertical_bias="0.133" />
<EditText
android:id="#+id/et_enterName"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:ems="10"
android:inputType="textPersonName"
android:hint="Name"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintHorizontal_bias="0.497"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintVertical_bias="0.244" />
<Button
android:id="#+id/btn_addName"
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_toTopOf="parent"
app:layout_constraintVertical_bias="0.379" />
</androidx.constraintlayout.widget.ConstraintLayout>
Name.kt
#Entity(tableName = "name_data")
data class Name (
#PrimaryKey(autoGenerate = true) val id: Int,
#ColumnInfo(name = "name") val name: String
)
NameDao.kt
#Dao
interface NameDao {
#Insert
fun addName(name: Name)
#Query("SELECT name FROM name_data ORDER BY RANDOM() LIMIT 1")
fun getRandomName(): String
}
NameDatabase.kt
#Database(entities = [Name::class], version = 1, exportSchema = false)
abstract class NameDatabase: RoomDatabase() {
abstract fun nameDao(): NameDao
companion object{
#Volatile
private var INSTANCE: NameDatabase? = null
fun getDatabase(context: Context): NameDatabase{
val tempInstance = INSTANCE
if(tempInstance != null){
return tempInstance
}
synchronized(this){
val instance = databaseBuilder(
context.applicationContext,
NameDatabase::class.java,
"name_data"
).build()
INSTANCE = instance
return instance
}
}
}
}
NameRepository.kt
class NameRepository(private val nameDao: NameDao) {
fun getRandomName() { nameDao.getRandomName() }
fun addName(name: Name) { nameDao.addName(name) }
}
NameViewModel.kt
class NameViewModel(application: Application): AndroidViewModel(application) {
private val repository: NameRepository
init {
val nameDao = NameDatabase.getDatabase(application).nameDao()
repository = NameRepository(nameDao)
}
fun addName(name: Name) {
viewModelScope.launch(Dispatchers.IO){
repository.addName(name)
}
}
fun getRandomName() {
viewModelScope.launch(Dispatchers.IO){
repository.getRandomName()
}
}
}
This is how the output of textview when pressing the button.
The database gets populated though.
Apreciate any help to get the data displayed. Thank you!
The issue is that in your getRandomNumber method inside viewmodel you don't return anything that's why you get kotlin.unit . You should instead make sure to return a value
A possible solution would be the following.
Create a method inside your dao which takes a number and returns that row (this will be essentially the random name)
From your repo call that method with a random number you could use Random.getNextInt not sure how do you get a random
From your view model call that method
From your button onClick call the viewModel method
Make sure to use suspend where applicable in order to get a result. For the case that I showcased above that would be to launch a coroutine in view level and make the rest of the calls (vm,repo,dao) suspend
So after some testing and back and forth this is what I have and it seems to be working.
If anyone has some things to bring in I gladly accept them and a big thanks to georkost for all the usefull tips!
// No changes made to database
#Entity(tableName = "name_data")
data class Name (
#PrimaryKey(autoGenerate = true) val id: Int,
#ColumnInfo(name = "name") val name: String
)
//*********************************************************************************
// Changed return type from Query to LiveData<String> (was just String before)
#Dao
interface NameDao {
#Insert
fun addName(name: Name)
#Query("SELECT name FROM name_data ORDER BY RANDOM() LIMIT 1")
fun getRandomName(): LiveData<String> // HERE
}
//*********************************************************************************
// Changed getRandomMeal from fun to val
class NameRepository(private val nameDao: NameDao) {
val getRandomMeal: LiveData<String> = nameDao.getRandomName() // HERE
fun addName(name: Name) { nameDao.addName(name) }
}
//*********************************************************************************
// Added getRandomName val, initialized it and removed the fun
class NameViewModel(application: Application): AndroidViewModel(application) {
val getRandomName: LiveData<String> // HERE
private val repository: NameRepository
init {
val nameDao = NameDatabase.getDatabase(application).nameDao()
repository = NameRepository(nameDao)
getRandomName = repository.getRandomMeal // HERE
}
fun addName(name: Name) {
viewModelScope.launch(Dispatchers.IO){
repository.addName(name)
}
}
}
//*********************************************************************************
// Changed the last row to observe the LiveData and display it in the Text View
class MainActivity : AppCompatActivity() {
private lateinit var mNameViewModel: NameViewModel
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
mNameViewModel = ViewModelProvider(this).get(NameViewModel::class.java)
val btn = findViewById<Button>(R.id.btn_addName)
val tv = findViewById<TextView>(R.id.tv_showName)
btn.setOnClickListener {
val text = findViewById<EditText>(R.id.et_enterName)?.text.toString()
val name = Name(0, text)
// Add Data to Database
mNameViewModel.addName(name)
Toast.makeText(applicationContext, "Successfully added $text.", Toast.LENGTH_LONG).show()
// HERE
mNameViewModel.getRandomName.observe(this, Observer { String -> tv.text = String })
}
}
}
I followed the InMobi guidelines for Android apps step by step but got the following exception from
DataBindingUtil.setContentView(this, R.layout.mainActivity):
Binary XML file line #670: Binary XML file line #670: Error inflating
class com.inmobi.ads.InMobiBanner
<LinearLayout
xmlns:inmobi="http://schemas.android.com/apk/lib/com.inmobi.ads"
android:layout_width="match_parent"
android:layout_height="match_parent" android:paddingLeft="#dimen/activity_horizontal_margin"
android:paddingRight="#dimen/activity_horizontal_margin"
android:paddingTop="#dimen/activity_vertical_margin"
android:paddingBottom="#dimen/activity_vertical_margin"
android:orientation="vertical">
<TextView android:text="Ad"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
<com.inmobi.ads.InMobiBanner
android:id="#+id/bannerAdInMobi"
android:layout_width="320dp"
android:layout_height="50dp"
inmobi:placementId="plid-1526902340491"
inmobi:refreshInterval="60" />
</LinearLayout>
Could anyone offer a tip on how to diagnose it?
Since no one answered after a month, let me post mine.
InMobil's support has kindly helped me find the culprit - layout inflation before InMobiSdk.init(). An app needs to run InMobiSdk.init() before inflating the layout.
My app cannot do this because it uses InMobil ads only under certain conditions (e.g. only the FREE version has ads), so I have removed com.inmobi.ads.InMobiBanner from the layout, and add it in Java code when it is needed.
Ok I Solved this problem . just follow these steps ->
Step 1: Declare the variable in your Activity/fragment
private lateinit var bannerAd: InMobiBanner
Step 2: Initialite InMobiSDK in onCreate()
override fun onCreate(savedInstanceState: Bundle?) {
bannerAd= Helper.InitializInMobiAds(requireContext())
super.onCreate(savedInstanceState)
}
Step 3: here is InitializInMobiAds() method in Helper Class
fun InitializInMobiAds(context: Context): InMobiBanner{
val consentObject = JSONObject()
try {
// Provide correct consent value to sdk which is obtained by User
consentObject.put(InMobiSdk.IM_GDPR_CONSENT_AVAILABLE, false)
// Provide 0 if GDPR is not applicable and 1 if applicable
consentObject.put("gdpr", "0")
// Provide user consent in IAB format
// consentObject.put(InMobiSdk.IM_GDPR_CONSENT_IAB, “ << consent in IAB format >> ”)
} catch (e: JSONException) {
e.printStackTrace()
}
InMobiSdk.init(context, "AcountIdHere" , consentObject, SdkInitializationListener() {
#Override
fun onInitializationComplete(error : Error?) {
if (null != error) {
Log.e("", "InMobi Init failed -" + error.message.toString())
} else {
Log.d("", "InMobi Init Successful")
}
}
})
return InMobiBanner(context, PLID_here)
}
Step 4: now use .load() method in onCreateView() or in whichever block which runs after onCreate()
binding.adView.load()
I have tried webview with Android studio and FB share and other social media share buttons are working fine. But FB direct like and comment button on my website is not working. When I press like button I can see white screen with left top screen number "1". Please kindly help me.
MainActivity.Java
package com.example.neermaicom;
import androidx.appcompat.app.AppCompatActivity;
import android.content.Intent;
import android.net.Uri;
import android.os.Bundle;
import android.view.WindowManager;
import android.webkit.WebSettings;
import android.webkit.WebView;
import android.webkit.WebViewClient;
import static android.content.Intent.*;
public class MainActivity extends AppCompatActivity {
private WebView webView;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
getSupportActionBar().hide();
getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN,WindowManager.LayoutParams.FLAG_FULLSCREEN);
webView = findViewById(R.id.webview);
webView.setWebViewClient(new WebViewClient() {
#Override
public boolean shouldOverrideUrlLoading(WebView view, String url) {
if (url == null || url.startsWith("http://") || url.startsWith("https://")) return false;
try {
Intent intent = new Intent(Intent.ACTION_VIEW, Uri.parse(url));
view.getContext().startActivity(intent);
return true;
} catch (Exception e) {
return true;
}
}
});
webView.loadUrl("http://www.neermai.com");
WebSettings webSettings = webView.getSettings();
webSettings.setJavaScriptEnabled(true);
}
//This method require to use back button if want to go previous web page
#Override
public void onBackPressed() {
if(webView.canGoBack()){
webView.goBack();
}else {
super.onBackPressed();
}
}
Activity_main.xml
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout 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">
<WebView
android:id="#+id/webview"
android:layout_width="match_parent"
android:layout_height="match_parent"/>
</RelativeLayout>
This is due to the Facebook user auth, unfortunately android webview is not fully compatible with auth systems, an alternative that I use in my webview applications is to use "Chrome Custom Tabs" to auth access to the system of comments that I use.
In my application when the user clicks on comment, a Google Chrome tab is opened inside my application showing the comments page, when the user is not logged, the chrome auth the user without having to close or minimize my application to open google chrome. Everything is done within my own application.
To start the Chrome Tab when I added an "Intent" to shouldOverrideUrlLoading, below is an example of my code.
#Override
public boolean shouldOverrideUrlLoading(WebView view, String url) {
if (url.contains("#comments")){
Uri uri = Uri.parse(url);
CustomTabsIntent.Builder builder = new CustomTabsIntent.Builder();
builder.build().launchUrl(PostActivity.this, uri);
return true;
}
else {
view.loadUrl(url);
return true;
}
}
And in Gradle app:
implementation 'androidx.browser:browser:1.3.0-alpha01'
My url for comment pages has "#comments" you change to something standard that you have in your comment page URLs or if the facebook comment system is directly on the post page, put something that is standard in the url of your posts to open in the google chrome tab.
I am just starting with Android Studio. I got some code from the web on how to ass a splash screen to my app, but it has compiling errors. I could use some help.
the errors are:
error. can not find symbol variable imageView2
error. can not find symbol variable s_img
error. can not find symbol variable s_image_black
error. can not find symbol variable s_image_black
I know this is due to my lack of knowledge, but I am just starting and trying to use this example to learn. Any help would be much appreciated.
Cheers
Paul
package org.quaestio.kotlinconvertedwebview;
import android.os.Bundle;
import android.app.Activity;
import android.content.Intent;
import android.widget.ImageView;
import org.quaestio.kotlinconvertedwebview.MainActivity;
import java.util.Random;
public class Splashscreen extends Activity {
Thread splashTread;
ImageView imageView;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_splashscreen);
imageView = (ImageView)findViewById(R.id.imageView2);
imageView.setScaleType(ImageView.ScaleType.FIT_XY);
int[] ids = new int[]{R.drawable.s_img,R.drawable.s_image_black, R.drawable.s_image_black2};
Random randomGenerator = new Random();
int r= randomGenerator.nextInt(ids.length);
this.imageView.setImageDrawable(getResources().getDrawable(ids[r]));
splashTread = new Thread() {
#Override
public void run() {
try {
int waited = 0;
// Splash screen pause time
while (waited < 3500) {
sleep(100);
waited += 100;
}
Intent intent = new Intent(Splashscreen.this,
MainActivity.class);
intent.setFlags(Intent.FLAG_ACTIVITY_NO_ANIMATION);
startActivity(intent);
Splashscreen.this.finish();
} catch (InterruptedException e) {
// do nothing
} finally {
Splashscreen.this.finish();
}
}
};
splashTread.start();
}
}
activity_splashscreen below
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:background="#feffc3"
android:layout_gravity="center"
android:id="#+id/lin_lay"
android:gravity="center"
android:orientation="vertical" >
<ImageView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="#+id/splash"
android:background="#drawable/splash_img" />
</LinearLayout>
The problem is that you're setting an id wich don't correspond with the xml file. For example imageView = (ImageView)findViewById(R.id.imageView2); you need to change imageView2 with your xml imageview id wich is "splash". For the pthers error you need to check that files in the drawable folder.
Hope it was helpful
The ImageView in your xml has id splash, so in your code, instead of:
imageView = (ImageView)findViewById(R.id.imageView2);
you should do
imageView = (ImageView)findViewById(R.id.splash);
Also, this line:
int[] ids = new int[]{R.drawable.s_img, R.drawable.s_image_black, R.drawable.s_image_black2};
assumes that in your drawable folder there exist all these drawables:
s_img, s_image_black, s_image_black2
but apparently they don't, so you have to copy or create them and put them in the drawable folder.
I am new to Java and JavaFX, so pardon my newbie questions. I have searched for the past couple of days for examples of what I am trying to do, but have been unable to find any answers.
Here is what I am trying to do: I am trying to create a simple javafx GUI client socket application using scene builder that will connect to a server and send/receive data. Simple enough, but when I try to implement this in Java FX, my GUI freezes. I have researched and found out that the reason is that the socket communications is taking all of the time, and the javafx GUI cannot update. My research has pointed me to using tasks. So, I have created a simple application that creates a task, connects to an internet socket (port 80), sends the command "GET / HTTP/1.1\r\n\r\n" which will request the page and then prints out each line received. The problem is that I want to do this over and over again (every 3 seconds). The task runs successfully once, but then it stops. In the following code, the lines that put the thread to sleep are never reached, but the lines that print any errors are not sent to system.out either.
Here is the controller code
package clientSocketExample;
import java.io.*;
import java.net.*;
import java.util.ResourceBundle;
import javafx.event.ActionEvent;
import javafx.event.EventHandler;
import javafx.fxml.FXML;
import javafx.fxml.Initializable;
import javafx.scene.control.*;
import javafx.concurrent.Task;
/**
* Controller class of the HelloWorld sample.
*/
public class ClientSocketExampleController implements Initializable
{
#FXML
Button button;
private boolean keepRunning = true;
/**
* Initializes the controller class.
*/
#Override
public void initialize(URL url, ResourceBundle rsrcs)
{
if (button != null)
{
button.setOnAction(new EventHandler<ActionEvent>()
{
#Override
public void handle(ActionEvent event)
{
keepRunning = false;
System.out.println("Hello World\n");
}
});
}
// Create a background task to handle the Client-Server socket
// This is needed because JavaFX is not thread safe
Task<Integer> task = new Task<Integer>()
{
#Override
protected Integer call() throws Exception
{
Socket s = new Socket();
// String host = "www.google.com";
// String host = "www.amazon.com";
String host = "www.yahoo.com";
PrintWriter s_out = null;
BufferedReader s_in = null;
int lineNums = 0;
try
{
s.connect(new InetSocketAddress(host, 80));
System.out.println("Connected\n");
// Create writer for socket
s_out = new PrintWriter(s.getOutputStream(), true);
// Create reader for socket
s_in = new BufferedReader(new InputStreamReader(s.getInputStream()));
}
catch (IOException e)
{
// Host not found, so print error
System.err.println("Don't know about host : " + host);
System.exit(1);
}
// Loop forever waiting for task to be cancelled
while (isCancelled() == false)
{
// Send message to server
String message = "GET / HTTP/1.1\r\n\r\n";
s_out.println(message);
System.out.println("Message sent\n");
// Get response from server
try
{
String response;
while ((response = s_in.readLine()) != null)
{
System.out.print("Line #: "+lineNums+" ");
System.out.println(response);
lineNums++;
}
} catch (IOException e)
{
System.err.println("Couldn't get response from host");
}
System.out.println("Thread going to sleep\n\n\n");
Thread.sleep(3000);
System.out.println("Thread waking up from sleep\n\n\n");
} // End while
return lineNums;
}
}; // End Initialize
// start the background task
Thread th = new Thread(task);
th.setDaemon(true);
System.out.println("Starting background task...");
th.start();
}
}`
The Main.java class looks like this:
package clientSocketExample;
import java.util.logging.Level;
import java.util.logging.Logger;
import javafx.application.Application;
import javafx.fxml.FXMLLoader;
import javafx.scene.Scene;
import javafx.scene.layout.AnchorPane;
import javafx.stage.Stage;
public class Main extends Application
{
/**
* #param args the command line arguments
*/
public static void main(String[] args)
{
Application.launch(Main.class, (java.lang.String[]) null);
}
#Override
public void start(Stage primaryStage)
{
try
{
AnchorPane page = (AnchorPane) FXMLLoader.load(Main.class
.getResource("ClientSocketExample.fxml"));
Scene scene = new Scene(page);
primaryStage.setScene(scene);
primaryStage.setTitle("Hello World Sample");
primaryStage.show();
} catch (Exception ex)
{
Logger.getLogger(Main.class.getName()).log(Level.SEVERE, null, ex);
}
}
}`
And finally the FXML file looks like this:
<?xml version="1.0" encoding="UTF-8"?>
<?import java.lang.*?>
<?import java.util.*?>
<?import javafx.scene.control.*?>
<?import javafx.scene.layout.*?>
<?import javafx.scene.paint.*?>
<AnchorPane id="AnchorPane" prefHeight="365.0" prefWidth="378.0" xmlns:fx="http://javafx.com/fxml" fx:controller="clientSocketExample.ClientSocketExampleController">
<children>
<Button fx:id="button" layoutX="147.0" layoutY="28.0" text="Connect" />
<TitledPane animated="false" layoutY="159.0" prefWidth="378.0" text="Received Data">
<content>
<AnchorPane id="Content" minHeight="0.0" minWidth="0.0" prefHeight="180.0" prefWidth="200.0">
<children>
<TextArea fx:id="textAreaField" prefHeight="180.0" prefWidth="374.0" wrapText="true" />
</children>
</AnchorPane>
</content>
</TitledPane>
</children>
</AnchorPane>
Thanks in advance for your help
Wayne
The problem you are getting with the Gui that freezes is because its your "controller" class that connects to the socket. I had the same problem when i was creating my own chat program using JavaFx and JavaFx scene builder.
You can do two things:
Create a new class (SocketConnector()) that connects you to the socket.
Connect to the socket within your main class instead of controller
regardless you cannot connect to a socket within your controller class i am sorry that i am unable to describe details on why you cannot i just know that ive experianced this problem several times and this what the way to fix it!
A couple things need to change with your request:
Insert this into your request
"\r\nHost: <host>\r\nConnection: keep-alive"
This will make sure that the server doesn't close your connection after it responds to your request.
Change your while loop to this:
while (s_in.ready() && (response = s_in.readLine()) != null)
This will make sure there is something to read from the BufferedReader. Check these posts about why the BufferedReader will hang: https://stackoverflow.com/a/7855911/1359765 and https://stackoverflow.com/a/15510821/1359765