I have this activity class that won't catch the if block. Because I'm a beginner, I couldn't think of any other way to catch the given userID("001") to launch a specific intent(AdminTab) after the Splash Thread.
Could someone please help me point out what i'm doing wrong or advice me with some sample code? Thank you!
public class Splash extends Activity{
#Override
protected void onCreate(Bundle savedInstanceState) {
final UserFunctions userFunction = new UserFunctions();
super.onCreate(savedInstanceState);
setContentView(R.layout.splash);
Thread timer = new Thread(){
public void run(){
String id = "";
id = userFunction.getID(getApplicationContext());
try{
sleep(1000);
//Should open AdminTab if user id is "001"
if("001".equals(id)){
Intent i = new Intent(getApplicationContext(),
AdminTab.class);
startActivity(i);
}else{
Intent i = new Intent(getApplicationContext(),
UserTab.class);
startActivity(i);
}
} catch (InterruptedException e){
e.printStackTrace();
}finally {
}
}
};
timer.start();
}
This is the getID method from UserFunctions Class.
getUserID from a sqlite database handler.
UserFunctions.java
public String getID(Context context) {
String id = "";
DatabaseHandler db = new DatabaseHandler(context);
Cursor cursor = db.getUserID();
if(cursor != null) {
while(cursor.moveToNext()) {
id = cursor.getString(0);
}
} else {
id = "";
}
cursor.close();
db.close();
return id;
}
Your code should work fine, are you getting an error?
maybe change it to id.equals("001")
If this isn't the main activity why don't you just send the id through in the intent if required?
I'm not entirely sure what the problem is.
There is no prob in "001".equals(id).
Please check the id that you are getting from getID(). There is some problem with the id that you are fetching from the database. Try to print the value and cross check.
Related
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();
}
I am currently building a login system for a simple game application. What I am trying to achieve is the following: When a user logs in I want to display the top 5 highscores in the activity the user comes to after logging in.
The response I am getting from the database is a JSON encoded string looking like this:
{"success":true,"toplist":
[{"username":"Tom","score":"4200"},
{"username":"John","score":"2303"},
{"username":"Benjamin","score":"700"},
{"username":"Michael","score":"648"},
{"username":"Daniel","score":"500"}]
}
From here I would like to "handle" and pass the top 5 information to the userAreaActivity and then show the top 5 in a table.
Here is what I have so far in order to handle the response:
bSignIn.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
final String username = etUsername.getText().toString();
final String password = etPassword.getText().toString();
Response.Listener<String> responseListener = new Response.Listener<String>() {
#Override
public void onResponse(String response) {
try {
JSONObject jsonResponse = new JSONObject(response);
boolean success = jsonResponse.getBoolean("success");
if(success){
Intent userAreaIntent = new Intent(LoginActivity.this, UserAreaActivity.class);
LoginActivity.this.startActivity(userAreaIntent);
}
else
{
AlertDialog.Builder builder = new AlertDialog.Builder(LoginActivity.this);
builder.setMessage("Login failed!")
.setNegativeButton("Retry", null)
.create()
.show();
}
} catch (JSONException e) {
e.printStackTrace();
}
}
};
LoginRequest loginRequest = new LoginRequest(username, password, responseListener);
RequestQueue queue = Volley.newRequestQueue(LoginActivity.this);
queue.add(loginRequest);
}
});
If it is of any use this is what my UserAreaActivity.Java looks like:
public class UserAreaActivity extends AppCompatActivity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_user_area);
final TableLayout tlHighscores = (TableLayout) findViewById(R.id.tlHighscores);
Intent intent = getIntent();
}
}
Would be thrilled if someone would give me some guidance as to how I would do this in the most convenient way.
You can simply do this
Intent userAreaIntent = new Intent(LoginActivity.this, UserAreaActivity.class);
userAreaIntent.putString("data", jsonResponse.toString());
LoginActivity.this.startActivity(userAreaIntent);
And in UserAreaActivity
JSONObject jsonObj = new JSONObject(getIntent().getStringExtra("data"));
Once you get the jsonObj you can parse it and use it anyway you want.
This is what the Intent object is for - to provide an intent along with associated information. You can simply do:
Intent intent = new Intent(this, UserAreaActivity.class);
intent.putString("key", "value");
startActivity(intent);
Now, you can do intent.getStringExtra("key") in your receiving Acitivity to extract the values. You can pass your entire JSON string and retrieve information this way.
I'm retrieving some information from the server using REST. I make a Get call using AsyncTask. But I need to wait for the results... Is there any way to do it synchronously? So I can get the result.
Code:
private void sendStuff(Context context, String[] params) {
RESTGet restGet = new RESTGet(context);
restGet.setMessageLoading("Loading...");
try {
restGet.execute(params);
} catch (Exception e) {
e.printStackTrace();
}
restGet.stopMessageLoading();
Intent intent = new Intent(context, ShowPictures.class);
((Activity)context).startActivity(intent);
}
Thanks...
You can use get() to wait for the task to end and even get its result. But I would not recommend this, because it will freeze your app.
Example assuming that RESTGet extends AsyncTask:
private void sendStuff(Context context, String[] params) {
final int TIMEOUT = 2000;
RESTGet restGet = new RESTGet(context);
restGet.setMessageLoading("Loading...");
try {
restGet.execute(params).get(TIMEOUT, TimeUnit.MILLISECONDS);
} catch (Exception e) {
e.printStackTrace();
}
restGet.stopMessageLoading();
Intent intent = new Intent(context, ShowPictures.class);
((Activity)context).startActivity(intent);
}
Instead of using get, put your code in onPostExecute method, so it will be called after the task execution.
Ex:
private void sendStuff(Context context, String[] params) {
RESTGet restGet = new RESTGet(context) {
#Override
protected void onPostExecute(String feed) {
super.onPostExecute(feed);
this.stopMessageLoading();
Intent intent = new Intent(context, ShowPictures.class);
((Activity)context).startActivity(intent);
}
}.execute(params);
}
Hope it helps...
this is the LoginActivty
public class MainActivity extends Activity {
ProgressDialog prgDialog;
TextView errorMsg;
EditText emailET;
EditText pwdET;
Button button;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
requestWindowFeature(Window.FEATURE_NO_TITLE);
setContentView(R.layout.activity_main);
errorMsg = (TextView) findViewById(R.id.login_error);
emailET = (EditText) findViewById(R.id.loginEmail);
pwdET = (EditText) findViewById(R.id.loginPassword);
prgDialog = new ProgressDialog(this);
prgDialog.setMessage("Please wait...");
prgDialog.setCancelable(false);
button = (Button) findViewById(R.id.btnLogin);
final Button button = (Button) findViewById(R.id.btnLogin);
button.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
try {
// Get Email Edit View Value
String email = emailET.getText().toString();
// Get Password Edit View Value
String password = pwdET.getText().toString();
// When Email Edit View and Password Edit View have values
// other than Null
if (Utility.isNotNull(email) && Utility.isNotNull(password)) {
// When Email entered is Valid
if (Utility.validate(email)) {
// call the async task
JSONObject js = new HttpAsyncTask(
getApplicationContext()).execute(email,
password).get();
Toast.makeText(getApplicationContext(),
"Asynctask started", Toast.LENGTH_SHORT)
.show();
}
// When Email is invalid
else {
Toast.makeText(getApplicationContext(),
"Please enter valid email",
Toast.LENGTH_LONG).show();
}
}
// When any of the Edit View control left blank
else {
Toast.makeText(
getApplicationContext(),
"Please fill the form, don't leave any field blank",
Toast.LENGTH_LONG).show();
}
} catch (Exception ex) {
}
}
});
TextView registerScreen = (TextView) findViewById(R.id.link_to_register);
// Listening to register new account link
registerScreen.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
// Switching to Register screen
Intent i = new Intent(getApplicationContext(),
RegisterActivity.class);
startActivity(i);
}
});
}
}
then I am using a AsyncTask, this the code
public class HttpAsyncTask extends AsyncTask<String, Integer, JSONObject> {
private static InputStream stream = null;
private static String API;
private JSONObject responseJson = null;
private Context contxt;
private Activity activity;
public HttpAsyncTask(Context context) {
// API = apiURL;
this.contxt = context;
}
// async task to accept string array from context array
#Override
protected JSONObject doInBackground(String... params) {
String path = null;
String response = null;
HashMap<String, String> request = null;
JSONObject requestJson = null;
DefaultHttpClient httpClient = null;
HttpPost httpPost = null;
StringEntity requestString = null;
ResponseHandler<String> responseHandler = null;
// get the username and password
Log.i("Email", params[0]);
Log.i("Password", params[1]);
try {
path = "http://192.168.x.xxx/xxxxService/UserAuthentication";
new URL(path);
} catch (MalformedURLException e) {
e.printStackTrace();
}
try {
// set the API request
request = new HashMap<String, String>();
request.put(new String("Email"), params[0]);
request.put(new String("Password"), params[1]);
request.entrySet().iterator();
// Store locations in JSON
requestJson = new JSONObject(request);
httpClient = new DefaultHttpClient();
httpPost = new HttpPost(path);
requestString = new StringEntity(requestJson.toString());
// sets the post request as the resulting string
httpPost.setEntity(requestString);
httpPost.setHeader("Content-type", "application/json");
// Handles the response
responseHandler = new BasicResponseHandler();
response = httpClient.execute(httpPost, responseHandler);
responseJson = new JSONObject(response);
} catch (Exception e) {
Log.e("Buffer Error", "Error converting result " + e.toString());
}
try {
responseJson = new JSONObject(response);
} catch (JSONException e) {
Log.e("JSON Parser", "Error parsing data " + e.toString());
}
return responseJson;
}
#Override
protected void onPostExecute(JSONObject result) {
// TODO Auto-generated method stub
super.onPostExecute(result);
String myResJson;
try {
myResJson = responseJson.getString("status");
String test = myResJson;
if (test.equals("200")) {
Log.i("Login Success", "Success message");
} else {
Log.e("Login Error", "Error converting result ");
}
} catch (JSONException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
when I enter correct email and password, it comes to this line
Log.i("Login Success", "Success message");
from there I want to open the HomeActivty but it doesn't allow me to use intent, or even to toast
I need help to implement directing to Home Activity once the logging is success.
Here:
JSONObject js = new HttpAsyncTask(
getApplicationContext()).execute(email,
password).get();
Because you are getting result on Main Thread by calling AsyncTask.get() method AsyncTask.
First just call AsyncTask.execute method to start AsyncTask task :
new HttpAsyncTask(MainActivity.this).execute(email,password);
then use onPreExecute() to show progessbar and onPostExecute for starting next Activity :
#Override
protected void onPreExecute() {
// show ProgressDialog here
}
#Override
protected void onPostExecute(Void result) {
// parse json here and start Home Activity
//.........your code here
if (test.equals("200")) {
Log.i("Login Success", "Success message");
Intent intent = new Intent(contxt,HomeActivity.class);
contxt.startActivity(intent);
} else {
Log.e("Login Error", "Error converting result ");
}
}
You can start activity like this from AsyncTask, You should use the context.
mContext.startActivity(new Intent(CurrentActivity.this, Home.class));
Or try like this also
Intent intent = new Intent();
intent.setClass(getApplicationContext(),Home.class);
startActivity(intent);
I know there is another valid answer to fix your problem. But to precisely explain why your error exists, I give my answer below.
To create an Intent for startActivity(), this can be done by:
Intent i = new Intent(currentActivity, NextActivity.class);
startActivity(i);
Notice that the first parameter of constructor of Intent is android.content.Context, in which Activity is a subclass of it. So in any situation, you can always pass the Context to your custom class and start a new Activity or create a Toast with this Context.
In your question, private Context contxt; in HttpAsyncTask is the context your need to do everything.
Reference: http://developer.android.com/reference/android/content/Intent.html#Intent%28android.content.Context,%20java.lang.Class%3C?%3E%29
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.