I am trying to create a Java Client-Server Program, where the Server is running on a Windows PC, and the Client is running on an Android 2.2 Phone.
The Connection is okay. Sending Data from the Phone to the PC works also fine.
Just receiving Data on the Phone crashes the program.
I am using DataInputStream and DataOutputStream to read/write through the Socket.
//Thread on the Phone
public void run() {
while (RUN) {
if (socket != null && socket.isConnected()) {
try {
//Crash
String text = dis.readUTF();
myTextView.setText(text);
} catch (IOException ex) {
//ErrorHandling
}
}
}
}
I want to receive a String from the server and then show it in a TextView.
Any Ideas? I am already setting this permission:
<uses-permission android:name="android.permission.INTERNET" />
do i need any other permissions? Thanks.
you can't set text on your UI if you're not in the UI thread.
do this...
add:
Runnable showmessage = new Runnable() {
public void run() {
myTextView.setText(membervariabletext);
}
};
and from your thread, after the readUTF(), call "runOnUiThread(showmessage);"
I would ensure that your Data Input Stream is initiated correctly:
Socket s = new Socket(serverAddress, port);
DataInputStream dis = new DataInputStream(s.getInputStream());
Otherwise, here's a link for example code where someone uses InputStreamReader() and OutputStreamWriter() to make a server and client for Android.
https://thinkandroid.wordpress.com/2010/03/27/incorporating-socket-programming-into-your-applications/
Related
I am trying to create a Java Android application to print with a Bluetooth printer (Start sm 300 ti).
The code looks something like:
Thread t = new Thread() {
#RequiresApi(api = Build.VERSION_CODES.O)
public void run() {
OutputStream os = bluetoothSocket.getOutputStream();
os.write(something1);
os.write(something1);
....
//close os
os.close();
....
}
The problem is that I need to know when OutputStream finished the print(os.write function ) job, because some data don't arrive at the Bluetooth Printer (for example, if I print a bitmap image)
Currently, I added a sleep function before os.close().
So i got my ESP32 and wanted to do some Porjects and I want to control them with an Android App, for example LED Stripes. I already did this with my Raspberry Pi where it runs perfectly.
I already tried some codes and it could connect to the Wifi. And my PC and even Raspberry Pi could connect to it but when i tried with my Smartphone i just didn't worked.
Here' my Android Code:
mainActivity.jre
connectButton.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
if (!IPAddress.getText().equals("") || IPAddress.getText() != null || !portNumber.getText().equals("") || portNumber.getText() != null){
return;
}
IPaddresse= IPAddress.getText().toString();
port=Integer.parseInt(portNumber.getText().toString());
try {
client = new Socket(IPaddresse,port);
pw = new PrintWriter(client.getOutputStream());
dataOutputStream= new DataOutputStream(client.getOutputStream());
msg.setText("Verbunden!");
} catch (UnknownHostException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
});
Permissions:
<uses-permission android:name="android.permission.INTERNET"></uses-permission>
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE"></uses-permission>
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"></uses-permission>
ESP32 Code:
#include <WiFi.h>
const char* ssid="Name";
const char* password="password";
WiFiServer server(80 );
void setup() {
Serial.begin(115200);
Serial.println("start");
delay(1000);
WiFi.begin(ssid, password);
while (WiFi.status() != WL_CONNECTED) {
delay(1000);
Serial.println("Connecting to WiFi..");
}
Serial.println("Connected to the WiFi network");
Serial.println(WiFi.localIP());
server.begin();
}
void loop() {
WiFiClient client = server.available();
if (client) {
while (client.connected()) {
while (client.available()>0) {
char c = client.read();
client.write(c);
}
Serial.println(client.localIP());
delay(10);
}
}
}
Sorry for my English. And my Code isn't the best im just beginning to Code
Thanks
First on the ESP32 i suggest you add mDNS to your setup, this allows you to give your esp a name on the network like when you give your esp the name pietje then you can find it as pietje.local on your network.
This seems not to work properly with the socket class, but maybe i did something work. It did not finding the ip of it. It was the first time working with sockets. So i learned something new.
I tried your example and it did fault me to. With some short search i found this website:
https://www.tutorialspoint.com/sending-and-receiving-data-with-sockets-in-android
By adding you socket creation inside a thread it did work for me.
I hope this helps you ahead.
I have a simple web service in c#.
Here is the C# code :
IService1.cs
[ServiceContract(ConfigurationName = "IService")]
public interface IService1
{
[OperationContract]
[WebGet]
string TestAndroid();
}
Service1.svc.cs
public class Service1 : IService1
{
public string TestAndroid()
{
return "Test done !";
}
}
Here is the Android code :
protected Boolean doInBackground(String... urls) {
try {
URL url = new URL("http://10.0.2.2:49363/Service1.svc/TestAndroid");
InputStream in = new BufferedInputStream(httpURLConnection.getInputStream());
BufferedReader reader = new BufferedReader(new InputStreamReader(urlConnection.getInputStream()));
String line = reader.readLine();
reader.close();
} catch(Exception e){
return false;
}
return null;
}
When I want to read the InputStream, I have an error.
It's
java.io.FileNotFoundException:
http://10.0.2.2:49363/Service1.svc/TestAndroid
I don't know where is the problem, because when I go in browser I have
<string xmlns="http://schemas.microsoft.com/2003/10/Serialization/">Test done !</string>
Can someone help me ?
I hope your service is working and you had tested it on your computer by invoking url http://10.0.2.2:49363/Service1.svc/TestAndroid
Am I right?
Then simple explanation for your issue would be that your Android doesn't know about ip address 10.0.2.2.
Can you validate that is accessible? Just try to open the same url in browser on your Android device.
Simple solution to see this IP address - your phone should be on the same WiFi as your computer.
Update:
Goal is to see computer with service running WCF host. Question is - can Android device see WCF host?
The opposite direction is irrelevant but it's good to know that
Android emulator cannot be seen from the computer. Here is good explanation
I'm writing a bluetooth HID server for a small and very simple bluetooth remote. I'm following the documentation here.
My application's permission include:
<uses-permission android:name="android.permission.BLUETOOTH"/>
<uses-permission android:name="android.permission.BLUETOOTH_ADMIN"/>
And this is my BluetoothServerSocket reading connection-accepting thread:
private class AcceptThread extends Thread {
public void run() {
BluetoothSocket socket = null;
while(true) {
try {
socket = MyBluetoothServerSocket.accept(); // problematic line
} catch(IOException e) {
Log.i(BLUETOOTH_SERVICE, e.toString());
break;
}
if(socket != null) {
readInput(socket);
try {
MyBluetoothServerSocket.close();
} catch (IOException e) {
Log.i(BLUETOOTH_SERVICE, e.toString());
}
} else {
Log.i(BLUETOOTH_SERVICE, "Could not accept a connection from the socket.\n");
}
break;
}
}
}
MyBluetoothServerSocket is a socket constructed like this:
MyBluetoothAdapter.listenUsingRfcommWithServiceRecord("MyService", UUID.fromString("00001124-0000-1000-8000-00805f9b34fb"));
The UUID I'm using above is the only one my remote control device reports through the following method:
MyBluetoothDevice.getUuids();
And MyBluetoothAdapter is just the default adapter:
BluetoothAdapter.getDefaultAdapter();
The rest of the code involved is minimal (making sure bluetooth is on, selecting the correct device) and working correctly. The remote is bonded to the phone.
The line marked as problematic in the code above (accept()) never returns i.e. it blocks forever. What am I doing wrong?
edit: I've tried MyBluetoothAdapter.listenUsingInsecureRfcommWithServiceRecord without success.
HID is based on the L2CAP bluetooth profile (protocol?), which is not implemented (line 107) in Android as of October 2013.
This makes it currently impossible to connect to a HID device.
I'm kind of new in this kind of development. To be short I'm working on a android app which sends a string to the cloud (I have a virtual server machine on Amazon), everything works well sending the string from my phone to the server machine, I print the string I'm sending and it works!. But when getting the response back from the server to my android app (I'm running it on my android phone) I don't get anything (The response should be a string + another string concatenated), that's it, easy right? But unfortunately I can't receive it back. I tested the server side and It's working properly (The amazon EC2). I'm not really sure if I can do what Im doing which is:
CREATING ransmission code to send the String by using a SOCKET TO SEND DATA TO THE CLOUD ON THE doInBackground() method from the AsyncTask class.
In the same method doInBackground I do the code to receive the response back by using a ServerSocket to receive the response back from the cloud. Is it possible or do I need another thread or something like that?
Here is my code:
`import android.os.Bundle;
import android.app.Activity;
import android.widget.TextView;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.net.*;
import android.os.AsyncTask;
import android.view.View;
public class ReadWebpageAsyncTask extends Activity {
private TextView textView;
/** Called when the activity is first created. */
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
textView = (TextView) findViewById(R.id.TextView01);
}
private class DownloadWebPageTask extends AsyncTask<String, Void, String> {
#Override
protected String doInBackground(String... urls)
{
String response = "";
//Transmission
try
{
Socket socket = new Socket("MyAmazonServerIp", 5678);
DataOutputStream salida = new DataOutputStream (socket.getOutputStream());
salida.writeUTF("Llego Perfectamente");
socket.close();
salida.close();
}
catch (Exception e)
{
e.printStackTrace();
}
//Final ends
// Reception
boolean ak=true;
try
{
ServerSocket ServerSock = new ServerSocket(7896);
while(ak)
{
Socket cl=ServerSock.accept();
InetAddress ipC = cl.getInetAddress();
DataInputStream en= new DataInputStream(cl.getInputStream());
response= en.readUTF();
//response= response.toString();
ak=false;
}
}
catch(Exception exp)
{
exp.printStackTrace();
}
// Reception ends
return response;
} //doInBackground ends
#Override
protected void onPostExecute(String result)
{
textView.setText(result);
}
}
public void readWebpage(View view) {
DownloadWebPageTask task = new DownloadWebPageTask();
task.execute(new String[] { "????" });
}
}`
I will really appreciate any help since I've been working on this for days and I have not been able to solve it.
Thanks,
The way you are doing it can not work over a 3G or likely even a WiFi connection. It can't work over 3G because the address your Amazon server sees is the address of the proxy/firewall on your cell provider's network. No external application can open a socket directly to your phone. Instead you need to send the response back over the same socket the phone created to send the initial message.
Over WiFi, it will not work because of the NAT translation likely going on with your WiFi firewall.
This is done for many reasons, not the least of which is data usage and security. Specifically, think about if your phone was publicly addressable to the entire Internet? It would constantly be getting hit with attempts to hack it.
So basically, just keep the original socket open and listen for a response on that socket and on your cloud server just send the response back over teh same socket you receive the request on.