i am making an android socket app to communicate with the server for creating accounts, and i noticed i have to do this in AsyncTask sub class, even when i seperate it to another class without UI,but i am terribly confused how can i use AsyncTask on this, is there any one expert here who can help me please?
this is the code:
public class AccountCreator extends Activity {
public AccountCreator(){
super();
}
// for I/O
ObjectInputStream sInput; // to read from the socket
ObjectOutputStream sOutput; // to write on the socket
Socket socket;
public static String LOGTAG="Lifemate";
public String server = "localhost";
public String username = "user";
public String password = "rezapassword" ;
public int port = 1400;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
Log.i(LOGTAG,"oncreate called");
this.start();
}
AccountCreator(String server, int port, String username,String password) {
this.server = "localhost";
this.port = 1400;
this.username = username;
Log.i(LOGTAG,"first accountcreator called");
}
public boolean start() {
// try to connect to the server
//this method returns a value of true or false when called
try {
socket = new Socket(server, port);
}
// if it failed not much I can so
catch(Exception ec) {
// display("Error connectiong to server:" + ec);
Log.i(LOGTAG,"Error connectiong to server:" + ec);
return false;
}
String msg = "Connection accepted " + socket.getInetAddress() + ":" +
socket.getPort();
// display(msg);
Log.i(LOGTAG, msg);
/* Creating both Data Stream */
try
{
sInput = new ObjectInputStream(socket.getInputStream());
sOutput = new ObjectOutputStream(socket.getOutputStream());
}
catch (IOException eIO) {
// display("Exception creating new Input/output Streams: " + eIO);
Log.i(LOGTAG,"Exception creating new Input/output Streams: " +
eIO);
return false;
}
// creates the Thread to listen from the server
// Send our username to the server this is the only message that we
// will send as a String. All other messages will be ChatMessage objects
try
{
sOutput.writeObject(username);
sOutput.writeObject(password);
}
catch (IOException eIO) {
// display("Exception doing login : " + eIO);
Log.i(LOGTAG,"Exception doing login : " + eIO);
disconnect();
return false;
}
// success we inform the caller that it worked
return true;
}
// private void display(String msg) {
// TextView screenprint = (TextView)findViewById(R.id.systemmessages);
// screenprint.setText(msg);
// }
private void disconnect() {
Log.i(LOGTAG,"reached disconnect");
try {
if(sInput != null) sInput.close();
}
catch(Exception e) {} // not much else I can do
try {
if(sOutput != null) sOutput.close();
}
catch(Exception e) {} // not much else I can do
try{
if(socket != null) socket.close();
}
catch(Exception e) {} // not much else I can do
}
public void Begin() {
Log.i(LOGTAG,"it begun");
int portNumber = 1400;
String serverAddress = server;
String userName = username;
String newpassword = password;
AccountCreator accountcreator = new AccountCreator(serverAddress, portNumber,
userName,password);
if(!accountcreator.start())
return;
}
}
i was trying to put whole code in Async, i dont know if was i right, do i need to do that also or just some parts of it?
In brief, AsyncTask contains a few methods which may be helpful:
onPreExecute:
This method is the first block of code executed when calling asyncTask.execute(); (runs on mainUIThread).
doInBackground:
Here you put all the code which may suspend you main UI (causes hang for your application) like internet requests, or any processing which may take a lot of memory and processing. (runs on background thread), contains one parameter taken from the asyncTask.execute(ParameterType parameter);
onPostExecute
Runs after doInBackground(). Its parameter is the return value of the doInBackground function, and mainly you put the changes in UI need to be done after the connection is finished (runs on mainUIThread)
You have to declare another class within the class you have already created.
class SomeName extends Async<Void, String, Void>{
protected void OnPreExecute(){
// starts the task runs on main UI thread
// Can be used to start a progress dialog to show the user progress
}
#Override
protected Void doInBackground(Void... params){
// does what you want it to do in the background
// Connected to the server to check a log-in
return result;
}
protected void OnPostExecute(Void result){
// finishes the task and can provide information back on the main UI thread
// this would be were you would dismiss the progress dialog
}
}
Related
I’m attempting to write Espresso unit test that depends on a component that makes TCP/IP network connection to an external app in order to pass successfully.
The test failed to due the fact that the TCP/IP network took longer than the allowed by Espresso...
Therefore, we need to have TCP/IP code Class TCPConnectionTask implement IdlingResource:
However, I'm getting, this exception:
java.lang.RuntimeException: Can't create handler inside thread that has not called Looper.prepare()
at android.os.Handler.<init>(Handler.java:200)
at android.os.Handler.<init>(Handler.java:114)
at android.app.Activity.<init>(Activity.java:786)
at com.sample.QuicksetSampleActivity.<init>(QuicksetSampleActivity.java:82)
at com.unitTests.QuicksetSampleActivityTest.<init>(QuicksetSampleActivityTest.java:52)
I enclosed the TCPConnectionTask and called Looper.prepare() & also attempted Looper.prepareMainLooper() , with no success, see below (TCPConnectionTask):
/**
* Async task to connect to create TCPIPDataComm and connect to external IRB.
*
*/
public class TCPConnectionTask extends AsyncTask<String, Void, Void > implements IdlingResource {
String ip_user = null;
int port_user;
private ResourceCallback callback;
private boolean flag = false;
protected Void doInBackground(String... args) {
try {
Handler handler = new Handler(Looper.getMainLooper());
handler.post(
new Runnable() {
#Override
public void run() {
Looper.prepare();
//Looper.prepareMainLooper();
flag = true;
TCPIPDataComm tcp = new TCPIPDataComm(ip_user, port_user);
if(tcp != null){
tcp.open();
_TCPDataComm = tcp;
// we can enable the DataComm interface for simulation in UI app
int resultCode = 0;
try {
resultCode = QuicksetSampleApplication.getSetup().setDataCommInfo(
getAuthKey(), _TCPDataComm.getHostName(),
_TCPDataComm.getPortNumber());
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
finally {
//task completed
flag = false;
}
Log.d(QuicksetSampleActivity.LOGTAG,
"Setting DataComm Result = "
+ resultCode
+ " - "
+ ResultCode
.getString(resultCode));
}
}
}
);
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
public void setInfo(String ipValue, int portNumber)
{
ip_user = ipValue;
port_user = portNumber;
}
#Override
public String getName() {
return this.getClass().getName().toString();
}
#Override public boolean isIdleNow() {
if (flag && callback != null) {
callback.onTransitionToIdle();
}
return flag;
}
#Override public void registerIdleTransitionCallback(ResourceCallback callback) {
this.callback = callback;
}
}
Below is the relevant snippet of the unit test class, QuicksetSampleActivityTest:
#RunWith(AndroidJUnit4.class)
public class QuicksetSampleActivityTest extends ActivityInstrumentationTestCase2<QuicksetSampleActivity> {
private QuicksetSampleActivity newQuicksetSampleActivity = null;
private final String ip = "192.168.43.139";
private final int port = 9999;
private final int timeOutTime = 1000;
//This is the idling resource that takes time to complete due to network latency...
private QuicksetSampleActivity.TCPConnectionTask taskIdlingResource = null;
//const
public QuicksetSampleActivityTest() {
super(QuicksetSampleActivity.class);
//instantiation of idling resource that is used for TCP connection
taskIdlingResource = new QuicksetSampleActivity().new TCPConnectionTask();
}
#Before
public void setUp() throws Exception {
super.setUp();
injectInstrumentation(InstrumentationRegistry.getInstrumentation());
//open activity
newQuicksetSampleActivity = getActivity();
// Make sure Espresso does not time out
IdlingPolicies.setMasterPolicyTimeout(timeOutTime * 10, TimeUnit.MILLISECONDS);
IdlingPolicies.setIdlingResourceTimeout(timeOutTime * 10, TimeUnit.MILLISECONDS);
//register idling resource
Espresso.registerIdlingResources(taskIdlingResource);
}
#After
public void unregisterIntentServiceIdlingResource() {
//unregister idling resource
Espresso.unregisterIdlingResources(taskIdlingResource);
}
//The EditText GUI with the port & Ip was noe found using espresso, we need to set teh ip & port programmatically
public void setIpandPortToPcBridge() {
// Use TCPCommunicatuonTask interface
taskIdlingResource.setInfo(ip, port);
taskIdlingResource.execute();
}
//after TCP connection is made and/or tested
#Test
public void testActionBarMenuItemsIrDevicesAfterTCPConnectionFunctions() {
//we were not able to find the IP & Port fields so set them programmatically
setIpandPortToPcBridge();
//open action bar menu
Espresso.openActionBarOverflowOrOptionsMenu(InstrumentationRegistry.getTargetContext());
//test IR Devices/Functions menu item
Espresso.onData(Matchers.allOf(Matchers.instanceOf(MenuItem.class), MatcherUtility.menuItemWithTitle("IR Devices/Functions"))).perform(ViewActions.click());
//add new device will connect the app
Espresso.onView(ViewMatchers.withId(R.id.btAdd)).perform(ViewActions.click());
//DeviceFunctionsActivity is rendered
Espresso.onView(ViewMatchers.withText("IR Devices")).check(ViewAssertions.matches(ViewMatchers.withText("IR Devices")));
//find the 3 required buttons for this UI
//test START learning
//Espresso.onView(ViewMatchers.withText("Start")).check(ViewAssertions.matches(ViewMatchers.withText("Start")));
//click
//test CANCEL learning
//test TEST Learned IR
//Espresso.onView(ViewMatchers.withText("Test Learned IR")).check(ViewAssertions.matches(ViewMatchers.withText("Test Learned IR")));
//click
//test Delete Learn Code
// Espresso.onView(ViewMatchers.withText("Delete Learn Code")).check(ViewAssertions.matches(ViewMatchers.withText("Delete Learn Code")));
//click
//go back
//ViewActions.pressBack();
}
}
}
How can I resolve this exception, and run the Espresso IdlingResource successfully?
Try
getInstrumentation().runOnMainSync(new Runnable() {
#Override
public void run() {
// Your testActionBarMenuItemsIrDevicesAfterTCPConnectionFunctions() test body
}
});
Example of usage with ActivityTestRule:
getInstrumentation().runOnMainSync(new Runnable() {
#Override
public void run() {
mMusicPlayerActivityTestRule.getActivity()
.getSupportMediaController().registerCallback(
new MediaControllerCompat.Callback() {
#Override
public void onPlaybackStateChanged(PlaybackStateCompat state) {
super.onPlaybackStateChanged(state);
if (state.getState() == STATE_PLAYING) {
countDownLatch.countDown();
}
}
});
}});
I am trying to implement connection failover in android application. Basically I have list of URLs which application connect using websocket, In case of unable to connect with any url I need to try a second connection. API which I am using to connect with websocket in android side is not synchronous. so when I start connect to websocket after executing this method I dont know either connection establish or not until OnOpen method called and then I set some boolean there to use further.
What I tried: One solution in my mind is to start to call connect method from a thread and sleep this for certain time if OnOpen method called within timespan is ok otherwise try to use second connection url.
Can someone give me hint how I can resolve this. Here is a sample code (without thread implementation):
private DataUploader() {
// test list of url
urlList = new ArrayList<String>();
urlList.add("192.168.220.197:9001/observation/");
urlList.add("192.168.220.197:9002/observation/");
urlList.add("echo.websocket.org");
connectWebSocket();
}
public void connectWebSocket() {
if (urlList.size() > -1) {
String url = urlList.get(index);
this.connect(url);
index++;
}
}
private void connect(String websocketEndPointUrl) {
URI uri;
try {
websocketEndPointUrl = "ws://" + websocketEndPointUrl;
uri = new URI(websocketEndPointUrl);
} catch (URISyntaxException e) {
e.printStackTrace();
return;
}
mWebSocketClient = new WebSocketClient(uri) {
#Override
public void onOpen(ServerHandshake serverHandshake) {
Log.i("Websocket", "Opened");
isReady = true;
}
#Override
public void onMessage(String s) {
///
}
#Override
public void onClose(int i, String s, boolean b) {
Log.i("Websocket", "Closed " + s);
}
#Override
public void onError(Exception e) {
Log.i("Websocket", "Error " + e.getMessage());
}
};
mWebSocketClient.connect();
}
I use a worker thread to read text from a url. My thread is as follow. In the first time running, I am sure thread running is finished as I can check sdcard_readstr is null.
In the second time running, when I call thread_download.start();, then the program crashed.
What could be wrong? Thanks
public class DownloadingThread extends AbstractDataDownloading {
#Override
public void doRun() {
// TODO Auto-generated method stub
try {
// Create a URL for the desired page
URL url = new URL(SDcard_DetailView.textfileurl);
// Read all the text returned by the server
BufferedReader in = new BufferedReader(new
InputStreamReader(url.openStream()));
do{
sdcard_readstr = in.readLine();
}while(sdcard_readstr!=null);
in.close();
} catch (MalformedURLException e) {
} catch (IOException e) {
}
}
}
public abstract class AbstractDataDownloading extends Thread{
private final Set<ThreadCompleteListener> listeners
= new CopyOnWriteArraySet<ThreadCompleteListener>();
public final void addListener(final ThreadCompleteListener listener) {
listeners.add(listener);
}
public final void removeListener(final ThreadCompleteListener listener) {
listeners.remove(listener);
}
private final void notifyListeners() {
for (ThreadCompleteListener listener : listeners) {
listener.notifyOfThreadComplete(this);
}
}
#Override
public final void run() {
try {
doRun();
} finally {
notifyListeners();
}
}
public abstract void doRun();
}
EDIT1:
In my thread complete notification, I use runOnUiThreadto use the UI components.
Is that causing problem?
public void notifyOfThreadComplete(Thread thread) {
// TODO Auto-generated method stub
if(downloadingStopbuttonispressed == false){//background process completed
textfileurl = null;
this.runOnUiThread(new Runnable() {
public void run() {
Wifibutton = (Button) findViewById(R.id.Wifiscanning);
Wifibutton.setText("Load another day's data");
final MenuItem refreshItem = optionsMenu.findItem(R.id.airport_menuRefresh);
refreshItem.setActionView(null);
}
});
}
}
I called thread start in onResume() as
#Override
protected void onResume() {
super.onResume();
if(textfileurl != null){
Wifibutton.setText("Stop Data Loading");
buttonStatus = "loading";
setRefreshActionButtonState(true);
thread_download.start();
}
}
EDIT2:
My LogCat image is attached.
My solution is here . I can't reuse the same instance of the Thread object in the second time. I need to create a new instance to call the Thread in the second time. So Thread is suitable for single time running process, for multiple time running process I should use AsyncTask. Even AsyncTack is only for one time execution and for multiple time execution, we should use as new MyAsyncTask().execute(""); I don't understand why people downvote with no reason given. I couldn't find the link in my first search.
Goodmorning,
I have a button on my android app that launches a search on the web (through google endpoints) through an AsyncTask. My problem is that the button does not "unclick" until the AsyncTask is completed, which may take several seconds. When the internet connection is slow, this even makes the application crash, in any case the application is completely stuck until the AsyncTask is completed. Now the reason for using AsyncTask was exactly to eliminate this problem, so I don't really get what happens!
Here is the OnClickListener:
SearchListener = new OnClickListener() {
#Override
public void onClick(View v) {
String cname=TextCourse.getText().toString();
if (!cname.isEmpty()){
try {
CollectionResponseWine listavini= new QueryWinesTask(messageEndpoint,cname,5).execute().get();
} catch (InterruptedException e) {
showDialog("Errore ricerca");
e.printStackTrace();
} catch (ExecutionException e) {
showDialog("Errore ricerca");
e.printStackTrace();
}
} else{
showDialog("Inserisci un piatto");
}
}
};
and here is the AsyncTask that is being called:
private class QueryWinesTask
extends AsyncTask<Void, Void, CollectionResponseWine> {
Exception exceptionThrown = null;
MessageEndpoint messageEndpoint;
String cname;
Integer limit;
public QueryWinesTask(MessageEndpoint messageEndpoint, String cname, Integer limit) {
this.messageEndpoint = messageEndpoint;
this.cname=cname;
this.limit=limit;
}
#Override
protected CollectionResponseWine doInBackground(Void... params) {
try {
CollectionResponseWine wines = messageEndpoint.listwines().setCoursename(cname).setLimit(limit).execute();
return wines;
} catch (IOException e) {
exceptionThrown = e;
return null;
//Handle exception in PostExecute
}
}
protected void onPostExecute(CollectionResponseWine wines) {
// Check if exception was thrown
if (exceptionThrown != null) {
Log.e(RegisterActivity.class.getName(),
"Exception when listing Messages", exceptionThrown);
showDialog("Non ci sono vini associati al tuo piatto. Aggiungine uno!");
}
else {
messageView.setText("Vini piu' votati per " +
cname + ":\n\n");
for(Wine wine : wines.getItems()) {
messageView.append(wine.getName() + " (" + wine.getScore() + ")\n");
}
}
}
}
...execute().get() is blocking. It makes UI thread wait for Task to complete.
Don't do get(). Use onPostExecute() to get the result (wines) of task and update the UI.
This is my code: (Some random text to complete question osdifhgsoid hgodfhgo hsdhoigifdshgnvfa oidvojd nobndisfn vbjobsf).
private class DownloadFilesTask extends AsyncTask<String, Integer, Long> {
protected Long doInBackground(String... urls) {
try{
Listen();
}
catch (Exception x)
{
textIn.setText("shit! " + x.toString());
}
long i = 10;
return i;
}
}
(Some random text again to complete question(stupid system) dpfgojd ipgsdigjsidoignsdog
public void Listen(){
int count = 0;
TextView msg = MyActivity.msg;
ServerSocket server;
Socket client;
try {
server = new ServerSocket(9797);
Log.d("My log", "server started");
Log.d("My log", "waiting for connnections");
while (started) {
try{
msg.setText("waiting for connection"); <=== here crashing
client = server.accept();
count++;
Log.d("My Log", "Connected");
Log.d("My Log", "aha" + count);
int i = 0;
String data = null;
byte[] bytes = new byte[1024];
InputStream is = client.getInputStream();
OutputStream os = client.getOutputStream();
while (is.available() == 0) {
try{
Thread.sleep(50);
}catch (Exception cc){}
}
is.read(bytes, 0, is.available());
os.write("hala".getBytes());
client.close();
}catch (Exception cc)
{
cc.toString();
}
}
} catch (Exception el) {
el.printStackTrace();
}
}
(Some random text to complete question). Please help
change it via the onPostExecute method!
The purpose of an AsyncTask is to do a long running task in a separate thread and then communicate the result back to the UI thread via onPostExecute().
Also, I'm not sure why you use Long as your return value since you do not seem to be using it. A much better solution would be to have Void as return value and save the exception and use that as an indicator if anything went wrong:
private class DownloadFilesTask extends AsyncTask<String, Integer, Void> {
private Exception exception = null;
#Override
protected Void doInBackground(String... urls) {
try{
Listen();
}
catch (Exception x) {
exception = x;
}
}
#Override
public void onPostExecute(Void result) {
if(exception != null) {
textIn.setText("shit! " + exception.toString());
}
else {
// long running task was completed successfully
}
}
}
Yes, because you are trying to set the TextView inside the doInBackground() method, and this is not allowed.
So there is a solution if you want to set the TextView inside the doInBackground() method, do the UI updating operations inside the runOnUiThread method.
Otherwise, suggestion is to do all the UI display/update related operations inside the onPostExecute() method instead of doInBackground() method of your AsyncTask class.
Good idea would be to return a String in doInBackground(), say exceptionCatched. You can set it to Exception title in catch() block and then in onPostExecuted() just check if(!TextUtils.isEmpty(exceptionCatched)) textIn.setText(exceptionCatched); That's it!
private class DownloadFilesTask extends AsyncTask<Void, Void,Long>{
#Override
protected Long doInBackground(Void... params) {
publishProgress(progress);
//calculate progress and value from your downloading logic
try {
} catch (Exception e) {
return (long) 0;
}
return null;
}
#Override
protected void onProgressUpdate(Void... values) {
super.onProgressUpdate(values);
//dis method run deafult on UI thread , so every time u publish ur onProgressUpdate will be called and update ur text here
}
#Override
protected void onPostExecute(Long result) {
super.onPostExecute(result);
if(result==0){
//error occured
}
}
// in case of exception return the result as long value to promt to onPostExceute()
I'm guessing runOnUiThread. You can't update the UI from any other thread than the UI thread.