I want to create a TCP socket when a button is pressed in my first activity and then access that same socket object from any activity (not sure that closing and opening a socket in each activity is a good idea).
I tried quite a few methods having my mind set on a Singleton instance being the best solution to access an object though any activity, my problem is since this is a TCP socket I don't see AsyncTask as the smart idea (can only execute once, defies my point of having one instance of an object) and I don't see how I combine a regular Thread with a singleton.
Singleton code:
public class TCPSingleton extends Application {
private static TCPSingleton singleInstance;
String HostIP;
int tcp_port;
Socket clientSocket;
DataOutputStream outToServer;
public static TCPSingleton getInstance() {
return singleInstance;
}
#Override
public void onCreate() {
super.onCreate();
singleInstance = this;
singleInstance.initializeInstance();
}
protected void initializeInstance() {
this.HostIP = "10.0.0.6";
this.tcp_port = 9871;
try {
this.clientSocket = new Socket(this.HostIP, this.tcp_port);
this.outToServer = new DataOutputStream(clientSocket.getOutputStream());
} catch (UnknownHostException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
public void send_data(String data){
try {
this.outToServer.writeBytes(data);
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
How do I merge a thread here (or what's the better idea other than singleton to do this).
Related
I have a fragment that contains a Button btn_connect that when it is pressed a WiFi Direct connection is established between 2 devices. This fragment implements ConnectionInfoListener. So it has onConnectionInfoAvailable function where I want to execute an AsyncTask class. The problem that I have is that in one Activity, I am doing:
fragment.mContentView.findViewById(R.id.btn_connect).performClick();
And the button is being clicked and the connection is established so the code goes into the onConnectionInfoAvailable function but the AsyncTask is not being executed.
#Override
public void onConnectionInfoAvailable(final WifiP2pInfo info) {
//..code..
Log.d("Test 1", "Test 1");
new MasterServerTask().execute();
}
public class MasterServerTask extends AsyncTask<Void, Void, Void> {
#Override
protected Void doInBackground(Void... arg0) {
//**************
Log.d("IM INSIDE ASYNCTASK CLASS", "SOCKET");
try {
serverSocket = new ServerSocket(8090);
} catch (IOException e) {
e.printStackTrace();
}
while (true) {//wait for clients
Socket socket = null;
try {
socket = serverSocket.accept();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
Log.d("ACCEPTED A SLAVE DEVICE "+num_clients, "ACCEPTED A SLAVE DEVICE "+num_clients);
num_clients++;
OutputStream os=null;
try {
os = socket.getOutputStream();
} catch (IOException e) {
e.printStackTrace();
}
proxy.addSlaveOutputStream(os);
}
}
#Override
protected void onPostExecute(Void result) {
super.onPostExecute(result);
}
}
mContentView.findViewById(R.id.btn_connect).setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {//Phone that connects first is NOT the group owner
// port = Integer.parseInt(editTextPort.getText().toString());
Log.d("IM IN THE OTHER FRAGMENT", "Connect");
WifiP2pConfig config = new WifiP2pConfig();
config.groupOwnerIntent = 0;
config.deviceAddress = device.deviceAddress;
config.wps.setup = WpsInfo.PBC;
if (progressDialog != null && progressDialog.isShowing()) {
progressDialog.dismiss();
}
progressDialog = ProgressDialog.show(getActivity(), "Press back to cancel",
"Connecting to :" + device.deviceAddress, true, true
);
((DeviceActionListener) getActivity()).connect(config);
}
});
Is there an easy workaround solution for this?
Check how/where you are calling WifiP2pManager.initialize() to create the WifiP2pManager.Channel object. The Looper you provide it is the one which will receive all callbacks for your instance of WifiP2pManager.ConnectionInfoListener. If you are giving it a background thread then the AsyncTask will not execute - it must be started from the main (UI) thread.
The comments on the question were really helpful. The reason why the AsyncTask was not getting executed is because it was called from another task that is currently being executed. So in order for it to work, I replaced the AsyncTask with Thread classes. All the code in the doInBackground() was placed inside the thread's run() function. Now the performClick() executes a Thread, not an AsyncTask and it worked.
I am new to android and I am building an app that I want to authenticate using the local users google account. Unfortunately I have gotten myself in a bit of a bind looking at Auth 2.0 and logging in via the google services.
What is the recommended route to authenticate (and hopefully not require typing a login name)? I tried many of the samples that I saw but much of it seems deprecated.
Any example code would be very helpful as well.
I was using this tutorial but it is a bit outdated and I believe that it is much simplier now.
http://blog.notdot.net/2010/05/Authenticating-against-App-Engine-from-an-Android-app
Thanks,
Craig
Here is how I solved it. Don't know if it is the recommended approach but it works...
in OnCreate of my entry activity (main) I put...
AccountManager accountManager = AccountManager.get(this);
Account[] accounts = accountManager.getAccountsByType("com.google");
AccountManagerFuture<Bundle> futur;
futur = accountManager.getAuthToken(accounts[0],AUTH_TOKEN_TYPE_USERINFO_PROFILE, null, null,
new OnTokenAcquired(), new Handler(new OnError()));
In that same activity I created...
private class OnTokenAcquired implements AccountManagerCallback<Bundle> {
#Override
public void run(AccountManagerFuture<Bundle> result) {
// Get the result of the operation from the AccountManagerFuture.
Bundle bundle;
try {
bundle = result.getResult();
// The token is a named value in the bundle. The name of the
// value
// is stored in the constant AccountManager.KEY_AUTHTOKEN.
String token = bundle.getString(AccountManager.KEY_AUTHTOKEN);
//If token isn't null then let them in and also make sure Crunchy accounts are created
if(token!=null){
ProcessToken pt = new ProcessToken(token);
pt.execute("");
}
Intent launch = (Intent) bundle.get(AccountManager.KEY_INTENT);
if (launch != null) {
startActivityForResult(launch, 0);
return;
}
}catch (OperationCanceledException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (AuthenticatorException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
I also created an asyncTask to process the token (because I do a bit more logic to setup account and set a cookie). It looks like this (much of my processing/cookie logic is not completed yet)
package com.craig.activities.login;
import java.io.IOException;
import java.net.HttpURLConnection;
import java.net.MalformedURLException;
import java.net.URL;
import android.os.AsyncTask;
import android.util.Log;
public class ProcessToken extends AsyncTask<String,Integer,Long>{
private static final String AUTH_ACCESS_TOKEN_URL = "https://www.googleapis.com/oauth2/v1/userinfo?access_token=";
private static final String DEBUG_TAG = "OnTokenAcquired.class";
private static String token="";
public ProcessToken(String tokenValue){
token=tokenValue;
}
#Override
protected Long doInBackground(String... params) {
try {
URL url = new URL(AUTH_ACCESS_TOKEN_URL+token);
HttpURLConnection con = (HttpURLConnection) url.openConnection();
int serverCode= con.getResponseCode();
if(serverCode==200){
Log.i(DEBUG_TAG, "code 200!!!");
//PUT MY LOGIC IN HERE....
}
else{
Log.i(DEBUG_TAG, "Oops, We had an error on authentication");
}
} catch (MalformedURLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return null;
}
}
Not sure if this is the best but it seems to be working for me....
I am trying to read in data from an input stream, but if the program does not receive data for X amount of time, I would like to terminate the attempt and return a -1. I was previously using Thread.sleep( X ) but then realized that thats a completely incorrect approach. If anyone has any ideas please let me know. Here is my code for reading from the input stream...
try {
// Read from the InputStream
bytes = mmInStream.read(buffer, 0, length);
// Send the obtained bytes to the UI Activity
mHandler.obtainMessage(MainMenu.MESSAGE_READ, bytes, -1, buffer)
.sendToTarget();
} catch (IOException e) {
Log.e(TAG, "disconnected", e);
connectionLost();
// Start the service over to restart listening mode
BluetoothService.this.start();
//break;
}
You can use Future to do this.
First, you need a class which will be returned as "future" value:
public class ReadResult {
public final int size;
public final byte[] buffer;
public ReadResult(int size, byte[] buffer) {
this.size = size;
this.buffer = buffer;
}
}
Then you need to use executor service and use get(long timeout, TimeUnit unit) like this:
ExecutorService service = Executors.newSingleThreadExecutor();
Future<ReadResult> future = service.submit(new Callable<ReadResult>() {
#Override
public ReadResult call() throws Exception {
bytes = mInStream.read(buffer, 0, length);
return new ReadResult(bytes, buffer);
}
});
ReadResult result = null;
try {
result = future.get(10, TimeUnit.SECONDS);
} catch (InterruptedException e1) {
// Thread was interrupted
e1.printStackTrace();
} catch (ExecutionException e1) {
// Something bad happened during reading
e1.printStackTrace();
} catch (TimeoutException e1) {
// read timeout
e1.printStackTrace();
}
if (result != null) {
// here you can use it
}
In that way you will be able to achieve your goal. Plz note that its better to subclass Callable class which will accept inputstream as constructor argument then using class variables.
You could start a new Thread and in there wait for x amount of time. Pass a reference to your activity and once the time is over, you can call a method in your activity from the Time Thread.
eg.
Thread time = new Thread() {
Activity foo;
public addActivity(Activity foo) {
this.foo = foo;
}
public void run() {
Thread.sleep(x);
// Once done call method in activity
foo.theTimeHasCome();
}
}.start();
I hope this helps!
im trying to implement a tcp socket connection between an android app (as server) and a java based client running on windows. (short version below, without code)
Im using some sensor listener to implement a game movement (everybody knows this sensor based movement of racing games.
Ive implemented a service for that purpose, which is started out of the first activity. This service is implemented as follows (im just pasting the relevant code snippets, not the whole class):
public class ServerService extends Service {
ConnectionHandler conHandler;
#Override
public void onCreate() {
startListener();
}
private void startListener() {
conHandler = new ConnectionHandler(this);
conHandler.execute();
}
private void sendMessage(String s)
{
conHandler.write(s);
}
public void messageNotify(String s) {
//Log.d("receivedMessage", s);
}
}
The ConnectionHandler class:
public class ConnectionHandler extends AsyncTask<Void, Void, Void>{
public static int serverport = 11111;
ServerSocket s;
Socket c;
ConnectionListening conListening;
ConnectionWriting conWriting;
DataOutputStream dos;
DataInputStream dis;
ServerService server;
public ConnectionHandler(ServerService server)
{
this.server = server;
}
#Override
protected Void doInBackground(Void... params) {
try {
Log.i("AsyncTank", "doInBackgoung: Creating Socket");
s = new ServerSocket(serverport);
} catch (Exception e) {
Log.i("AsyncTank", "doInBackgoung: Cannot create Socket");
}
try {
//this is blocking until client connects
c = s.accept();
Log.d("ConnectionHandler", "client connected");
dis = new DataInputStream(c.getInputStream());
dos = new DataOutputStream(c.getOutputStream());
} catch (IOException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
}
conWriting = new ConnectionWriting(this.c, this.dos);
conWriting.execute();
conListening = new ConnectionListening(this.c, this.dis, this.server);
if(this.c != null)
{
Timer timer = new Timer();
timer.schedule(conListening, 0, 10);
}
Log.i("AsyncTank", "doInBackgoung: Socket created, Streams assigned");
return null;
}
public void write(String s)
{
conWriting.writeToStream(s);
}
public void messageNotify(String s) {
// TODO method stub
}
}
The ConnectionHandler ist implemented as AsyncTask similarly to the ConnectionWriting, so that the blocking of tcp methods doenst affect the whole communication.
The client is able to send messages to the server to. Because i dont know when this messages will arrive, im using a TimerTask which is executed every 10ms, to check if there is a new message.
ConnectionWriting looks as follows:
public class ConnectionWriting extends AsyncTask<Context, Void, Boolean>{
public DataOutputStream dos;
Socket c;
public ConnectionWriting(Socket c, DataOutputStream dos) {
this.dos = dos;
this.c = c;
}
#Override
protected Boolean doInBackground(Context... params) {
return true;
}
public void writeToStream(String s) {
try {
if (c != null){
//Log.i("AsynkTask", "writeToStream");
dos.writeBytes(s+"\n");
dos.flush();
Log.i("AsynkTask", "write: " +s);
} else {
Log.i("AsynkTask", "writeToStream : Cannot write to stream, Socket is closed");
}
} catch (Exception e) {
Log.i("AsynkTask", "writeToStream : Writing failed");
}
}
}
And the ConnectionListening class:
public class ConnectionListening extends TimerTask{
public DataInputStream dis;
Socket c;
ServerService server;
public ConnectionListening(Socket c, DataInputStream dis, ServerService server)
{
this.c = c;
this.dis = dis;
this.server = server;
}
#Override
public void run() {
String message = "";
try {
if (c != null) {
//Log.i("AsynkTask", "readFromStream : Reading message");
message = dis.readLine();
Log.i("AsynkTask", "read: " + message);
} else {
Log.i("AsynkTask", "readFromStream : Cannot Read, Socket is closed");
}
} catch (Exception e) {
Log.i("AsynkTask", "readFromStream : Writing failed");
}
if(message != null)
{
this.server.messageNotify(message);
}
}
}
I choose this complex, asynchronous way because the server is almost continuous sending data to the client and there are situations where the client has to send data back.
With the traditional way of using tcp sockets, it is not possible to realise a non blocking communication, so that means if the server is sending (writing), the read function blocks and i will never get the client message.
to keep it short:
Ive tested my approach but the server is always sending his data first and then getting the client messages. It is not asynchronous!? :-/
Maybe anybody can help me to solve this problem.
Or is there even a simpler way to implement that approach?
It is necessary that the communication is asynchronous! And the read has to be done automatically (what i tried to implement with this polling approach).
Ive read that i can use a single thread for the reading and one for the writing, but then i have a problem with using the write functionality (dont know how to call a function in a running thread) and with calling functions in my activities.
Im thankful for every help!
regards
I have an app in java which is playing the rolle of a server .For limiting the number of incoming connections I'm using a ThreadPool server.
But I have a few problems understanding a part of the code:
Here is y code:
protected ExecutorService threadPool =
Executors.newFixedThreadPool(5);
public ThreadPooledServer(BlockingQueue queue,int port) {
this.serverPort = port;
this.queue=queue;
}
while (!isStopped()) {
Socket clientSocket = null;
try {
System.out.println("Serverul asteapta clienti spre conectare la port" +serverPort);
clientSocket = serverSocket.accept();
clientconnection++;
System.out.println("Serverul a acceptat clientul cu numarul:"
+ clientconnection);
} catch (IOException e) {
if (isStopped()) {
System.out.println("Server Stopped.");
return;
}
throw new RuntimeException("Error accepting client connection",
e);
}
WorkerRunnable workerRunnable = new WorkerRunnable(queue,clientSocket);
this.threadPool.execute(workerRunnable);
}
this.threadPool.shutdown();
System.out.println("Server Stopped.");
}
private synchronized boolean isStopped() {
return this.isStopped;
}
public synchronized void stop() {
this.isStopped = true;
try {
this.serverSocket.close();
}
catch (IOException e) {
throw new RuntimeException("Error closing server", e);
}
}
private void openServerSocket() {
try {
InetSocketAddress serverAddr = new InetSocketAddress(SERVERIP,
serverPort);
serverSocket = new ServerSocket();
serverSocket.bind(serverAddr);
} catch (IOException e) {
throw new RuntimeException("Cannot open port", e);
}
}
WHAT I don't understand:
I'm using a ThreadPooledServer which accepts for 5 incoming connections....
The connection with the clients is done in a while() loop.
while (!isStopped()) {
}
isStopped is a boolean variable returned byt this function:
private synchronized boolean isStopped() {
return this.isStopped;
}
which I call as a condition for starting the loop.
This boolean variable is initially set to false.....and is set back to true in the here:
public synchronized void stop() {
this.isStopped = true;
}
When is setup back to true my while() loop ends and then I close up all the workers of my thread pool.
this.threadPool.shutdown();
The problem is that I never call for this function " stop() "
Question: Is the function called automatically when I close my server?????...or I should call for it somewhere????
You need to call it somewhere in your code to stop your server and close those connections. If you don't the system will eventually reclaim its resources as the server will be shutting down.
You should be able to register a shutdown hook in the JVM (which can call stop()) to help with reclaiming those yourself... Good luck!