passing values between classes by sharedPreferences in Android - java

I want to save a value in login page that I can use afterwards in other fragments. For doing this I used sharedPreferences and could store the "username", and here is the code:
Login.java
btnl.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
// get The User name and Password
String userName=un.getText().toString();
String password=pa.getText().toString();
String PATIENTID="";
// fetch the Password form database for respective user name
String storedPassword=demoCRUD.getSingleEntry_Username(userName);
// check if the Stored password matches with Password entered by user
if(password.equals(storedPassword)) {
show("Welcome!");
SharedPreferences userDetails = getContext().getSharedPreferences("userdetails", Context.MODE_PRIVATE);
Editor edit = userDetails.edit();
edit.clear();
edit.putString("_user", userName.trim());
edit.apply();
Intent intentLogin=new Intent(getActivity(),Welcome.class);
startActivity(intentLogin);
}
else {
show("User Name or Password does not match");
}
}
});
In addition I could fetch the value again using sharedPreferences in other fragment using the following code:
EditPersonal.java
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
ep_demoCRUD = new DemographicsCRUD(getActivity());
SharedPreferences userDetails = getContext().getSharedPreferences("userdetails", Context.MODE_PRIVATE);
String puser = userDetails.getString("_user", "");
show("puser = " + puser); *SHOWS ME IT HAS A STRING INSIDE
}
Also in "EditPersonal.java" I have this piece of code that call a method from different class:
protected Long doInBackground(Void... arg0) {
return ep_demoCRUD.UpdateDemographics(ep_demoId,puser);
}
The problem is that when onCreate method of "EditPersonal.java" run, "puser" has a value equal to the username from Login.java, but once "doInBachground" call the method "ep_demoCRUD.UpdateDemographics(ep_demoId,puser);" it pass null!
I printed the Log and I understood puser=null.
I can't understand what is the problem? why "null" is passed while it has already had the value ?
p.s the method UpdateDemographics is defined as following:
public long UpdateDemographics(Demographics_to demoId,String us) {
SQLiteDatabase db = dbHelper.getWritableDatabase();
ContentValues values = new ContentValues();
values.put(DataBaseHelper.lastName, demoId.getD_lastName());
values.put(DataBaseHelper.firstName, demoId.getD_firstName());
values.put(DataBaseHelper.dateOfBirth, demoId.getD_dateOfBirth());
Log.d("puser","=" +us); * NULL IS PRINTED IN LOG*
long result = database.update(dbHelper.Demographics_Table,values,"username = ?" , new String[]{us});
Log.d("Update Result:", "=" + result);
db.close();
return result;
}
Thank you in advance!

i think you are using two variable with same name puser ,, one of them global and the other is Local ,, Just make sure if thats true or not ,, if not then show me the full code of class EditPersonal.java

doInBackground(Void... arg0){}
You do not give the puser variable in the AsyncTask. Why not? is puser a global var?
try giving the puser var with the AsyncTask.
doInBackground(String... puser) {
return ep_demoCRUD.UpdateDemographics(ep_demoId,puser);
}
can you post the whole AsyncTask and where puser is defined?

Why are you using editor.clear()? If you want to store, replace editor.clear() with editor.commit();

Related

Nothing Happened when i put right and wrong password

why nothing happened when i put the correct email, but whatevet i put correct or incorrect password the program still not doing anything. It's like the program not checked the password, can you help me ?
This my login.php
<?php
if ($_SERVER['REQUEST_METHOD']=='POST') {
$email = $_POST['email'];
$password = $_POST['password'];
require_once 'connect.php';
$sql = "SELECT * FROM user WHERE email='$email' ";
$response = mysqli_query($conn, $sql);
$result = array();
$result['login'] = array();
if ( mysqli_num_rows($response) === 1 ) {
$row = mysqli_fetch_assoc($response);
if ( password_verify($password, $row['password']) ) { // I Think The Problem At This but i still don't know.
echo $password;
$index['name'] = $row['name'];
$index['email'] = $row['email'];
$index['id'] = $row['id'];
array_push($result['login'], $index);
$result['success'] = "1";
$result['message'] = "success";
echo json_encode($result);
mysqli_close($conn);
} else {
$result['success'] = "0";
$result['message'] = "error";
echo json_encode($result);
mysqli_close($conn);
}
}
}
?>
This my SignInActivity.java // or at this the problem is ?
public class SignInActivity extends AppCompatActivity {
private EditText email,password;
private Button login;
private TextView link_regist;
private static String URL_LOGIN = "https://awalspace.com/app/imbalopunyajangandiganggu/login.php";
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_sign_in);
email = findViewById(R.id.titEmail);
password = findViewById(R.id.titPassword);
login = findViewById(R.id.btnSignIn);
link_regist = findViewById(R.id.tvToSignUp);
login.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
String mEmail = email.getText().toString().trim();
String mPassword = password.getText().toString().trim();
if(!mEmail.isEmpty() || !mPassword.isEmpty())
{
login(mEmail,mPassword);
}
else{
email.setError("Silahkan Masukkan Email");
password.setError("Silahkan Masukkan Password");
}
}
});
}
private void login(final String email, final String password) {
StringRequest stringRequest = new StringRequest(Request.Method.POST, URL_LOGIN,
new Response.Listener<String>() {
#Override
public void onResponse(String response) {
try {
JSONObject jsonObject = new JSONObject(response);
String success = jsonObject.getString("success");
JSONArray jsonArray =jsonObject.getJSONArray("login");
if (success.equals("1")){
for (int i = 0; i < jsonArray.length(); i++){
JSONObject object = jsonArray.getJSONObject(i);
String name = object.getString("name").trim();
String email = object.getString("email").trim();
Toast.makeText(SignInActivity.this, "Success Login. \n Your Name : "+name+"\nYour Email : "+email,Toast.LENGTH_SHORT).show();
}
}
} catch (JSONException e) {
e.printStackTrace();
Toast.makeText(SignInActivity.this, "Error "+e.toString(),Toast.LENGTH_SHORT).show();
}
}
},
new Response.ErrorListener() {
#Override
public void onErrorResponse(VolleyError error) {
Toast.makeText(SignInActivity.this, "Error "+error.toString(),Toast.LENGTH_SHORT).show();
}
})
{
#Override
protected Map<String, String> getParams() throws AuthFailureError {
Map<String, String> params = new HashMap<>();
params.put("email",email);
params.put("password",password);
return params;
}
};
RequestQueue requestQueue = Volley.newRequestQueue(this);
requestQueue.add(stringRequest);
}
}
Partial answer:
First off
You are open to SQL injection. You should parameterize your query.
Parameterized queries in PHP with MySQL connection
Second
You can add the password to your query so you don't have to do a 2nd check, if you store the passed password in the DB, or you can hash your password first then use it in your query. That avoids getting more user data than necessary (with the associated possible leaking of data) and avoids needing a second method to find the correct user.
This is shown in the link above.
If you store a salt in the DB, I can understand why you need the 2nd method, but you might be able to salt the password in the SQL, via a SQL function. Since you don't include the code for password_verify, we have no way to know what you're actually doing there, so I'm keeping this as basic as I can. (My philosophy is to keep things simple until complications are required.)
Third
Even if you are getting all the columns in that table, specify the column names you need. You might end up adding to that table later, which would cause this query to pull more data than it needs, again.
Fourth
Since you already have the email, which is one of the parameters of the query, you don't need to get it from the DB.
FYI, the link above adds each parameter individually, but mysqli_stmt_bind_param can do them all in one shot.
Object oriented style
mysqli_stmt::bind_param ( string $types , mixed &$var1 [, mixed &$... ] ) : bool
Procedural style
mysqli_stmt_bind_param ( mysqli_stmt $stmt , string $types , mixed &$var1 [, mixed &$... ] ) : bool
...
types
A string that contains one or more characters which specify the types for the corresponding bind variables:
...
https://www.php.net/manual/en/mysqli-stmt.bind-param.php
$stmt = mysqli_prepare($dbc, "SELECT name, id FROM users WHERE email= ? AND password = ?");
mysqli_stmt_bind_param($stmt, "ss", $email, $password); // or use a hash from a method instead of $password
mysqli_stmt_execute($stmt);
$row = mysqli_stmt_fetch($stmt);
This should pull just the one user, unless it doesn't pull any users, so you should have a clear indication of whether this user has access to your site/data/whatever or not. I would suggest sending an actual success message that you can recognize as something a little more specific to you, rather than the generic message you have right now. I understand you're still in testing phase, so it's something to think about later, if you hadn't already.
I would also suggest sending an HTTP 401 message back if $row is null. That way it's 100% guaranteed that your client software understands what happened as well as not giving any specifics as to why it failed. You can still tell the user something more meaningful, such as "Email and Password Combination Not Recognized". Also, don't specify if the email or the password is wrong, since this can lead to easier brute force hacking. There's a lot of contention around this idea of prompts, so I'll let you do your own research and make up your mind about it.
Whether your Java code is correctly sending the login credentials to your PHP server, IDK. I'm rusty on that, so I'll let someone else chime in, and why I'm saying this is a partial answer. At least this answer should get your PHP on the right track.

access the .push key of firebase database for updating Profile info in android

I am developing an android app with Firebase, so saving data to Firebase with .push method and displaying them into list , i want to update the UserInfo stored in database but confused how i can access push method generated Key to update profile info , or any other way to setting profile info under the Authenticated user ID and read all this data so it will update on the list i am displaying.
or any other method to access this by User_id in child values?
myOnBtnClick code below
btn_register.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
if (Validation()) {
final String name = Field_fullName.getText().toString();
String phone = firebaseUser.getPhoneNumber();
String bg = field_bloodGroups.getSelectedItem().toString();
String DOB = Field_dateOfBirth.getText().toString();
String state = Field_state.getText().toString();
final String country = Field_country.getText().toString();
String city = Field_city.getText().toString();
UserSignUp userSignUp = new UserSignUp(name, phone, bg, DOB, state, country, city, firebaseUser.getUid());
DBref.child("DONORS").child(country).push().setValue(userSignUp).addOnCompleteListener(reg.this, new OnCompleteListener<Void>() {
#Override
public void onComplete(#NonNull Task<Void> task) {
if (task.isSuccessful()) {
Toast.makeText(reg.this, DBref.getKey() + "", Toast.LENGTH_SHORT).show();
Toast.makeText(reg.this, "User Created", Toast.LENGTH_SHORT).show();
editor = sharedPreference.edit();
editor.putInt("UserReg", 1);
editor.putString("UserCountry", country);
editor.putInt("FirstTimeRun", 1);
editor.apply();
startActivity(new Intent(reg.this, Main2Activity.class));
finish();
}
}
});
}
}
});
When you are using the push() method to generate that unique key, is the moment in which you can get and store the key like this:
String key = yourRef.getKey();
And to update a record please use the following line of code:
FirebaseDatabase.getInstance().getReference()
.child("Pakistan")
.child(key)
.child("user_ID")
.setValue("123456789");
Edit:
DatabaseReference keyRef = DBref.child("DONORS").child(country).push();
String key = keyRef.getKey();
Log("TAG", key);
keyRef.setValue(userSignUp).addOnCompleteListener(/* ... */);
Once you have this key, you can use it in other DatabaseReference. When you are using DBref.getKey() inside onComplete() method isn't getting the pushed key is just getting the key of your DBref.

Android : static String get Last Outgoing Call() method

I'd like to use the static String getLastOutgoingCall() method in order to pull the duration of the last outgoing phone call but I don't know how !
I'm a beginner with java programming (I usually program in c++)
The tutorials that I found use the ancient APIs and none of them use the method I'm talking about.
I hope I have not misinterpreted your question. If so, please let me know.
The method String getLastOutgoingCall (Context context) from android.provider.CallLog.Calls, according to the documentation, returns
The last phone number dialed (outgoing) or an empty string if none
exist yet.
So, you can't retrieve the last outgoing call duration using that method.
To get the last outgoing call duration, you can query the CallLog.Calls.CONTENT_URI to retrieve this info.
You can use a method like this:
public String getLastOutgoingCallDuration(final Context context) {
String output = null;
final Uri callog = CallLog.Calls.CONTENT_URI;
Cursor cursor = null;
try {
// Query all the columns of the records that matches "type=2"
// (outgoing) and orders the results by "date"
cursor = context.getContentResolver().query(callog, null,
CallLog.Calls.TYPE + "=" + CallLog.Calls.OUTGOING_TYPE,
null, CallLog.Calls.DATE);
final int durationCol = cursor
.getColumnIndex(CallLog.Calls.DURATION);
// Retrieve only the last record to get the last outgoing call
if (cursor.moveToLast()) {
// Retrieve only the duration column
output = cursor.getString(durationCol);
}
} finally {
// Close the resources
if (cursor != null) {
cursor.close();
}
}
return output;
}
Note: To perform this query you will need to add the following permission to your manifest:
<uses-permission android:name="android.permission.READ_CALL_LOG" />
Edit based on your own answer:
You need to call the getLastOutgoingCallDuration() on the onCreate() method of your Activity:
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main); // Here you need to set the name of your xml
TextView displayDuration;
displayDuration = (TextView) findViewById(R.id.textView2);
String duration = getLastOutgoingCallDuration(this);
displayDuration.setText(output + "sec");
}

How to store all keys from a specific value from SharedPreferences

In my android app, I have a custom listview of installed apps with a checkbox next to it. I am using SharedPreferences to store the boolean true for checked and false for unchecked. The key value is the packagename of the app and the value is a boolean, true or false.
I am trying to store all the keys (packagenames) with the value-- true, all together and so then I can use the packagenames in another class for a specific task. However, I want the data structure that stores all the keys to stay the same and hold all the checked packagename keys even when the app is killed.
Currently, I am using code like this:
String findKey(SharedPreferences sharedPreferences, String value) {
for (Map.Entry<String, ?> entry: sharedPreferences.getAll()) {
if (value.equals(entry.getValue())) {
return entry.getKey();
}
}
return null; // not found
}
I have tried researching but still unable to produce a solution.
Get all SharedPreferences names and all their keys?
Gather all Strings from SharedPreference getAll() Method?
How would I implement this correctly to get all my packagenames in a data structure that I can use in another class and have it stored with the same stuff even when the app is killed?
This is my code in my adapter class:
for(int i= 0; i<packageList.size(); i++){
PACKAGE_NAME = packageInfo.packageName;
sharedPrefs = context.getSharedPreferences(PACKAGE_NAME, Context.MODE_PRIVATE);
holder.ck1.setChecked(sharedPrefs.getBoolean(PACKAGE_NAME,false));
}
holder.ck1.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
SharedPreferences.Editor editor = context.getSharedPreferences(packageInfo.packageName, Context.MODE_PRIVATE).edit();
if (holder.ck1.isChecked()) {
itemChecked[position] = true;
holder.ck1.setChecked(true);
editor.putBoolean(packageInfo.packageName, true);
editor.apply();
} else {
itemChecked[position] = false;
holder.ck1.setChecked(false);
editor.putBoolean(packageInfo.packageName, false);
editor.apply();
}
}
});
Just extending from my comment.Here have a look.
final String CHECKBOX_DATA="CHECKBOX_DATA";
JSONObject js=new JSONObject();
js.put("package.name1", true);
js.put("package.name2", false);
js.put("package.name3", true);
js.put("package.name4", true);
SharePreferences prefs=context.getSharedPreferences(context.getPackageName(),Context.MODE_PRIVATE);
prefs.edit().putString(CHECKBOX_DATA, js.toString()).commit();
And then retrieve the same as
SharedPreferences prefs = context.getSharedPreferences(
context.getPackageName(), Context.MODE_PRIVATE);
String json=prefs.getString(CHECKBOX_DATA, null);
JSONObject jsobj=new JSONObject(json);
Iterator<String> iter = jsobj.keys();
while (iter.hasNext()) {
String key = iter.next();//This is your packagename
try {
boolean value = jsobj.getBoolean(key);
} catch (JSONException e) {
// Something went wrong!
}
}
Sorry, now I understand your question.
In Android >=3.0 (API 11), you can store package name array by putStringSet (String key, Set values)
In Android <3.0, you can combine all package name into one string, separate by "," because the package name cannot have ",".
For an example:
String allPackageName = "com.app1,com.app2,com.app3";
After that, save allPackageName in SharedPreference with a key:
SharedPreferences.Editor editor = sharedPref.edit();
editor.putString("key_app_checked", allPackageName );
editor.commit();
Get all package name and split to an String array:
String packageNameChecked = sharedPref.getString("allPackageName");
if(packageNameChecked !=null){
String [] arrPackageNameChecked = packageNameChecked.split(",");
//Do somethings with arrPackageNameChecked ...
}
According your post, i don't know what exactly what do you want. Because SharedPreferences save many value in xml file, so you can access it in every where in your app and it not lost when the app is killed.
I saw some issue when you use SharedPref:
When save value:
It must have editor.commit() after you change or store value.
I think your code store each value in one SharedPreference file. It NOT necessary. You should save all value in one file with difference key.
You should read this post, it will help you understand more about SharedPrefercence.

SharedPefs seeminly wiped even though I use them to auto login

I am trying to save to my apps shared preferences, I save the Username and password.
on successful login, these get stored fine. When I kill the app, then re-open it, it auto logs in as it should using the shared prefs.
however when I navigate to the account management activity and try access the prefs again the keys for the username and password can't be found and the default value is returned. I'm definetly using the right key values as it works perfectly fine when a manual login is required if there are no user/password prefs stored on first startup.
This really confuses me as the username and password keys clearly exist otherwise the it wouldn't auto-login.
Some code:
This is my account management activity:
public class AccManagement extends Activity
{
TextView textName;
TextView textEmail;
String SharedUsername;
String SharedPassword;
#Override
protected void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_acc_management);
textName = (TextView)findViewById(R.id.textviewName);
textEmail = (TextView)findViewById(R.id.textviewEmail);
//these return null, as if there are no shared prefs stored.
SharedUsername= SharedPrefsWrapper.getFromPrefs(this, "USERNAME", null);
SharedPassword= SharedPrefsWrapper.getFromPrefs(this, "PASSWORD", null);
}
I made a wrapper class for shared prefs which gets and puts key/value pairs into the shared prefs.
This is how I check if a user exists in my main activity:
public void Checker()
{
String SharedUsername= SharedPrefsWrapper.getFromPrefs(this, "USERNAME", null);
String SharedPassword= SharedPrefsWrapper.getFromPrefs(this, "PASSWORD", null);
if(SharedUsername== null || SharedPassword== null)
{
setContentView(R.layout.activity_main);
}
else
{
Login(url);
}
}
Login executes an http request and this method is called on completion:
public void onTaskCompleted(String data)
{
if(data.contains("name")) //a successful login will return a json string with "name".
{
Intent intent = new Intent(this, MenuActivity.class);
SharedPrefsWrapper.saveToPref(this, "USERNAME", textusername);
SharedPrefsWrapper.saveToPref(this, "PASSWORD", textpassword);
startActivity(intent);
}
}
On successful login the user is taken a menu which contains the account management button, and on click are taken to account management, which displays the username and password. Though this is where my problem occurs. It can't find the shared prefs I saved on login. It only happens when the app auto logs in using the shared prefs. If it's a first time login it seems to work fine and the shared prefs still seem to be there when I try get them from my account activity.
Thanks for any help
and sorry if the question simply doesn't make sense!
:)
EDITS:
SharedPrefs class methods:
public static void saveToPref(Context context, String key, String value)
{
SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(context);
final SharedPreferences.Editor editor = prefs.edit();
editor.putString(key, value);
editor.commit();
}
public static String getFromPrefs(Context context, String key, String defValue)
{
SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(context);
try
{
return prefs.getString(key, defValue);
}
catch(Exception ex)
{
return defValue;
}
}
When auto loging, textusername and textpassword are empty, so this wipes out your prefs.
Try to respect java naming conventions, your code is hard to read.

Categories