the data is submitted in firebase once in each run - android

I am inserting data into my firebase realtime database. I wrote a code for it. however, when i run the program, first thing it will insert and submit the data correctly, but when I move in the same run to other activity for example to login, and came back to insert other data, it will not insert it.
when I want to insert a data in my firebase, each time I must re-install the program and install it again and do it at the first,
Here is my code
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_fill_request_page);
firebaseAuth=FirebaseAuth.getInstance();
Title = (EditText) findViewById(R.id.Title);
Content = (EditText) findViewById(R.id.Content);
insert =(Button) findViewById(R.id.insert);
status=(EditText)findViewById(R.id.statustxt);
edittxtDate =(EditText) findViewById(R.id.edittxtDate);
edittxtTime =(EditText) findViewById(R.id.edittxtTime);
edittxtExpDate=(EditText) findViewById(R.id.edittxtExpDate);
imagebtnDate = (ImageButton) findViewById(R.id.imagebtnDate);
imagebtnTime = (ImageButton) findViewById(R.id.imagebtnTime);
imagebtnExpDate=(ImageButton) findViewById(R.id.imagebtnExpDate);
location = (Spinner) findViewById(R.id.location);
typeof=(Spinner)findViewById(R.id.typeof);
database = FirebaseDatabase.getInstance();
ref1 = database.getReference("requests");
insert.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
btnInsert1();
}
});
private void getValues(){
request1.setTitle(Title.getText().toString());
request1.setContent(Content.getText().toString());
request1.setDate(edittxtDate.getText().toString());
request1.setTime(edittxtTime.getText().toString());
request1.setLocation(location.getSelectedItem().toString());
request1.setTypeof(typeof.getSelectedItem().toString());
request1.setExpDate(edittxtExpDate.getText().toString());
request1.setStatus(status.getText().toString());
}
private void btnInsert1(){
database = FirebaseDatabase.getInstance();
ref1 = database.getReference("requests");
DatabaseReference ref2=ref1.push();
String id=ref2.getKey();
request1 =new requests();
getValues();
ref1.child(id).setValue(request1);
Toast.makeText(FillRequestPage.this,"Data inserted....",Toast.LENGTH_SHORT).show();
}

my problem was from the firebase its self, the access is denied , I just edited the Rules So the user can read and write to my database and it works!

Related

Room query that should return LiveData always returns NULL

I want to create a login screen in android using Room/SQLLite.
Once my login activity is launched, a user object will be inserted in the database.
When pressing on the login button, I want to look for the user by the username I filled in.
Then I will check if the password that I gave in, is the correct password.
Based on that I will go to another activity or I will show an error message.
But this is going wrong, the next code is always returning NULL, so I will always end up showing the error message.
UserWithWorkorders userWithWorkorders = ie4ViewModel.getUserWithWorkorders(username.getText().toString()).getValue();
Here is the query in the UserDao. As you can see it returns LiveDate.
#Query("SELECT * FROM User WHERE username =:username")
LiveData<UserWithWorkorders> getUserWithWorkorders(String username);
Here is the onCreate() of my Login activity:
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_login);
IE4ViewModel ie4ViewModel = new ViewModelProvider(this).get(IE4ViewModel.class);
User user = new User("John", "Doe", "john", "doe");
ie4ViewModel.insertUser(user);
final Button loginButton = findViewById(R.id.loginButton);
final EditText username = findViewById(R.id.username);
final EditText password = findViewById(R.id.password);
final TextView errorMessage = findViewById(R.id.errorMessage);
loginButton.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
UserWithWorkorders userWithWorkorders = ie4ViewModel.getUserWithWorkorders(username.getText().toString()).getValue();
if (userWithWorkorders != null) {
if(userWithWorkorders.user.getPassword().equals(password.getText().toString())){
Intent i = new Intent(LoginActivity.this, WorkordersActivity.class);
i.putExtra("userObject", userWithWorkorders);
startActivity(i);
}
else {
errorMessage.setVisibility(View.VISIBLE);
}
}
else {
errorMessage.setVisibility(View.VISIBLE);
}
}
});
ie4ViewModel.getUsersWithWorkorders().observe(this, new Observer<List<UserWithWorkorders>>() {
#Override
public void onChanged(List<UserWithWorkorders> usersWithWorkorders) {
if (usersWithWorkorders != null && usersWithWorkorders.size() > 0) {
new Handler(Looper.getMainLooper()).post(new Runnable() {
#Override
public void run() {
}
});
}
}
});
}
What am I doing wrong? If there is any other code, you'd like to see, please let me know.
Or in other words: how do I retrieve an object in my android activity from a SQLLite database using Room if the Dao query is returning a LiveData object?
For this line of code, you dont need to make it return observable.
UserWithWorkorders userWithWorkorders = ie4ViewModel.getUserWithWorkorders(username.getText().toString()).getValue();
simply declare a method in your viewmodel like that.
public UserWithWorkorders getUserWithWorkorders(String value){
//get result from DAO.
}
Also make your DAO method return UserWithWorkorders
Now call this method in your activity as you are already doing it.
UserWithWorkorders userWithWorkorders = ie4ViewModel.getUserWithWorkorders(username.getText().toString()).getValue();
Be fully sure that your database has some data to return.

How to check for string changes after a user presses a Button?

This question is hard to word, but explaining is easy.
I have an Activity, where a user can modify their origin and personal description.
Once all changes are made, they press the "done" Button.
Now I want to know the most optimal way of checking if the strings they entered is novel and not equal to the previous description and origin.
Because... what if they only change description, and not origin, vice versa, or they change both?
Not sure the most optimal way of doing it.
Here is my current Activity.
public class EditProfile extends AppCompatActivity
{
private TextView originTV;
private EditText descriptionET;
private ImageView cameraIV, mainIV;
private Button doneButton;
private static final String EDIT_PROFILE = "EDIT_PROFILE";
private UpdateUserString updateUserString;
private int PLACE_AUTOCOMPLETE_REQUEST_CODE = 20;
private User localActivityUser;
#Override
protected void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_16e_profile_edit);
bindActivity();
}
private void bindActivity()
{
localActivityUser = Global_Class.getInstance().getValue().user;
originTV = (TextView) findViewById(R.id.editProfile_originTV);
descriptionET = (EditText) findViewById(R.id.editProfile_descriptionET);
cameraIV = (ImageView) findViewById(R.id.editProfile_cameraIV);
mainIV = (ImageView) findViewById(R.id.editProfile_imageIV);
doneButton = (Button) findViewById(R.id.editProfile_doneButton);
doneButton.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
if(!localActivityUser.getDescription().equals(descriptionET.getText().toString()))
{
//Call api to update my backend.
UpdateUserStringAsyncTask updateUserStringAsyncTask = new UpdateUserStringAsyncTask("description",descriptionET.getText().toString());
updateUserStringAsyncTask.execute();
}
else if(!localActivityUser.getOrigin().equals(originTV.getText()))
{
//Call api to update my backend
UpdateUserStringAsyncTask updateUserStringAsyncTask = new UpdateUserStringAsyncTask("origin",originTV.getText().toString());
updateUserStringAsyncTask.execute();
}
}
});
}
The most optimal way would be not to care about checking every combination of valid changes, and send the whole user object to the API. Multiple network requests is bad on your device's resources. Let the database handle updating the data, even if it is the same. That isn't a problem for your app.
doneButton.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
// These two could be in a TextWatcher instead
localActivityUser.setDescription(
descriptionET.getText().toString());
localActivityUser.setOrigin(
originTV.getText().toString());
UpdateUserStringAsyncTask task = new UpdateUserStringAsyncTask(localActivityUser);
task.execute();
}
});
You could also look into Android Data Binding library so that you don't need to worry about maintaining the state of the User class yourself.

I'm having a small issue using .push() to store data under key without replacing the childs

So I'm trying to generate a new push key and save the 2 children under it on each button click...however, Every time I submit my requests it either replaces the key or does not change anything if the data entered in my edit text is the same as it was initially entered here is my code.
DatabaseReference reference = FirebaseDatabase.getInstance().getReference().push();
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_home);
tvStoreName = (TextView) findViewById(R.id.tvStoreName);
tvStoreName.setText(getIntent().getExtras().getString("Email"));
etDestination= (EditText) findViewById(R.id.etDestination);
bAddNew = (Button) findViewById(R.id.bAddNew);
bAddNew.setOnClickListener(new View.OnClickListener(){
#Override
public void onClick(View view){
Toast.makeText(Home.this, "Request Sent", Toast.LENGTH_LONG).show();
String value1 = tvStoreName.getText().toString();
String value3 = etDestination.getText().toString();
reference.child("StoreEmail").setValue(value1);
reference.child("Destination").setValue(value3);
}
});
}}
Every time I submit my requests it either replaces the key or does not change anything
It is correct.
Since you are using:
reference.child("StoreEmail").setValue(value1);
You can check the official doc:
Using setValue() in this way overwrites data at the specified location, including any child nodes.
If you want to update data you have to use the updateChildren() method.
You have to call push().getKey() on a DatabaseReference to get the key. If you want to save both data under same pushkey in different location, the following code will do that. But when you're updating data in multiple locations, it's always recommended to do that in one call with updateChildren() method.
DatabaseReference reference = FirebaseDatabase.getInstance().getReference().push();
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_home);
tvStoreName = (TextView) findViewById(R.id.tvStoreName);
tvStoreName.setText(getIntent().getExtras().getString("Email"));
etDestination= (EditText) findViewById(R.id.etDestination);
bAddNew = (Button) findViewById(R.id.bAddNew);
bAddNew.setOnClickListener(new View.OnClickListener(){
#Override
public void onClick(View view){
Toast.makeText(Home.this, "Request Sent", Toast.LENGTH_LONG).show();
String value1 = tvStoreName.getText().toString();
String value3 = etDestination.getText().toString();
String key = reference.push().getKey();
reference.child("StoreEmail").child(key).setValue(value1);
reference.child("Destination").child(key).setValue(value3);
}
});
}}
Long story short
If you want to set value1 into this path your-db-name\StoreEmail, then you should change reference init like this:
DatabaseReference reference = FirebaseDatabase.getInstance().getReference();
Hope this helps
The description
I just realize that reference object is result of ...push() method. That makes every time you wrote
reference.setValue(yourValueHere);
it execute:
FirebaseDatabase.getInstance().getReference().push().setValue(yourValueHere);
Please note that getReference().push() will make one new random child uid in your database (like your-db-name/-K83298jsdal. So it makes your code, that looks like this:
reference.child("StoreEmail").setValue(value1);
will actually save new value (value1) at your-db-name/-K83298jsdal/StoreEmail
I was able to get it to work !! the issue was caused because I did not include this..
finish();
startActivity(getIntent());
to the bottom of my OnClickListener but I do have to say you guys are awesome !!

RecyclerView don't show inserted SQLite data instantly

When the user from a FragmentDialog type his data into the edittexts and press the save button, the data should instantly show in the recyclerView, but that dosn't happend. To get/show the latest data, you have to restart the app
I have used a temporary solution where I pass data from the FragmentDialog to the mainActivity via a interface and then I directly pass that data into the arraylist for the recyclerView. This work, but dosn't look like a propor solution. I wish a "correct" way to do it
I have also tried to set adapter.notifyDataSetChanged(); different places without any succses
DialogFragment class where the user type his data and is then insertet to SQLite database
public class DialogAdd extends DialogFragment {
#Nullable
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
final View rootView = inflater.inflate(R.layout.add_productdialog,container, false);
name = (EditText) rootView.findViewById(R.id.dialog_productname);
quantity = (EditText) rootView.findViewById(R.id.dialog_qantity);
location = (EditText) rootView.findViewById(R.id.dialog_location);
normalPrice = (EditText) rootView.findViewById(R.id.dialog_normalPrice);
offerPrice = (EditText) rootView.findViewById(R.id.dialog_offerPrice);
okButton = (Button) rootView.findViewById(R.id.dialog_okButton);
okButton.getBackground().setColorFilter(Color.parseColor("#2fbd4b"), PorterDuff.Mode.MULTIPLY);
okButton.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
if (name.getText().toString().isEmpty()) {
Toast.makeText(context, "You must add a name", Toast.LENGTH_LONG).show();
} else {
DialogAddListener addListener = (DialogAddListener) getActivity();
dbHelper.insertData(name.getText().toString(), quantity.getText().toString(), location.getText().toString(), normalPrice.getText().toString(), offerPrice.getText().toString());
addListener.getDialogData(name.getText().toString(), quantity.getText().toString(), location.getText().toString(), normalPrice.getText().toString(), offerPrice.getText().toString());
getDialog().dismiss();
}
}
});
return rootView;
}
The mainActivity class that instantiate the recyclerview,sqlite and adapters.
public class MainActivity extends AppCompatActivity implements DialogAdd.DialogAddListener{
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.shoppinglist_mainactivity);
databaseHelper = new DatabaseHelper(this);
addbutton = (ImageButton) findViewById(R.id.addbtn);
addbutton.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
dialogAdd = new DialogAdd();
dialogAdd.show(getSupportFragmentManager(), "addDialog");
}
});
//RecyclerView
recyclerView = (RecyclerView)findViewById(R.id.rv_shoppinglist);
LinearLayoutManager linearLayoutManager = new LinearLayoutManager(App.getAppContex());
linearLayoutManager.setOrientation(LinearLayoutManager.VERTICAL);
recyclerView.setLayoutManager(linearLayoutManager);
initializeData();
adapter = new ShoplistAdapter(shopListItems);
recyclerView.setAdapter(adapter);
adapter.notifyDataSetChanged();
}
private void initializeData(){
shopListItems = new ArrayList<>();
resultset = databaseHelper.getAllData();
if (resultset.moveToFirst()){
while(!resultset.isAfterLast()){
shopListItems.add(new ShopListItem(resultset.getString(1), resultset.getString(2), resultset.getString(3), resultset.getString(4), resultset.getString(5)));
resultset.moveToNext();
totalPrice.setText("Total cost: $" + "26");
totalItems.setText("Total items: " + resultset.getCount());
}
}
resultset.close();
}
//This is only used to show the data instantly
#Override
public void getDialogData(String name, String qty, String location, String price1, String price2) {
shopListItems.add(new ShopListItem(name, qty, location, price1, price2));
}
}
You should use a CursorLoader which automatically listens for changes in Uri. And notify changes via contentResolver.notifyChanged(uriOfInsertedData). The beast way is to use a ContentProvider to make all thins thing work appropriately.
Or for an easier way, register an Observer in a singleton for your database and notify it upon changing. In general this will do the same and you will not have any relations between components. It takes some code to post so I hope you will figure it out.
Update 2016-03-09, based on your comment
If you implemented example 1, it doesn't tell you how to monitor for changes. There is no existing mechanism for this case.
The best approach to implement this mechanism is to use an Observer pattern.
I would go with a singleton that hosts Observers.
You can extend Observable (which already has logic for storing a list of Observers, notifying and removing them) and make a singleton of it.
Register Observer by calling addObserver() wherever you need to listen to (don't forget to call deleteObserver() to avoid Activity leaks).
Now, whenever you call insert or modify a database in any way, make sure to call notifyObservers("tablename") of Observable singleton.
This way all observers will get notified the table was modified (passing a table name is an example, you can use any Object there to inform your components about the change)
Then in update() of your Observer, check if the table you wish to monitor is updated, if so, reload the data as you normally would do.

Pass the textvalue between two xml

I have a "Login" xml in layout. And I have another xml is the "List".
In my Application, the user login into the application with e-mail address and password than show their mail list. I did it like that:
public void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
// setContentView(R.layout.main);
LoginScreen();
}
// I am receiving the email and password on the main layout for login page
public void LoginScreen()
{
setContentView(R.layout.main);
EditText emailTxt = (EditText) findViewById(R.id.txtMail);
EditText passwordTxt = (EditText) findViewById(R.id.txtPassword);
String email= epostaTxt.getText().toString();
String password = parolaTxt.getText().toString();
// After receive, call the MailList() for connection and getting the list
MailList()
}
// and I use this email and password again into the MailList() for connection with server then receive the mail list
public void MailList()
{
setContentView(R.layout.list);
EditText emailTxt = (EditText) findViewById(R.id.txtMail);
EditText passwordTxt = (EditText) findViewById(R.id.txtPassword);
String email= epostaTxt.getText().toString();
String password = parolaTxt.getText().toString();
Sending emain and password to the server etc...
}
This just for now but this code repeat will be continue . I want to get this email and password from Edittxt just one time and use it all the methods. And this code doesn't work also, Maillist doesn't show the list because cannot connect
How can I do that?
If I unterstand it well, you simply want to pass data between your Activities, here might be some help : In Android: How do I get variables/data from one screen to another?
EDIT: My new answer, hope it's the good one:
Simply create two variables to store the date?
public class LoginScreen extends Activity{
private String email;
private String password;
public void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
// setContentView(R.layout.main);
LoginScreen();
}
// I am receiving the email and password on the main layout for login page
public void LoginScreen()
{
setContentView(R.layout.main);
EditText emailTxt = (EditText) findViewById(R.id.txtMail);
EditText passwordTxt = (EditText) findViewById(R.id.txtPassword);
email= emailTxt.getText().toString();
password = passwordTxt.getText().toString();
// After receive, call the MailList() for connection and getting the list
MailList()
}
// and I use this email and password again into the MailList() for connection with server then receive the mail list
public void MailList()
{
setContentView(R.layout.list);
//Sending emain and password to the server etc...
//just use the email and password stored above
yourFunctionToSend(email,password);
}
}

Categories

Resources