I am working on an Android app that will receive multicast packets from a network that already outputs reliable multicast data on 239.255.x.x . I have verified that my device can receive multicast with another application. I'm new to Java and Android but I did confirm that my original code to gather the Multicast info worked in a java application and have been struggling to get everything working in the Android side of things. I have permissions set in the manifest,
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE"/>
<uses-permission android:name="android.permission.CHANGE_WIFI_MULTICAST_STATE"/>
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/>
<uses-permission android:name="android.permission.INTERNET"/>
the networking portion of code runs in an Asynctask as to not crash the app but my Multicast.receive() calls all result in a time out.Is there something else I am missing or something that prevents multicast sockets from working in the asynctask class?
public class MainActivity extends AppCompatActivity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
final Button button = findViewById(R.id.button);
button.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
new getACN.execute();
}
});
}
public class getACN extends AsyncTask<Void, Void, String> {
#Override
public String doInBackground(Void... Void) {
byte[] buf = new byte[1000];
try {
WifiManager wifiManager = (WifiManager) getApplicationContext().getSystemService(Context.WIFI_SERVICE);
MulticastLock multicastLock = wifiManager.createMulticastLock("sACN");
multicastLock.acquire();
InetAddress group = InetAddress.getByName("239.255.0.3");
DatagramPacket recv = new DatagramPacket(buf,buf.length);
MulticastSocket sock = new MulticastSocket(5568);
sock.joinGroup(group);
sock.setSoTimeout(1000);
sock.receive(recv);
sock.leaveGroup(group);
} catch (IOException e) {
return e.getMessage();
} catch (SecurityException e) {
return e.getMessage();
}
return Arrays.toString(buf);
}
#Override
protected void onPostExecute(String result){
TextView textView = (TextView) findViewById(R.id.text01);
textView.setText(result);
}
}
}
Related
I'm trying to work with a socket output stream. I want to launch it from inside a broad cast receiver.... I believe the socket is working since the client is always receiving a null value.... But the broadcast listener seems to not be working. I seem it's not even registering as even a simple Toast inside it is not working.
I tried to use a broadcast receiver class and registered it via the Manifest. I worked but I don't want that since :
broadcast registered via manifest stay alive even after shuting down the application
I need to use some Main UI class variable/methods/inner class (here for now, that class is ServerReplyThread). Therefore a separate class for the broadcast receiver isn't going to help me much...
Below is my code ; can you help me fix that ?
public class MainActivity extends AppCompatActivity {
public ServerSocket serverSocket;
public ServerSocket getServerSocket() {
return serverSocket;
}
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
btnDemarrer.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
Thread socketServerThread = new Thread(new SocketServerThread());
socketServerThread.start();
}
});
}
#Override
public void onResume() {
super.onResume();
IntentFilter filter = new IntentFilter("android.provider.Telephony.SMS_RECEIVED");
MainActivity.this.registerReceiver(smsReceived, filter);
sendBroadcast(new Intent("android.provider.Telephony.SMS_RECEIVED"));
}
#Override
public void onPause() {
MainActivity.this.unregisterReceiver(smsReceived);
super.onPause();
}
private class SocketServerThread extends Thread {
static final int SocketServerPORT = 7777;
#Override
public void run() {
try {
serverSocket = new ServerSocket(SocketServerPORT);
while (true) {
Socket socket = serverSocket.accept();
SocketServerReceiveThread socketServerReplyThread
= new SocketServerReceiveThread(socket);
socketServerReplyThread.run();
}
} catch (IOException e) {
e.printStackTrace();
}}}
private class SocketServerReceiveThread extends Thread {
private Socket hostThreadSocket;
SocketServerReceiveThread(Socket socket) {
hostThreadSocket = socket;
}
#Override
public void run() {
try{
InputStream is = hostThreadSocket.getInputStream();
ObjectInputStream ois = new ObjectInputStream(is);
//Launch USSD query
}catch(Exception e){
e.printStackTrace();
}}}
private class SocketServerReplyThread extends Thread {
private Socket hostThreadSocket;
private String sms;
SocketServerReplyThread(Socket socket, String sms) {
hostThreadSocket = socket;
this.sms = sms;
}
#Override
public void run() {
try{
OutputStream os = hostThreadSocket.getOutputStream();
ObjectOutputStream oos = new ObjectOutputStream(os);
MyClass myclass = new MyClass();
myclass.setSms(sms);
oos.writeObject(dt2);
hostThreadSocket.close();
}catch(Exception e){
e.printStackTrace();
}}}
BroadcastReceiver smsReceived = new BroadcastReceiver() {
#Override
public void onReceive(Context context, Intent intent) {
if (intent.getAction().
equals("android.provider.Telephony.SMS_RECEIVED")) {
StringBuilder sb = new StringBuilder();
Bundle bundle = intent.getExtras();
if (bundle != null) {
Object[] pdus = (Object[])
bundle.get("pdus");
for (Object pdu : pdus) {
SmsMessage smsMessage =
SmsMessage.createFromPdu
((byte[]) pdu);
sb.append("body - " + smsMessage.
getDisplayMessageBody());
}
Toast.makeText(context,sb.toString(),Toast.LENGTH_LONG); //This is not popping up
try {
Socket socket = getServerSocket().accept();
SocketServerReplyThread socketServerReplyThread = new SocketServerReplyThread(socket,sb.toString());
socketServerReplyThread.run();
} catch (IOException e) {
e.printStackTrace();
}}}}};
}
Below are the permissions of my Manifest
<!-- TELEPHONY SETTINGS-->
<uses-feature
android:name="android.hardware.telephony"
android:required="true" />
<!-- Permission needed to read TelephoneManager data -->
<uses-permission android:name="android.permission.READ_PHONE_STATE" />
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
<!-- END -->
<!-- Permissions to dial -->
<uses-permission android:name="android.permission.CALL_PHONE" />
<uses-permission android:name="android.permission.PROCESS_OUTGOING_CALLS" />
<uses-permission android:name="android.permission.CALL_PRIVILEGED" />
<uses-permission android:name="android.permission.MODIFY_PHONE_STATE" />
<!-- END -->
<!-- SMS permissions -->
<uses-permission android:name="android.permission.RECEIVE_SMS" />
<uses-permission android:name="android.permission.READ_SMS" />
<uses-permission android:name="android.permission.WRITE_SMS" />
<uses-permission android:name="android.permission.SEND_SMS" />
<!-- END -->
<!-- END OF TELEPHONY SETTINGS-->
When the SMS came your app is in foreground/visible to user ? If not in foreground/visible you want receive it as you are unregistering receiver in onPause(). If you like to receive it always define receiver in the AndroidMainfes.xml file.
You can register/unregister in onStart() and onStop() of activity life cycle
I wrote a simple HTTP-Proxy for Android which is listening on the device external IP Address and a specific port (e.g. 192.168.1.20:8080).
I can access IP/port from the device itself - but any tries from external devices will never be accepted in the run-loop.
The simplified code looks like this:
public class MainActivity extends AppCompatActivity implements Runnable {
private ServerSocket socket;
private int port = 8080;
private Thread thread;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
WifiManager wm = (WifiManager) getSystemService(Context.WIFI_SERVICE);
String ip = Formatter.formatIpAddress(wm.getConnectionInfo().getIpAddress());
Log.v("TAG", "http://"+ip+":"+port);
try {
Log.v("TAG", InetAddress.getByName(ip).toString());
socket = new ServerSocket(port, 5, InetAddress.getByName(ip));
socket.setSoTimeout(5000);
thread = new Thread(this);
thread.start();
} catch (Exception e) {
e.printStackTrace();
}
}
#Override
public void run() {
while (true) {
try {
Socket client = socket.accept();
// Never reaches this line if connected externally
Log.d("TAG", "client connected");
} catch (SocketTimeoutException e) {
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
I also added the permissions in AndroidManifest.xml:
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
<uses-permission android:name="android.permission.INTERNET" />
But still no luck. Anybody out there who can give advise?
Thx.
public class MainActivity extends AppCompatActivity {
private static final String API_KEY = "b8fo0q33XyuCTm0qbr6XCg";
static final HttpTransport HTTP_TRANSPORT = new NetHttpTransport();
static final JsonFactory JSON_FACTORY = new JacksonFactory();
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Button myBtn = (Button) findViewById(R.id.button);
TextView t=(TextView) findViewById(R.id.text);
}
public void onClick(View v) {
try {
CSApi api = new CSApi(
HTTP_TRANSPORT,
JSON_FACTORY,
API_KEY
);
CSPostConfig imageToPost = CSPostConfig.newBuilder()
.withRemoteImageUrl("https://questions4thoughts.files.wordpress.com/2008/11/50rupees.png")
.build();
CSPostResult portResult = api.postImage(imageToPost);
System.out.println("Post result: " + portResult);
try{
Thread.sleep(30000);
CSGetResult scoredResult = api.getImage(portResult);
// t.setText(scoredResult);
}
catch (InterruptedException e){
e.getCause();
}
}
catch (IOException e)
{
e.printStackTrace();
}
}
}
i am new to this api. i have post and get files also i dont know how to use it. when i am running the app it says unfortunately stop. i have used cloudsight api but there no source for using it. Can u suggest some solution on how to use it or some other free api for image recognition.
Did you try giving internet permission above the application tag in Manifest.xml?
if not, add the following line :
<uses-permission android:name="android.permission.INTERNET" />
i've the same issue, few time ago. And i did it :
new Thread() {
#Override
public void run() {
//your code here
}
}.start();
it works perfect, so i share it to you. but for the first time you will received status "not completed", because cloudsight needs 6-12 second until complete. so try to run the thread until you get status complete. Hope you success. :)
I'm playing a little bit with multicast sockets. I write a server which sends a message to a android client. Until yet the client should only log the received message.
I noticed that no multicast packet are received on my device.
Here is the code for the server (runs on the pc):
public class MulticastServer{
private int port;
private boolean running = false;
private MulticastSocket serverSocket;
private InetAddress group;
private String multicastAddress = "230.192.0.11";
public MulticastServer(int port) {
super();
this.port = port;
init();
}
public MusicStreamerServer() {
this(5500);
}
private void init() {
try {
group = InetAddress.getByName(multicastAddress);
serverSocket = new MulticastSocket(port);
serverSocket.joinGroup(group);
} catch (IOException e) {
e.printStackTrace();
}
}
public void start() throws IOException {
System.out.println("server started");
if (running)
return;
running = true;
new Thread(new Runnable() {
#Override
public void run() {
byte[] buf = new byte[1024];
DatagramPacket packet = new DatagramPacket(buf, buf.length,
group, port);
String msg = "msg";
while (running) {
packet.setData(msg.getBytes(), 0, msg.length());
try {
serverSocket.send(packet);
} catch (IOException e) {
e.printStackTrace();
}
}
}
}).start();
}
public void stop() throws IOException {
running = false;
} }
Here is the code for the android client:
public class MainActivity extends Activity {
private MulticastSocket socket;
private InetAddress group;
private String multicastAddress = "230.192.0.11";
private int port = 5500;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
init();
}
private void init() {
StrictMode.ThreadPolicy policy = new StrictMode.ThreadPolicy.Builder()
.permitAll().build();
StrictMode.setThreadPolicy(policy);
try {
group = InetAddress.getByName(multicastAddress);
socket = new MulticastSocket(port);
socket.joinGroup(group);
socket.setBroadcast(true);
} catch (IOException e) {
e.printStackTrace();
Log.wtf("init", e.getMessage());
}
new Thread(new Runnable() {
#Override
public void run() {
WifiManager wm = (WifiManager) getSystemService(Context.WIFI_SERVICE);
WifiManager.MulticastLock multicastLock = wm
.createMulticastLock("mylock");
multicastLock.acquire();
byte[] buf = new byte[1024];
while (true) {
try {
socket.receive(packet);
Log.d("receiver","received = " + (new String(packet.getData())));
} catch (IOException e) {
e.printStackTrace();
}
}
}
}).start();
}
#Override
public boolean onCreateOptionsMenu(Menu menu) {
getMenuInflater().inflate(R.menu.main, menu);
return true;
}}
I've tested the code with 2 different devices. The Nexus4 and the Nexus7 (2013) both running the latest Android.
Could anybody help me?
Thanks
I've seen that the issue is really inconsistent.
Android version: 4.2.x
On Samsung S4 active:
Multicast is working as expected.
On Samsung Note 10.1 and Nexus 4.2.3
Multicast is not working as expected.
239.x.x.x is not supported (and sadly it's the one used to multicast television...)
224.0.0.251 is working as expected.
I think they have a bug with the mask.
A multicast address is normally
|1 1 1 0| MULTICAST Address | 224.0.0.0 - 239.255.255.255
11100000.00000000.00000000.00000001 = 224.0.0.1
11101111.00000000.00000000.00000001 = 239.0.0.1
So the mask should be 224.0.0.0/4 and not 224.0.0.0/8
Does your manifest request the proper permissions?
<uses-permission android:name="android.permission.CHANGE_WIFI_MULTICAST_STATE" />
Also, you may want to play with the Advanced settings in the WiFi menu on your phone, both Wi-Fi optimizations and Keep Wi-Fi on during sleep may impact your ability to do multicasts.
I have a problem on android. I have an application that asks the user for the local Ip address (from the device's interface) and another remote address. The application has to bind to the specified local address and connect to the remote address. Quite simple, but, indeed, bind does not work ass i expected..
I added the following permissions on the manifest file:
<uses-permission android:name="android.permission.INTERNET"/>
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/>
The source code is the following one:
public class MainActivity extends Activity
{
String Tag = "TAG";
private int LOCAL_PORT = 4444;
private int REMOTE_PORT = 80;
private EditText LOCAL;
private EditText REMOTE;
private Button Connect;
private TextView STATUS;
private Context context = this;
#Override
public void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
LOCAL = (EditText) findViewById(R.id.editText1);
REMOTE = (EditText) findViewById(R.id.editText2);
Connect = (Button) findViewById(R.id.button1);
Connect.setOnClickListener(new View.OnClickListener() {
public void onClick(View v)
{
BotleneckHandle WORK;
Toast.makeText(getApplicationContext(), "Proceeding to connect",
Toast.LENGTH_SHORT).show();
/*
if(LOCAL.getText().toString() == null || REMOTE.getText().toString() == null || LOCAL.getText().toString().equals(" ") || REMOTE.getText().toString().equals(" ") || LOCAL.getText().toString().equals("") || REMOTE.getText().toString().equals(""))
Toast.makeText(context, "Wrong parameters", 2000);
else
{
Toast.makeText(getApplicationContext(), "Proceeding to connect",Toast.LENGTH_SHORT).show();
}*/
WORK = new BotleneckHandle();
WORK.execute();
}
});
STATUS = (TextView) findViewById(R.id.textView1);
}
private class BotleneckHandle extends AsyncTask <Void , Void , String>
{
Socket Skt = null;
String ReturnStatemente = new String();
SocketAddress localAddr = new InetSocketAddress(LOCAL.getText().toString(), LOCAL_PORT);
protected void onPreExecute(){ }
protected String doInBackground(Void... params)
{
try
{
String s=new String();
s+= "Local="+LOCAL.getText().toString()+":"+LOCAL_PORT+" Remote="+REMOTE.getText().toString()+":"+REMOTE_PORT; //so far so good, Confirmed by debug
Toast.makeText(getApplicationContext(), s,Toast.LENGTH_SHORT).show(); //Does not show anything due the fact that i didn't published it as an assync task update..
//binding to a local address
Skt.bind(localAddr); //cannot make the bind :-/
//connecting to remote host
Skt=new Socket(REMOTE.getText().toString(), REMOTE_PORT); //if bind is comment, still does not work.. I bet
ReturnStatemente = "Connected";
}
catch (UnknownHostException e)
{
e.printStackTrace();
Toast.makeText(context, "Unknown remote host", 2000);
ReturnStatemente = "Not Connected";
}
catch (IOException e)
{
e.printStackTrace();
Toast.makeText(context, "Connection fail", 2000);
ReturnStatemente = "Not Connected";
}
finally{try {
Skt.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}}
return ReturnStatemente;
}
protected void onPostExecute(String result) { STATUS.setText(" CONECTION STATUS == " + result); }
}
}
What am i doing wrong on bind? As far as i see, and as i searched for its good.. Did i miss something?
kind regards
You're trying to call bind on a variable before you assigned anything to it. So its still null. That isn't going to work. You need to create an instance of Socket before you can call methods on it.