Any way to edit a URI based on User Input? - java

I have an HTTP GET that is receiving information from a URI. The URI is for Google Shopping.
https://www.googleapis.com/shopping/search/v1/public/products?key=key&country=US&q=digital+camera&alt=atom
(Left my key out).
Is there a way that I can change it from
q=digital+camera
to anything a user puts in an EditText?
So basically, I want the EditText to change what is searched on Google Shopping.
First screen, ProductSearchEntry with EditText for search query:
Code for ProductSearchEntry
public class ProductSearchEntry extends Activity{
protected void onCreate(Bundle savedInstanceState){
super.onCreate(savedInstanceState);
setContentView(R.layout.productsearchentry);
Button search = (Button) findViewById(R.id.searchButton);
search.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
Intent searchIntent = new Intent(getApplicationContext(), ProductSearch.class);
startActivity(searchIntent);
}
});
}
}
Then, I have a second class, ProductSearch, with no picture, but just this code:
public class ProductSearch extends Activity{
protected void onCreate(Bundle savedInstanceState){
super.onCreate(savedInstanceState);
setContentView(R.layout.productsearchresults);
EditText searchQuery = (EditText) findViewById(R.id.searchQuery);
ProductSearchMethod test = new ProductSearchMethod();
String entry;
TextView httpStuff = (TextView) findViewById(R.id.httpTextView);
try {
entry = test.getSearchData(searchQuery.getText().toString());
httpStuff.setText(entry);
} catch (Exception e) {
e.printStackTrace();
}
}
}
Which references the ProductSearchMethod class which consists of a TextView that is changed to the code recieved in the HTTP GET:
Code:
public class ProductSearchMethod {
public String getSearchData(String query) throws Exception{
BufferedReader in = null;
String data = null;
try{
HttpClient client = new DefaultHttpClient();
URI site = new URI("https://www.googleapis.com/shopping/search/v1/public/products?key=key&country=US&q="+query.replace(" ","+")+"&alt=atom");
HttpGet request = new HttpGet();
request.setURI(site);
HttpResponse response = client.execute(request);
in = new BufferedReader(new InputStreamReader(response.getEntity().getContent()));
StringBuffer sb = new StringBuffer("");
String l = "";
String nl = System.getProperty("line.seperator");
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){
e.printStackTrace();
}
}
}
}
}
ProductSearchMethod comes up great, but it doesn't change the text from "Loading Items" to the website code. I had it working before but then I tried to edit what it searched (all this ^) and now it doesn't change.

Make changes in your code like
public class ProductSearchEntry extends Activity{
protected void onCreate(Bundle savedInstanceState){
super.onCreate(savedInstanceState);
setContentView(R.layout.productsearchentry);
EditText etSearch = (EditText) findViewById(id of your edittext);
Button search = (Button) findViewById(R.id.searchButton);
search.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
//while calling intent
Intent searchIntent = new Intent(getApplicationContext(), ProductSearch.class);
searchIntent.putExtra("searchText",etSearch.getText().toString());
startActivity(searchIntent);
}
});
}
}
and another activity like this,
public class ProductSearch extends Activity{
protected void onCreate(Bundle savedInstanceState){
super.onCreate(savedInstanceState);
setContentView(R.layout.productsearchresults);
String searchQuery = getIntent().getStringExtra("searchText");
ProductSearchMethod test = new ProductSearchMethod();
String entry;
TextView httpStuff = (TextView) findViewById(R.id.httpTextView);
try {
entry = test.getSearchData(searchQuery);
httpStuff.setText(entry);
} catch (Exception e) {
e.printStackTrace();
}
}
}

Yeah... Change your getSearchData() method to include a string as a parameter
public String getSearchData(String query) throws Exception{
Then, insert that string into the query URL, replacing spaces with "+". You may want to do further conditioning to the string, for instance URL encoding it.
URI site = new URI("https://www.googleapis.com/shopping/search/v1/public/products?key=key&country=US&q="+query.replace(" ","+")+"&alt=atom");
In your XML, create a button that contains the following line:
android:onClick="search"
In your ProductSearch activity, add the following method, and move the code in onCreate into it. You will also need to create an EditText in your XML for input.
public void search(View v)
{
EditText searchQuery = (EditText) findViewById(R.id.searchQuery);
ProductSearchMethod test = new ProductSearchMethod();
String returned;
try {
returned = test.getSearchData(searchQuery.getText().toString());
httpStuff.setText(returned);
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
Finally, you will probably want to read up on running asynchronous tasks so that the query won't freeze your app while performing.

May be I got you wrong, but why don't you just pass it as a parameter in
getSearchData() => getSearchData(string query)
Then you can change the line
URI site = new URI("https://www.googleapis.com/shopping/search/v1/public/products?key=key&country=US&q=digital+camera&alt=atom");
to
URI site = new URI("https://www.googleapis.com/shopping/search/v1/public/products?key=key&country=US&q=+ URLEncoder.encode(query, "UTF-8")+&alt=atom");

Check out http://androidforums.com/developer-101/528924-arduino-android-internet-garage-door-works-but-could-use-input.html I use Asynctask to trigger a get command on a local Arduino server. It appends the Arduino's pin number and, depending on if it's needed, a port number to the end of the URL. I'm sure you could use it to help you out.

Related

Cannot get correct SharedPreferences value on onClick

I'm currently making a small app and I'm getting stuck on changing fragments using an onClick listener. I've searched the site and could find similar situations, but none of the proposed solutions worked.
So, when a user logs in, it sets a few values in SharedPreferences such as username, email and account level using a method from a class used to set and get SharedPreferences values. Afterwards, it should automatically redirect the user to a different Fragment. What's not happening, is redirecting the user to the other fragment.
I'm using AsyncTask for accessing the database. This is my code for the Login AsyncTask:
public class LoginSync extends AsyncTask <String, Void, String> {
AlertDialog dialog;
Context context;
String result;
JSONObject jObject;
String username, password;
String jEmail, jLevel;
public LoginSync(Context context){
this.context = context;
}
#Override
protected void onPreExecute() {
dialog = new AlertDialog.Builder(context).create();
dialog.setTitle("Login Status");
}
#Override
protected void onPostExecute(String s) {
super.onPostExecute(s);
if(result.equals("login")) {
dialog.setMessage("Logged in successfully!");
}else{
dialog.setMessage("Failed to login! Please check username/password.");
}
dialog.show();
}
#Override
protected String doInBackground(String... voids) {
username = voids[0];
password = voids[1];
String connstr = "URL HERE";
try{
URL url = new URL(connstr);
HttpURLConnection http = (HttpURLConnection) url.openConnection();
http.setRequestMethod("POST");
http.setDoInput(true);
http.setDoOutput(true);
OutputStream ops = http.getOutputStream();
BufferedWriter writer = new BufferedWriter(new OutputStreamWriter(ops, StandardCharsets.UTF_8));
String data = URLEncoder.encode("username","UTF-8")+"="+URLEncoder.encode(username,"UTF-8")
+"&&"+URLEncoder.encode("password","UTF-8")+"="+URLEncoder.encode(password,"UTF-8");
writer.write(data);
writer.flush();
writer.close();
ops.close();
InputStream ips = http.getInputStream();
BufferedReader reader = new BufferedReader(new InputStreamReader(ips, StandardCharsets.ISO_8859_1));
String line;
while((line = reader.readLine()) != null){
jObject = new JSONObject(line);
result = "false";
if (jObject != null){
jEmail = jObject.getString("email");
jLevel = jObject.getString("account_level");
result = "login";
}
}
if(result.equals("login")) {
AppPreferences.setUserInfo(context.getApplicationContext(), username,jEmail,jLevel);
AppPreferences.setLoggedStatus(context.getApplicationContext(), true);
}
reader.close();
ips.close();
http.disconnect();
return result;
}catch (MalformedURLException e){
result = e.getMessage();
} catch (IOException e) {
e.printStackTrace();
} catch (JSONException e) {
e.printStackTrace();
}
return result;
}
}
Using the debugger, I see that the values are being set as intended in the SharedPreferences. However, in the onClick check on the Login Fragment, it's set to false until the onClick method ends.
This is my Login Fragment code:
public class LoginFragment extends Fragment {
private FragmentLoginBinding binding;
public View onCreateView(#NonNull LayoutInflater inflater,
ViewGroup container, Bundle savedInstanceState) {
binding = FragmentLoginBinding.inflate(inflater, container, false);
View root = binding.getRoot();
binding.btnLogin.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
final String user = binding.username.getText().toString().trim();
final String pass = binding.password.getText().toString().trim();
LoginSync login = new LoginSync(getActivity());
login.execute(user,pass);
if(AppPreferences.getLoggedStatusBool(getActivity()).equals(true)){
NavHostFragment.findNavController(getParentFragment()).navigate(R.id.action_nav_login_to_nav_home);
}
}
});
binding.lnkRegister.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
NavHostFragment.findNavController(getParentFragment()).navigate(R.id.action_nav_login_to_nav_register);
}
});
return root;
}
#Override
public void onDestroyView() {
super.onDestroyView();
binding = null;
}
}
On the first click, the values are set correctly, but checking the onClick with the debugger tells me that it's still false, after running the AsyncTask, and it doesn't trigger the fragment change in the if clause. On the second click, it changes the fragment.
What am I doing wrong? How can I make it change the fragment on the same click as it sets the information?
Thank you.
You are getting correct value from sharedPreference, only your timing to get that value is not correct. You are using async task, which works on a different thread. in your onCLick you have these lines:
LoginSync login = new LoginSync(getActivity());
login.execute(user,pass);
if(AppPreferences.getLoggedStatusBool(getActivity()).equals(true)){
NavHostFragment.findNavController(getParentFragment()).navigate(R.id.action_nav_login_to_nav_home);
}
you must have assumed that your if statement will execute after your login async task is completed, but this will not happen, it will execute straight after starting the login process and will check the sharedPref before the value is even set. You are doing network call and IO operation which will take some time and shared pref should be checked after the async task has been completed. So yo should write your if statement in async class's onPostExecute method like this:
#Override
protected void onPostExecute(String s) {
super.onPostExecute(s);
if(result.equals("login")) {
dialog.setMessage("Logged in successfully!");
if(AppPreferences.getLoggedStatusBool(getActivity()).equals(true)){
NavHostFragment.findNavController(getParentFragment()).navigate(R.id.action_nav_login_to_nav_home);
}
}else{
dialog.setMessage("Failed to login! Please check username/password.");
}
dialog.show();
}

Where should I put my AsyncTask class for my app?

So I have been trying to make a feature in my app where I can login and then fetch data from my database through the Django REST Framework. My logging in works as it only uses POST, but retrieving items does not work.
For some reason my AsyncTask does not get called for retrieving posts.
I have placed my AsyncTask for both activities, which are login and posts, on a separate java file only for handling Web Server stuff.
I am wondering if this is because I should put AsyncTask on each activities.
login.java
public class Login extends AppCompatActivity {
Button LoginButton;
EditText uUserName, uPassWord;
WSAdapter.SendAPIRequests AuthHelper;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_login);
//SetupHomeBtn = (ImageButton) findViewById(R.id.SetupHomeBtn);
LoginButton = (Button) findViewById(R.id.LoginButton);
uUserName = (EditText) findViewById(R.id.LoginUserBox);
uPassWord = (EditText) findViewById(R.id.LoginPassBox);
//AuthHelper = new WSAdapter().new SendDeviceDetails();
// Moves user to the main page after validation
LoginButton.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
// gets the username and password from the EditText
String strUserName = uUserName.getText().toString();
String strPassWord = uPassWord.getText().toString();
// API url duh
String APIUrl = "http://192.168.0.18:8000/token-auth/";
// If the user is authenticated, then transfer to the MainActivity page
if (APIAuthentication(strUserName, strPassWord, APIUrl)){
startActivity(new Intent(Login.this, Posts.class));
}
}
});
}
private boolean APIAuthentication(String un, String pw, String url){
// when it wasn't static -> AuthHelper = new WSAdapter().new SendAPIRequests();
AuthHelper = new WSAdapter.SendAPIRequests();
JSONObject postData = new JSONObject();
try {
// Attempt to input info to the Django API
postData.put("username", un);
postData.put("password", pw);
// Putting the data to be posted in the Django API
AuthHelper.execute(url, postData.toString());
return true;
} catch (JSONException e) {
e.printStackTrace();
}
return false;
}
}
posts.java
public class Posts extends AppCompatActivity {
TextView postsSect;
Button postsDoneBtn;
WSAdapter.SendAPIRequests PostsHelper;
StringBuilder postsBuffer = new StringBuilder();
#Override
protected void onResume(){
super.onResume();
PostsDetails postDetailsHelper = new PostsDetails();
postDetailsHelper.ListPosts();
}
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_posts);
PostsDetails postDetailsHelper = new PostsDetails();
postsDoneBtn = (Button) findViewById(R.id.PostsDoneButton);
postDetailsHelper.callPostDetails("192.168.0.18:8000/api");
postDetailsHelper.ListPosts();
postDetailsHelper.postDetailsCalled('n');
postsDoneBtn.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
startActivity(new Intent(Posts.this, MainActivity.class));
}
});
}
public class PostsDetails {
//String post_title, post_content;
ArrayList<Integer> post_id = new ArrayList<Integer>();
ArrayList<String> post_title = new ArrayList<String>();
ArrayList<String> post_content = new ArrayList<String>();
boolean isPDCalled;
// sets if Post details are called
boolean postDetailsCalled(char called) {
if (called == 'y'){
return true;
}
return false;
}
// checks if postsDetails functions are called for AsyncTask
boolean getIsPDCalled(){
return isPDCalled;
}
// calls the execute for AsyncTask
private void callPostDetails(String theurl){
PostsHelper = new WSAdapter.SendAPIRequests();
// sets if post details are called
postDetailsCalled('y');
// executes AsyncTask
PostsHelper.execute(theurl);
}
// sets values for the posts arrays
public void setPost(int p_id, String p_title, String p_content) {
post_id.add(p_id);
post_title.add(p_title);
post_content.add(p_content);
}
// Lists the posts from the database
public void ListPosts() {
/////////// add functionality if a post was deleted and was clicked
postsSect = (TextView) findViewById(R.id.PostsSection);
postsSect.setText(post_title.get(post_title.size()) + "\n");
for (int i = post_id.size() - 1; i > 0; i--)
{
postsSect.append(post_title.get(i));
}
}
}
}
WSAdapter.java
// I forgot what WS stands for, but this class serves as an adapter for JSON and Online stuff
// I think it stands for With-Server Adapter
public class WSAdapter extends AppCompatActivity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
}
static public class SendAPIRequests extends AsyncTask<String, String, String> {
// Add a pre-execute thing
#Override
protected String doInBackground(String... params) {
Log.e("TAG", params[0]);
Log.e("TAG", params[1]);
String data = "";
HttpURLConnection httpURLConnection = null;
try {
// Sets up connection to the URL (params[0] from .execute in "login")
httpURLConnection = (HttpURLConnection) new URL(params[0]).openConnection();
// Sets the request method for the URL
httpURLConnection.setRequestMethod("POST");
// Tells the URL that I am sending a POST request body
httpURLConnection.setDoOutput(true);
// To write primitive Java data types to an output stream in a portable way
DataOutputStream wr = new DataOutputStream(httpURLConnection.getOutputStream());
// Writes out a byte to the underlying output stream of the data posted from .execute function
wr.writeBytes("postData=" + params[1]);
// Flushes the postData to the output stream
wr.flush();
wr.close();
// Representing the input stream
InputStream in = httpURLConnection.getInputStream();
// Preparing input stream bytes to be decoded to charset
InputStreamReader inputStreamReader = new InputStreamReader(in);
StringBuilder dataBuffer = new StringBuilder();
// Translates input stream bytes to charset
int inputStreamData = inputStreamReader.read();
while (inputStreamData != -1) {
char current = (char) inputStreamData;
inputStreamData = inputStreamReader.read();
// concatenates data characters from input stream
dataBuffer.append(current);
}
data = dataBuffer.toString();
} catch (Exception e) {
e.printStackTrace();
} finally {
// Disconnects socket after using
if (httpURLConnection != null) {
httpURLConnection.disconnect();
}
}
Log.e("TAG", data);
return data;
}
#Override
protected void onPostExecute(String result) {
super.onPostExecute(result);
// expecting a response code fro my server upon receiving the POST data
Log.e("TAG", result);
Posts.PostsDetails postsHelper = new Posts().new PostsDetails();
// For posts
try {
if (postsHelper.getIsPDCalled()){
JSONObject pJObj = new JSONObject(result);
JSONArray pJObjArray = pJObj.getJSONArray("posts");
for (int i = 0; i < pJObjArray.length(); i++) {
JSONObject pJObj_data = pJObjArray.getJSONObject(i);
postsHelper.setPost(pJObj_data.getInt("id"), "post_title", "post_content");
}
}
} catch (JSONException e) {
//Toast.makeText(JSonActivity.this, e.toString(), Toast.LENGTH_LONG).show();
Log.d("Json","Exception = "+e.toString());
}
}
}
}
Yes, you can and should put the network calls functions in a separate java file for better readability and test-coverage.
Apart from that, i would suggest to use Retrofit as your HTTP client. It helps you to manage all the dirty things like headers and converters etc, so you can put all your effort on your logic and implementing your callback actions.

How to update/refresh TextView to show updated Json data every second?

I want to create an online queue monitoring application which it will show the new data entered to the database.The UI sample is below
I want the Current Serving Ticket to update every second if there is a new data entered(Json).
Here the MainActivity.java
public class MainActivity extends AppCompatActivity {
public static TextView data;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Button input_number = (Button) findViewById(R.id.button2);
Button reminder = (Button) findViewById(R.id.button);
final TextView userinputtext = (TextView) findViewById(R.id.textView6);
data = (TextView)findViewById(R.id.textView10);
Here is the data.java that i created.
public class data extends AsyncTask<Void,Void,Void> {
String data=" ";
String singleParsed = " ";
#Override
protected Void doInBackground(Void... voids) {
try {
URL url = new URL("url/SamplePage.php");
HttpURLConnection httpURLConnection=(HttpURLConnection) url.openConnection();
InputStream inputStream = httpURLConnection.getInputStream();
BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(inputStream));
String line ="";
while(line!=null){
line = bufferedReader.readLine();
data = data + line;
}
JSONArray JA = new JSONArray(data);
for (int i =0; i<JA.length();i++){
JSONObject JO = (JSONObject) JA.get(i);
singleParsed = JO.get("ticket_number")+"";
//dataParsed = dataParsed + singleParsed;
}
}catch (MalformedURLException e){
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}catch (JSONException e){
e.printStackTrace();
}
return null;
}
#Override
protected void onPostExecute(Void aVoid) {
super.onPostExecute(aVoid);
MainActivity.data.setText(this.singleParsed);
}
}
If there is any comment or help I would appreciate. Thanks.
The fastest answer would be setting a timer each second to query the database for data, and update the view.
If you're looking for a more optimized, complete, documented and easier solution, I suggest you use firebase, which offers services like Realtime database : https://youtu.be/U5aeM5dvUpA
Of course there are other alternatives like RethinkDB.
You should also look up websocket since they are similar approach to this kind of real time update problem.
But firebase is perfect for this in my opinion.
You can use SyncAdapter and LiveData. If you use Room, it will be more easier to handle.

Android - Send HTTP Request with AsyncTask on Button Click | Problems with delegate

i am about to write a small application. On button click i send a http request in a custom async task class. I want to write this value in a EditText field and in a ListView as item. My problem now is that i want to return the value of the request to the main thread to process it further. I searched around and found a method with an interface. This is my asynctask class:
public class Request extends AsyncTask<String,Void,String> {
public AsyncResponse delegate=null;
private MainActivity mAct;
public Request(MainActivity mainActivity){
this.mAct = mainActivity;
}
#Override
protected String doInBackground(String... url){
String returnString = "";
try {
URL u = new URL(url[0]);
final HttpURLConnection connection = (HttpURLConnection)u.openConnection();
BufferedInputStream bis = new BufferedInputStream(connection.getInputStream());
byte[] content = new byte[1024];
int bytesRead = 0;
String strContent = "";
while((bytesRead = bis.read(content)) != -1){
strContent += new String(content,0,bytesRead);
}
returnString = strContent;
} catch (Exception e){
} finally {
return returnString;
}
}
protected void onPostExecute(String result){
delegate.processFinish(result);
}
}
And this is my MainActivity:
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
final Button btnSend = (Button)findViewById(R.id.btnSendMessage);
final ListView lv = (ListView)findViewById(R.id.treeView);
final EditText editText = (EditText)findViewById(R.id.txtReqID);
final MainActivity ma = this;
final ArrayList<String> arrList = new ArrayList<String>();
final ArrayAdapter<String> arrAdapter = new ArrayAdapter<String>(getApplicationContext(),R.layout.simple_list_item_1,arrList);
btnSend.setOnClickListener(new View.OnClickListener(){
public void onClick(View v){
String t = new String("http://myhttprequest");
Request r = new Request(ma);
public void onCreate(Bundle savedInstanceState){
r.delegate = this;
}
editText.setText(returnValue);
lv.setAdapter(arrAdapter);
arrList.add(returnValue);
arrAdapter.notifyDataSetChanged();
}
});
}
public interface AsyncResponse{
void processFinish(String output);
}
The problem is that i have to declare every variable as final because i acces them within a function. I don't feel very happy with my code now and i also have no idea how i can make this work. Any help is very much appreciated.
Best regards
Try this way:
btnSend.setOnClickListener(new View.OnClickListener(){
public void onClick(View v){
String t = new String("http://myhttprequest");
Request r = new Request(ma){
protected void onPostExecute(String result){
editText.setText(result);
lv.setAdapter(result);
arrList.add(result);
arrAdapter.result();
}
};
}
});
What you should do I pretty simple.
Create an AsyncTask constructor that takes "delegate" as param
1.1 In case the "delegate" is an Activity (it is in your case) just make sure it's hold in a WeakReference (to avoid memory leaks)
Do you thing with http
When you want to dispatch the callback, just use your "delegate" param (check for null - as it is a WeakReference).
Cheers!

onPostExecute retrieves null from server

I trying read data from server by using AsyncTask, but when i give the parameter to onPostExecute, it retrieves me null.The MainActivity class:
public class MainActivity extends Activity{
EditText name, password;
Button login;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
name = (EditText) findViewById(R.id.name);
password = (EditText) findViewById(R.id.password);
login = (Button) findViewById(R.id.login);
login.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
TextView uiUpdate = (TextView) findViewById(R.id.output);
String outputasync = uiUpdate.getText().toString();
String serverURL = "http://192.168.1.105/myapp/text.php";
LongOperation longOperation = new LongOperation(MainActivity.this);
longOperation.execute(serverURL);
longOperation.onPostExecute(uiUpdate);
}
});
}
The AsyncTask:
public class LongOperation extends AsyncTask<String, Void, String> {
private Context mcontext;
private String content;
private String error = null;
AlertDialog alertDialog;
public LongOperation(Context context){
mcontext = context ;
}
#Override
protected void onPreExecute() {
alertDialog = new AlertDialog.Builder(mcontext).create();
alertDialog.setTitle("Login Information....");
}
#Override
protected String doInBackground(String... urls) {
try {
URL url = new URL(urls[0]);
HttpURLConnection client = (HttpURLConnection)url.openConnection();
client.connect();
InputStream inputStream = client.getInputStream();
BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(inputStream));
content = bufferedReader.readLine();
bufferedReader.close();
inputStream.close();
client.disconnect();
} catch (IOException e) {
error = e.getMessage();
}
return null;
}
protected void onPostExecute(TextView unused) {
alertDialog.dismiss();
if (error != null) {
unused.setText("Output : " + error);
} else {
unused.setText("Output : "+ content);
}
}
}
The connectivity to server is correct, the problem is display the message inside the server in the TextView.
Upadte and solution
Like androholic said :
You should not be calling onPostExecute manually from your code. Calling execute on the asynctask should suffice. onPostExecute will automatically be called when the asynctask finishes its work.
And change the onPostExecute parameter to String
And for retrieve a TextView with the message of the server, i did what Sharj said:
2) How to set your TextView that is in your Activity. The simplest way is to pass activity variable to LongOperation constructor and use that for accessing TextView in onPostExecute.
The AsyncTask:
public class LongOperation extends AsyncTask<String, Void, String> {
TextView textviews;
private Context mcontext;
private String content;
private String error = null;
AlertDialog alertDialog;
public LongOperation(Context context, TextView textView){
textviews = textView;
mcontext = context ;
}
#Override
protected void onPreExecute() {
alertDialog = new AlertDialog.Builder(mcontext).create();
alertDialog.setTitle("Login Information....");
}
#Override
protected String doInBackground(String... urls) {
try {
URL url = new URL(urls[0]);
HttpURLConnection client = (HttpURLConnection)url.openConnection();
client.connect();
InputStream inputStream = client.getInputStream();
BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(inputStream));
content = bufferedReader.readLine();
bufferedReader.close();
inputStream.close();
client.disconnect();
} catch (IOException e) {
error = e.getMessage();
}
return null;
}
#Override
protected void onPostExecute(String unused) {
alertDialog.dismiss();
if (error != null) {
unused=("Output : " + error);
textviews.setText(unused);
} else {
unused=("Output : "+ content);
textviews.setText(unused);
}
}
The MainActivity class:
public class MainActivity extends Activity{
EditText name, password;
Button login;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
name = (EditText) findViewById(R.id.name);
password = (EditText) findViewById(R.id.password);
login = (Button) findViewById(R.id.login);
login.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
TextView uiUpdate = (TextView) findViewById(R.id.output);
String outputasync = uiUpdate.getText().toString();
String serverURL = "http://192.168.1.105/myapp/text.php";
LongOperation longOperation = new LongOperation(MainActivity.this, uiUpdate);
longOperation.execute(serverURL, outputasync);
}
});
}
Note: doInBackground still working with "return = null" because im just using it for read the data inside the server, not for retrieve it anywhere.
You should not be calling onPostExecute manually from your code. Calling execute on the asynctask should suffice. onPostExecute will automatically be called when the asynctask finishes its work.
First about the problem in your Activity:
LongOperation longOperation = new LongOperation(MainActivity.this);
longOperation.execute(serverURL);
longOperation.onPostExecute(uiUpdate);
longOperation.execute(serverURL); is an asynchronous method. Which means your program will call longOperation.onPostExecute(uiUpdate); right after execute method without waiting for the results in doInBackground.
You can't do that and you shouldn't do that. onPostExecute is automatically called after doInBackground returns result (which you return null right now.)
LongOperation longOperation = new LongOperation(MainActivity.this);
longOperation.execute(serverURL);
longOperation.onPostExecute(uiUpdate);
Now the solution:
1) doInBackground return type should always be equal to onPostExecute parameter.
If you are return String then onPostExecute will look like this:
protected void onPostExecute(String string) {
}
2) How to set your TextView that is in your Activity. The simplest way is to pass activity variable to LongOperation constructor and use that for accessing TextView in onPostExecute.
3) How to send data to onPostExecute? You have to return it in method:
#Override
protected String doInBackground(String... urls) {
// do anything here.
return "String"; //Since return type is String. You can change that you anything and make sure it matches `onPostExecute` parameter type.
}
Your doInBackground() method only returns null. Ever.
Your onPostExecute() method isn't called because it isn't overriding AsyncTask's onPostExecute() method, which would take a String argument

Categories