how can i send data from a service to an activity if that activity is running without restarting service or activity. actually i have a Asynctask class inside my service that downloads a file and i wanna show the percentage of downloading on a Progress-bar inside an activity . can any one tell me how should i do that?
i tried interface in asynctask but it make a new request and my progress bar is null.
public class Downloader extends AsyncTask<Combine,String,Combine> {
Responcer1 responder;
HttpURLConnection connection;
int id;
int position;
public Downloader(int position){
this.position=position;
}
#Override
protected void onPreExecute() {
super.onPreExecute();
responder=new SavedLinks();
responder.start(position);
}
#Override
protected Combine doInBackground(Combine... param) {
try {
int position=param[0].position;
Log.i("downloader",param[0].caption+param[0].link+param[0].url+param[0].user);
id=param[0].id;
connection = null;
URL url;
url = new URL(param[0].link);
connection = (HttpURLConnection) url.openConnection();
connection.setConnectTimeout(45000);
connection.setReadTimeout(5000);
InputStream in = connection.getInputStream();
BufferedReader reader = new BufferedReader(new InputStreamReader(in, "UTF-8"), 8);
StringBuilder sb = new StringBuilder();
String line = null;
while ((line = reader.readLine()) != null) {
sb.append(line + "\n");}
in.close();
connection.disconnect();
return saperate(sb.toString(),param[0]);
} catch (Exception e) {
e.printStackTrace();
return null;
}}
}
I suggest you to use EventBus, a library written just to simplify interaction between activity, service and so on. It's quite simple to use, you can start reading quick start guide.
Well you don't need to actually send it all that frequently. Every couple of seconds is good enough for a progress bar. But ignoring that, there's a couple of good solutions:
1)Broadcast the status from the Service and use a BroadcastReceiver in the Activity
2)Bind to the service and pass in a status callback to the Service to call back to your activity
3)Use an EventBus for message passing of status
2 and 3 require the service to be in the same process, but since that's the default they're probably ok.
Related
Okay so I'm trying to make an app that is able to retrieve data from a web server and then show it on a textView and constantly update it if the data changes from the web server. And what I got so far after many rounds of trying is this as shown
public class HttpTest extends AppCompatActivity {
TextView text = (TextView) this.findViewById(R.id.textView3);
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_http_test);
HttpURLConnection urlConnection = null;
try {
URL url = new URL("http://IPGOESHERE/");
HttpURLConnection urLConnection = (HttpURLConnection) url.openConnection();
InputStream in = urLConnection.getInputStream();
BufferedReader data = new BufferedReader(new InputStreamReader(in));
StringBuilder total = new StringBuilder();
String line;
while ((line = data.readLine()) != null) {
total.append(line).append('\n');
}
String result = total.toString();
text.setText(result);
}
catch (Exception e) {
e.printStackTrace();
}
finally {
if (urlConnection != null) {
urlConnection.disconnect();
}
}
}
I don't think what i have written allows for constant update, but I at least want to be able to show some kind of data on a textView and make sure it doesn't crash first. So if someone could point out what I'm doing wrong it will be much appreciated.
The app crash because you are making HTTP request on main thread. Use an AsyncTask instead
you need to this kind of work on a different thread. try using an AsyncTask.
you create a class that extends AsyncTask, than make the url connection in the doInBackground method (a method that gets called on a worker thread). you can then update the textview in the onPostExecute method which is called on the ui thread. good luck :)
I need to fetch some data from my server in order to make my app work. In order to do that, I will be using POST. As far as I know, I have to request that data in a thread which can not be the main thread. I am finding it a little bit difficult to put the data I am receiving in a variable defined in the UI thread. So, my question is, which is the best way to do it?
Is it correct to set the value of a variable defined, for example, in my main activity, with a setter called inside an AsyncTask? Or is there a better option than this?
Thread nt = new Thread(){
#Override
public void run(){
try{
//get data with POST and then something like main.setValue(data);
}catch(Exception e){
e.printStackTrace();
}
}
};
nt.start();
I have read that I may use Interfaces in order to archive that, but it is a concept that I do not understand very well yet. I would like to directly use a method which returns the data, but as far as I know, it is not possible.
EDIT: new code according to NoChinDeluxe answer:
public class LoginHandler {
public static class Login extends AsyncTask<String, String, Integer> {
LoginCallback listener;
#Override
protected Integer doInBackground(String... params) {
URL url;
postDataParams.put("name", params[0]);
HashMap<String, String> postDataParams = new HashMap<String, String>();
postDataParams.put("password", params[1]);
try {
url = new URL("http://mashiron.xyz/_03z/gmpia/proc.php");
HttpURLConnection conn = (HttpURLConnection) url.openConnection();
conn.setReadTimeout(15000);
conn.setConnectTimeout(15000);
conn.setRequestMethod("POST");
conn.setDoInput(true);
conn.setDoOutput(true);
OutputStream os = conn.getOutputStream();
BufferedWriter writer = new BufferedWriter(
new OutputStreamWriter(os, "UTF-8"));
writer.write(HttpHandler.getPostDataString(postDataParams));
writer.flush();
writer.close();
os.close();
System.out.println("Respuesta: "+conn.getResponseCode());
return conn.getResponseCode();
} catch (Exception e) {
e.printStackTrace();
return 404;
}
}
protected void onPostExecute(int result){
System.out.println("Respuesta 2: "+result);
listener.onResultReceived(result);
}
}
public interface LoginCallback {
void onResultReceived(int result);
}
}
EDIT: added exception for NoChinDeluxe:
03-24 17:38:09.072 13312-13312/com.pitazzo.geomoments E/AndroidRuntime: FATAL EXCEPTION: main
Process: com.pitazzo.geomoments, PID: 13312
java.lang.NullPointerException: Attempt to invoke interface method 'void com.pitazzo.geomoments.Handlers.LoginHandler$LoginCallback.onResultReceived(int)' on a null object reference
at com.pitazzo.geomoments.Handlers.LoginHandler$Login.onPostExecute(LoginHandler.java:65)
at com.pitazzo.geomoments.Handlers.LoginHandler$Login.onPostExecute(LoginHandler.java:17)
at android.os.AsyncTask.finish(AsyncTask.java:636)
at android.os.AsyncTask.access$500(AsyncTask.java:177)
at android.os.AsyncTask$InternalHandler.handleMessage(AsyncTask.java:653)
at android.os.Handler.dispatchMessage(Handler.java:102)
at android.os.Looper.loop(Looper.java:135)
at android.app.ActivityThread.main(ActivityThread.java:5300)
at java.lang.reflect.Method.invoke(Native Method)
at java.lang.reflect.Method.invoke(Method.java:372)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:904)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:699)
EDIT: more code for NoChainDeluxe
public class LoginActivity extends AppCompatActivity implements LoginHandler.LoginCallback{
EditText name;
EditText password;
Button login;
int code;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.login_activity);
/*
if(logueado){
}
*/
name = (EditText) findViewById(R.id.loginuser);
password = (EditText) findViewById(R.id.loginpassword);
login = (Button) findViewById(R.id.loginlogin);
login.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
String params[] = {name.getText().toString(), password.getText().toString()};
System.out.println("Params: "+params.toString());
new LoginHandler.Login().execute(params);
System.out.println("Respuesta 4: "+code);
if(code == 200){
Toast toast1 =
Toast.makeText(getApplicationContext(),
"Iniciado sesión", Toast.LENGTH_SHORT);
toast1.show();
}else{
Toast toast1 =
Toast.makeText(getApplicationContext(),
"Nombre de usuario y/o contraseña incorrectos: "+code, Toast.LENGTH_SHORT);
toast1.show();
}
}
});
}
public void onResultReceived(int resultado) {
code = resultado;
System.out.println("Respuesta 3: "+code);
}
}
The best way to achieve this is to use an HttpURLConnection to make your web calls inside an AsyncTask and then pass the result back to your calling Activity through a callback. Here's some code to help you get started:
The first thing you should understand is how to properly use a callback with an AsyncTask. Here is an example AsyncTask that defines a callback interface:
import android.os.AsyncTask;
public class TestTask extends AsyncTask<String, Void, String> {
TestTaskCallback listener;
public TestTask(TestTaskCallback listener) {
this.listener = listener;
}
protected String doInBackground(String... args) {
String input = args[0];
String output = "simulated return value";
return output;
}
protected void onPostExecute(String result) {
listener.onResultReceived(result);
}
public interface TestTaskCallback {
void onResultReceived(String result);
}
}
The way this works is, you define a public interface that you then implement in your Activity. This acts as a "listener" that is waiting for any data that is sent through to it. We define the interface TestTaskCallback because we are going to be sending our data from our AsyncTask to our calling Activity.
Then in the Activity, we need to implement this interface, and pass in a reference to our implementation to the task when we create it. That way, when the task fires, it knows where to send the result, which is back to our Activity. An example implementation might look like this:
public class TestActivity extends AppCompatActivity implements TestTask.TestTaskCallback {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.your_layout);
new TestTask(this).execute("Some input");
}
public void onResultReceived(String result) {
Log.d("TEST TASK RESULT", result);
}
}
So our Activity implements the interface that we defined inside our AsyncTask, and notice that our AsyncTask takes the reference to this implementation (passed in through the constructor) and sends data to it in the onPostExecute() method. This will allow your result to be sent to the main UI thread so that you can update your Activity appropriately.
The only thing left is to actually make the web calls. I would recommend using an HttpURLConnection for this. You would put this code inside the doInBackground() method of your AsyncTask.
I'll show you an example web service call I have set up. This shows how to make a web service call to retrieve a JSON response. It looks something like this:
//The JSON we will get back as a response from the server
JSONObject jsonResponse = null;
//Http connections and data streams
URL url;
HttpURLConnection httpURLConnection = null;
OutputStreamWriter outputStreamWriter = null;
try {
//open connection to the server
url = new URL("your_url_to_web_service");
httpURLConnection = (HttpURLConnection) url.openConnection();
//set request properties
httpURLConnection.setDoOutput(true); //defaults request method to POST
httpURLConnection.setDoInput(true); //allow input to this HttpURLConnection
httpURLConnection.setRequestProperty("Content-Type", "application/json"); //header params
httpURLConnection.setRequestProperty("Accept", "application/json"); //header params
httpURLConnection.setFixedLengthStreamingMode(jsonToSend.toString().getBytes().length); //header param "content-length"
//open output stream and POST our JSON data to server
outputStreamWriter = new OutputStreamWriter(httpURLConnection.getOutputStream());
outputStreamWriter.write(jsonToSend.toString());
outputStreamWriter.flush(); //flush the stream when we're finished writing to make sure all bytes get to their destination
//prepare input buffer and get the http response from server
StringBuilder stringBuilder = new StringBuilder();
int responseCode = httpURLConnection.getResponseCode();
//Check to make sure we got a valid status response from the server,
//then get the server JSON response if we did.
if(responseCode == HttpURLConnection.HTTP_OK) {
//read in each line of the response to the input buffer
BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(httpURLConnection.getInputStream(),"utf-8"));
String line;
while ((line = bufferedReader.readLine()) != null) {
stringBuilder.append(line).append("\n");
}
bufferedReader.close(); //close out the input stream
try {
//Copy the JSON response to a local JSONObject
jsonResponse = new JSONObject(stringBuilder.toString());
} catch (JSONException je) {
je.printStackTrace();
}
}
} catch (IOException ioe) {
ioe.printStackTrace();
} finally {
if(httpURLConnection != null) {
httpURLConnection.disconnect(); //close out our http connection
}
if(outputStreamWriter != null) {
try {
outputStreamWriter.close(); //close our output stream
} catch (IOException ioe) {
ioe.printStackTrace();
}
}
}
//Return the JSON response from the server.
return jsonResponse;
This is pretty much all you need to know to do exactly what it is you are trying to do. I realize this is a ton of info to throw at you all at once, but if you take your time and work through it piece by piece, you'll find it's not too difficult after all and is actually a VERY powerful tool that you'll use all the time programming Android apps!
Hope this helps. Feel free to ask questions for any parts you don't fully understand yet!
Better use an AsyncTask to propagate the data to your UI thread, just use onPostExecute() to set the result on your activity's class.
The error you are getting is because of accessing UI elements from background thread.
AsyncTask is a Thread pool based api that runs your task in a seperate thread
,but your UI part runs in a thread usually called UI thread,
to update any changes to ui put the logic onPostExecute()
NOTE: Use okhttp to get consistent http api, it also supports http2.Their github wiki is very helpful, check here for examples.
I am developing an app that logs onto a tomcat server.
I am using a HTTP GET request to do so, and upon successful connection,
the message is displayed via a buffered stream.
The following code, is used to connect.
public String getInternetData() throws Exception {
BufferedReader in = null;
String data = null;
try {
HttpClient client = new DefaultHttpClient();
client.getConnectionManager().getSchemeRegistry().register(getMockedScheme());
URI website = new URI("https://ts.rks.com:8443/kss/login?username=hydm&password=pw1234");
HttpGet request = new HttpGet();
request.setURI(website);
HttpResponse response = client.execute(request);
response.getStatusLine().getStatusCode();
in = new BufferedReader(new InputStreamReader(response.getEntity().getContent()));
StringBuffer sb = new StringBuffer("");
String l = "";
String nl = System.getProperty("line.separator");
while ((l = in.readLine()) != null) {
sb.append(l + nl);
}
in.close();
data = sb.toString();
return data;
} finally {
if (in != null) {
try {
in.close();
return data;
} catch (Exception e) {
Log.e("GetMethodLogin", e.getMessage());
}
}
}
This is the code that is activated when the user logs in via a login activity.
When I go back to the menu screen and try to run another activity that requires the user
to be logged in, it says that the user is not logged in.
Is the connection being disconnected when the user moves away from the activity or am I not establishing the connection correctly.
There are actually two things you need to change, not just one.
Anything that you need to have persistent across Activities should be done in a Service, not in the code of an Activity.
Second, on recent Android releases, all networking must be done from background threads, rather than the UI thread (there was always a recommendation against UI thread networking, but now it triggers an exception). Just putting the code in a Service does not mean it is in another thread.
So the answer is that you should be doing this using one of the background threading mechanisms, and doing that within a Service.
The connection will not persist when the activity is moved to the background. I cannot tell from your posted code, but I believe you should be using an AsyncTask for this connection. This is coming from my experience pulling HTML source from a link.
This question may answer yours: What to do with AsyncTask in onPause()?
The first time I made a method to read data from my chat server, it frooz. I found out I had the wrong port number and it was freezing at
new BufferedReader(new InputStreamReader(conn.getInputStream()));
Is there a way to have a time out so my program does not freez on a network error? I'm assuming there must be,
the complete methed
void SendMessage()
{
try {
URL url = new URL("http://50.63.66.138:1044/update");
System.out.println("make connection");
URLConnection conn = url.openConnection();
conn.setDoOutput(true);
BufferedReader rd = new BufferedReader(new InputStreamReader(conn.getInputStream()));
// String line;
String f=new String("");
String line=new String();
while ((line= rd.readLine() ) != null) {
f=f+line;
f+="\n";
}
mUsers.setText(f);
} catch (Exception e) {
System.out.println("exception");
System.out.println(e.getMessage());
}
}
}
First of all, I hope you execute this code in a separate thread in order to make your UI thread responsive on touches even while connection is being established.
Second, there are two timeout methods available for URLConnection class:
http://developer.android.com/reference/java/net/URLConnection.html#setReadTimeout(int)
http://developer.android.com/reference/java/net/URLConnection.html#setConnectTimeout(int)
Try to play with these guys, maybe it will help.
If not, you can always do your own way:
start the thread with a runnable which tries to establish a connection and InputReader. Then wait for some time-out and try to interrupt the thread if it is still running.
This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
Download a file with Android, and showing the progress in a ProgressDialog
I want to load info from a web server into my app. Currently I'm doing it in the main thread, which I've read is very bad practice (if the request takes longer than 5 secs, the app crashes).
So instead I'd like to learn how to move this operation to a background thread. Does this involve a service somehow?
Here is a sample of the code where I make server requests:
// send data
URL url = new URL("http://www.myscript.php");
URLConnection conn = url.openConnection();
conn.setDoOutput(true);
OutputStreamWriter wr = new OutputStreamWriter(conn.getOutputStream());
wr.write(data);
wr.flush();
// Get the response
BufferedReader rd = new BufferedReader(new InputStreamReader(conn.getInputStream()));
StringBuilder sb = new StringBuilder();
String line;
while ((line = rd.readLine()) != null) {
sb.append(line + "\n");
}
wr.close();
rd.close();
String result = sb.toString();
Intent i = new Intent(searchEventActivity.this, searchResultsActivity.class);
i.putExtra("result", result);
startActivity(i);
So I'm waiting to build up a JSON string response, then I'm passing that string to a new activity. This is a timely operation, and instead of hanging the UI, I'd like to show the user a nice "Progress" bar of some sort (even one of those circles with the spinning lights is good) while this URL business is happening in a background thread.
Thanks for any help or links to tutorials.
The basic idea of the process is to create a Thread to handle the web request, then use Handlers and Runnables to manage the UI interaction.
The way that I manage this in my apps is to use a custom class that includes all of the intelligence and business rules to manage my communications. It also includes variables in the constructor to allow the UI thread to be called.
Here's an example:
public class ThreadedRequest
{
private String url;
private Handler mHandler;
private Runnable pRunnable;
private String data;
private int stausCode;
public ThreadedRequest(String newUrl, String newData)
{
url = newUrl;
data = newData;
mHandler = new Handler();
}
public void start(Runnable newRun)
{
pRunnable = newRun;
processRequest.start();
}
private Thread processRequest = new Thread()
{
public void run()
{
//Do you request here...
if (pRunnable == null || mHandler == null) return;
mHandler.post(pRunnable);
}
}
}
This would be called from your UI thread as follows:
final ThreadedRequest tReq = new ThreadedRequest(url, maybeData);
//This method would start the animation/notification that a request is happening
StartLoading();
tReq.start(new Runnable()
{
public void run()
{
//This would stop whatever the other method started and let the user know
StopLoading();
}
});