Related
I am trying to implement a ViewModel architecture for a RecyclerView in AndroidX, following the example as stated in enter link description here and enter link description here. Items in the recyclerView get selected on position clicked, but for some reason, the selected item de-select and revert to default after the device is rotated and configuration changed. I know there have been answers for questions like this in the past, but all I have seen are either not directly applicable in my case or are simply for deprecated cases.
CAN SOMEONE PLEASE TELL ME WHAT I AM DOING WRONG!
Below are snippets from my Code:
Dependencies added
dependencies {
def lifecycle_version = "2.2.0"
// ViewModel
implementation "androidx.lifecycle:lifecycle-viewmodel:$lifecycle_version"
// LiveData
implementation "androidx.lifecycle:lifecycle-livedata:$lifecycle_version"
// Saved state module for ViewModel
implementation "androidx.lifecycle:lifecycle-viewmodel-savedstate:$lifecycle_version"
// Annotation processor
annotationProcessor "androidx.lifecycle:lifecycle-compiler:$lifecycle_version"
implementation 'androidx.hilt:hilt-lifecycle-viewmodel:1.0.0-alpha02'
}
Repository Class:
public class TopicRepository {
private Application application;
private SharedPreferences sharedPreferences;
private ArrayList<RootTopic> topicGroupList;
private MutableLiveData<ArrayList<RootTopic>>topicGroupMLD;
public TopicRepository(Application application) {
this.application = application;
}
public LiveData<ArrayList<RootTopic>> getRootTopicLD(String subject){
if (topicGroupMLD == null){
topicGroupMLD = new MutableLiveData<ArrayList<RootTopic>>();
generateTopicGroup(subject);
}
return topicGroupMLD;
}
private void generateTopicGroup(final String subject){
Log.d(TAG, "generateTopicGroup: CALLED");
isRequestingMLD.postValue(true);
final String subjectTopicGroupList = subject + "TopicGroupList";
sharedPreferences = application.getSharedPreferences(AppConstant.Constants.PACKAGE_NAME, Context.MODE_PRIVATE);
String serializedTopicGroup = sharedPreferences.getString(subjectTopicGroupList, null);
if (serializedTopicGroup != null){
Gson gson = new Gson();
Type type = new TypeToken<ArrayList<RootTopic>>(){}.getType();
topicGroupList = gson.fromJson(serializedTopicGroup, type);
topicGroupMLD.postValue(topicGroupList);
}else {// - Not saved in SP
Log.d(TAG, "getTopicGroup: NOT IN SP");
new ActiveConnectionCheck(new ActiveConnectionCheck.Consumer() {
#Override
public void accept(Boolean internet) {
Log.d(TAG, "accept: CHECKED INTERNET");
if (internet){
Log.d(TAG, "accept: INTERNET CONNECTION = TRUE");
internetCheckMLD.postValue(AppConstant.Constants.IS_INTERNET_REQUEST_SUCCESS);
FirebaseFirestore fbFStore = FirebaseFirestore.getInstance();
CollectionReference lectureRef = fbFStore.collection(subject);
lectureRef.orderBy(AppConstant.Constants.POSITION, Query.Direction.ASCENDING)
.get().addOnSuccessListener(
new OnSuccessListener<QuerySnapshot>() {
#Override
public void onSuccess(QuerySnapshot queryDocumentSnapshots) {
ArrayList<Topic>topicList = new ArrayList<>();
ArrayList<String> rootTitleList = new ArrayList<>();
for (QueryDocumentSnapshot snapshot : queryDocumentSnapshots){
Topic topic = snapshot.toObject(Topic.class);
topicList.add(topic);
}
Log.d(TAG, "onSuccess: TopicListSize = " + topicList.size());
for (Topic topic : topicList){
String rootTopicString = topic.getRootTopic();
if (!rootTitleList.contains(rootTopicString)){
rootTitleList.add(rootTopicString);
}
}
Log.d(TAG, "onSuccess: RootTitleListSize = " + rootTitleList.size());
for (int x = 0; x < rootTitleList.size(); x ++){
RootTopic rootTopic = new RootTopic(rootTitleList.get(x), new ArrayList<Topic>());
topicGroupList = new ArrayList<>();
topicGroupList.add(rootTopic);
}
for (int e = 0; e < topicList.size(); e++){
addTopicToGroup(topicGroupList, topicList.get(e));
}
topicGroupMLD.postValue(topicGroupList);
Gson gson = new Gson();
String serializedTopicGroup = gson.toJson(topicGroupList);
sharedPreferences.edit().putString(subjectTopicGroupList, serializedTopicGroup).apply();
Log.d(TAG, "onSuccess: TOPICGROUPSIZE = " + topicGroupList.size());
Log.d(TAG, "onSuccess: SERIALIZED GROUP = " + serializedTopicGroup);
isRequestingMLD.postValue(false);
}
}
).addOnFailureListener(
new OnFailureListener() {
#Override
public void onFailure(#NonNull Exception e) {
isRequestingMLD.postValue(false);
Log.d(TAG, "onFailure: FAILED TO GET TOPICLIST e = " + e.toString());
}
}
);
}else {
internetCheckMLD.postValue(AppConstant.Constants.IS_INTERNET_REQUEST_FAIL);
Log.d(TAG, "accept: InternetCONECTION = " + false);
}
}
});
}
}
private void addTopicToGroup(ArrayList<RootTopic>rootGroup, Topic topic){
for (int x = 0; x < rootGroup.size(); x++){
RootTopic rootTopic = rootGroup.get(x);
if (rootTopic.getRootTopicName().equals(topic.getRootTopic())){
rootTopic.getTopicGroup().add(topic);
}
}
}
}
My ViewModel class
public class LectureViewModel extends AndroidViewModel {
public static final String TAG = AppConstant.Constants.GEN_TAG + ":LectureVM";
private Application application;
private TopicRepository topicRepository;
private ArrayList<RootTopic> topicGroupList;
public LectureViewModel(#NonNull Application application) {
super(application);
this.application = application;
topicRepository = new TopicRepository(application);
}
public LiveData<ArrayList<RootTopic>> getRootTopicListLD(String subject){
return topicRepository.getRootTopicLD(subject);
}
}
Activity Implementing ViewModel
public class LectureRoomActivity extends AppCompatActivity {
public static final String TAG = AppConstant.Constants.GEN_TAG + " LecRoom";
private LectureViewModel lectureRoomVM;
private String subject;
private RecyclerView mainRecyclerView;
private RootTopicAdapter rootTopicAdapter;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_lecture_room);
Intent intent = getIntent();
subject = intent.getStringExtra(AppConstant.Constants.SUBJECT);
mainRecyclerView = findViewById(R.id.recyclerView);
downloadVM = new ViewModelProvider(this).get(DownloadLectureViewModel.class);
lectureRoomVM = new ViewModelProvider(this).get(LectureViewModel.class);
lectureRoomVM.getRootTopicListLD(subject).observe(
this,
new Observer<ArrayList<RootTopic>>() {
#Override
public void onChanged(ArrayList<RootTopic> rootTopics) {
if (rootTopics != null){
currentTopic = lectureRoomVM.getCursorTopic(subject, rootTopics);
setUpRec(rootTopics, currentTopic);
}
}
});
}
private void setUpRec( ArrayList<RootTopic>topicGroup, CursorTopic currentTopic){
rootTopicAdapter = new RootTopicAdapter(topicGroup,
new ArrayList<String>(), currentTopic.getParentPosition(),
currentTopic.getCursorPosition());
LinearLayoutManager linearLayoutManager = new LinearLayoutManager(
this, RecyclerView.VERTICAL,false);
mainRecyclerView.setHasFixedSize(true);
mainRecyclerView.setLayoutManager(linearLayoutManager);
mainRecyclerView.setAdapter(rootTopicAdapter);
Log.d(TAG, "setUpRec: SETTING REC");
}
}
For saving and restoring UI related data you better use savedInstanceState Bundle to survive the last state. To achive this you simply override two methods in you UI activity. See the sample code snippet below.
In your RootTopicAdapter
// Add this where you detect the item click, probably in your adaptor class
private int lastRecyclerViewIndex; // define the variable to hold the last index
...
#Override
public void onClick(View v) {
lastRecyclerViewIndex = getLayoutPosition();
}
public int getLastIndex() {
return lastRecyclerViewIndex;
}
In your view model class
public class LectureViewModel extends AndroidViewModel {
public static final String TAG = AppConstant.Constants.GEN_TAG + ":LectureVM";
private Application application;
private TopicRepository topicRepository;
private ArrayList<RootTopic> topicGroupList;
public boolean mustRestore; // Is there any data to restore
public int lasIndexSelected;
public LectureViewModel(#NonNull Application application) {
super(application);
this.application = application;
topicRepository = new TopicRepository(application);
}
public LiveData<ArrayList<RootTopic>> getRootTopicListLD(String subject){
return topicRepository.getRootTopicLD(subject);
}
}
In you UI activity which uses the RecyclerView
public class LectureRoomActivity extends AppCompatActivity {
...
private LectureViewModel lectureRoomVM;
...
private RecyclerView mainRecyclerView;
private RootTopicAdapter rootTopicAdapter;
...
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_lecture_room);
Intent intent = getIntent();
subject = intent.getStringExtra(AppConstant.Constants.SUBJECT);
mainRecyclerView = findViewById(R.id.recyclerView);
downloadVM = new ViewModelProvider(this).get(DownloadLectureViewModel.class);
lectureRoomVM = new ViewModelProvider(this).get(LectureViewModel.class);
lectureRoomVM.getRootTopicListLD(subject).observe(
this,
new Observer<ArrayList<RootTopic>>() {
#Override
public void onChanged(ArrayList<RootTopic> rootTopics) {
if (rootTopics != null){
currentTopic = lectureRoomVM.getCursorTopic(subject, rootTopics);
setUpRec(rootTopics, currentTopic);
// Exactly here, after setting up the data get your index for example
if(lectureRoomVM.mustRestore){
// Check the item count in the adaptor to avoid crashes
if(mainRecyclerView.getAdapter().getItemCount >= lastRecyclerViewIndex){
mainRecyclerView.findViewHolderForAdapterPosition(lastRecyclerViewIndex).itemView.performClick();
}
// After the restoration set the mustRestore to false
lectureRoomVM.mustRestore = false;
}
}
}
});
}
#Override
protected void onDestroy() {
super.onDestroy();
Log.d(E, "onDestroy");
/*
* Here just set the mustRestore to true in order to be able to restore in onCreate method.
* If the application itself is not destroyed your data will still be live in the
* memory thanks to the ViewModel's life cycle awarness.
*/
lectureRoomVM.mustRestore = true;
}
}
There you go. Try this logic carefully without bugs. Then I think you will achive what you want to get.
This question already has answers here:
What is a NullPointerException, and how do I fix it?
(12 answers)
Closed 3 years ago.
I have faced a problem which are I attempt to invoke the null object reference but Im follow the video of Instagram Clone exactly, the video can done it without problem, but I get the problem, i had try so hard to find out the problem for an hour but I still didnt have any idea and I really tried all the solutions you proposed but it does not work for me.
here are the problem :
java.lang.NullPointerException: Attempt to invoke virtual method 'java.lang.String com.fivenine.shareit2.models.UserAccountSettings.getProfile_photo()' on a null object reference
at com.fivenine.shareit2.ViewPostFragment.setupWidgets(ViewPostFragment.java:134)
at com.fivenine.shareit2.ViewPostFragment.onCreateView(ViewPostFragment.java:98)
at android.support.v4.app.Fragment.performCreateView(Fragment.java:2439)
at android.support.v4.app.FragmentManagerImpl.moveToState(FragmentManager.java:1460)
at android.support.v4.app.FragmentManagerImpl.moveFragmentToExpectedState(FragmentManager.java:1784)
at android.support.v4.app.FragmentManagerImpl.moveToState(FragmentManager.java:1852)
at android.support.v4.app.BackStackRecord.executeOps(BackStackRecord.java:802)
at android.support.v4.app.FragmentManagerImpl.executeOps(FragmentManager.java:2625)
at android.support.v4.app.FragmentManagerImpl.executeOpsTogether(FragmentManager.java:2411)
at android.support.v4.app.FragmentManagerImpl.removeRedundantOperationsAndExecute(FragmentManager.java:2366)
at android.support.v4.app.FragmentManagerImpl.execPendingActions(FragmentManager.java:2273)
at android.support.v4.app.FragmentManagerImpl$1.run(FragmentManager.java:733)
at android.os.Handler.handleCallback(Handler.java:754)
at android.os.Handler.dispatchMessage(Handler.java:95)
at android.os.Looper.loop(Looper.java:165)
at android.app.ActivityThread.main(ActivityThread.java:6375)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:912)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:802)
Here are the code for UserAccountSettings:
public class UserAccountSettings {
private String description;
private String display_name;
private long followers;
private long following;
private long posts;
private String profile_photo;
private String username;
private String website;
private String user_id;
public UserAccountSettings(String description, String display_name, long followers, long following, long posts, String profile_photo, String username, String website, String user_id) {
this.description = description;
this.display_name = display_name;
this.followers = followers;
this.following = following;
this.posts = posts;
this.profile_photo = profile_photo;
this.username = username;
this.website = website;
this.user_id = user_id;
}
public UserAccountSettings() {
}
public String getUser_id() {
return user_id;
}
public void setUser_id(String user_id) {
this.user_id = user_id;
}
public String getDescription() {
return description;
}
public void setDescription(String description) {
this.description = description;
}
public String getDisplay_name() {
return display_name;
}
public void setDisplay_name(String display_name) {
this.display_name = display_name;
}
public long getFollowers() {
return followers;
}
public void setFollowers(long followers) {
this.followers = followers;
}
public long getFollowing() {
return following;
}
public void setFollowing(long following) {
this.following = following;
}
public long getPosts() {
return posts;
}
public void setPosts(long posts) {
this.posts = posts;
}
public String getProfile_photo() {
return profile_photo;
}
public void setProfile_photo(String profile_photo) {
this.profile_photo = profile_photo;
}
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
public String getWebsite() {
return website;
}
public void setWebsite(String website) {
this.website = website;
}
#Override
public String toString() {
return "UserAccountSettings{" +
"description='" + description + '\'' +
", display_name='" + display_name + '\'' +
", followers=" + followers +
", following=" + following +
", posts=" + posts +
", profile_photo='" + profile_photo + '\'' +
", username='" + username + '\'' +
", website='" + website + '\'' +
", user_id='" + user_id + '\'' +
'}';
}
}
and then it point out to the problem in ViewPostFragment, here are the code:
public class ViewPostFragment extends Fragment {
private static final String TAG = "ViewPostFragment";
public ViewPostFragment(){
super();
setArguments(new Bundle());
}
//firebase
private FirebaseAuth mAuth;
private FirebaseAuth.AuthStateListener mAuthListener;
private FirebaseDatabase mFirebaseDatabase;
private DatabaseReference myRef;
private FirebaseMethods mFirebaseMethods;
//widgets
private SquareImageView mPostImage;
private BottomNavigationViewEx bottomNavigationView;
private TextView mBackLabel, mCaption, mUsername, mTimestamp;
private ImageView mBackArrow, mEllipses, mHeartRed, mHeartWhite, mProfileImage;
//vars
private Photo mPhoto;
private int mActivityNumber = 0;
private String photoUsername = "";
private String profilePhotoUrl = "";
private UserAccountSettings mUserAccountSettings;
#Nullable
#Override
public View onCreateView(LayoutInflater inflater, #Nullable ViewGroup container, #Nullable Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.fragment_view_post, container, false);
mPostImage = (SquareImageView) view.findViewById(R.id.post_image);
bottomNavigationView = (BottomNavigationViewEx) view.findViewById(R.id.bottomNavViewBar);
mBackArrow = (ImageView) view.findViewById(R.id.backArrow);
mBackLabel = (TextView) view.findViewById(R.id.tvBackLabel);
mCaption = (TextView) view.findViewById(R.id.image_caption);
mUsername = (TextView) view.findViewById(R.id.username);
mTimestamp = (TextView) view.findViewById(R.id.image_time_posted);
mEllipses = (ImageView) view.findViewById(R.id.ivEllipses);
mHeartRed = (ImageView) view.findViewById(R.id.image_heart_red);
mHeartWhite = (ImageView) view.findViewById(R.id.image_heart);
mProfileImage = (ImageView) view.findViewById(R.id.profile_photo);
try{
mPhoto = getPhotoFromBundle();
UniversalImageLoader.setImage(mPhoto.getImage_path(), mPostImage, null, "");
mActivityNumber = getActivityNumFromBundle();
}catch (NullPointerException e){
Log.e(TAG, "onCreateView: NullPointerException: " + e.getMessage() );
}
setupFirebaseAuth();
setupBottomNavigationView();
getPhotoDetails();
setupWidgets();
return view;
}
private void getPhotoDetails(){
Log.d(TAG, "getPhotoDetails: retrieving photo details.");
DatabaseReference reference = FirebaseDatabase.getInstance().getReference();
Query query = reference
.child(getString(R.string.dbname_user_account_settings))
.orderByChild(getString(R.string.field_user_id))
.equalTo(mPhoto.getUser_id());
query.addListenerForSingleValueEvent(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
for ( DataSnapshot singleSnapshot : dataSnapshot.getChildren()){
mUserAccountSettings = singleSnapshot.getValue(UserAccountSettings.class);
}
//setupWidgets();
}
#Override
public void onCancelled(DatabaseError databaseError) {
Log.d(TAG, "onCancelled: query cancelled.");
}
});
}
private void setupWidgets() {
String timestampDiff = getTimestampDifference();
if (!timestampDiff.equals("0")) {
mTimestamp.setText(timestampDiff + " DAYS AGO");
} else {
mTimestamp.setText("TODAY");
}
UniversalImageLoader.setImage(mUserAccountSettings.getProfile_photo(), mProfileImage, null, "");
mUsername.setText(mUserAccountSettings.getUsername());
}
/**
* Returns a string representing the number of days ago the post was made
* #return
*/
private String getTimestampDifference(){
Log.d(TAG, "getTimestampDifference: getting timestamp difference.");
String difference = "";
Calendar c = Calendar.getInstance();
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss'Z'", Locale.CANADA);
sdf.setTimeZone(TimeZone.getTimeZone("Canada/Pacific"));//google 'android list of timezones'
Date today = c.getTime();
sdf.format(today);
Date timestamp;
final String photoTimestamp = mPhoto.getDate_created();
try{
timestamp = sdf.parse(photoTimestamp);
difference = String.valueOf(Math.round(((today.getTime() - timestamp.getTime()) / 1000 / 60 / 60 / 24 )));
}catch (ParseException e){
Log.e(TAG, "getTimestampDifference: ParseException: " + e.getMessage() );
difference = "0";
}
return difference;
}
/**
* retrieve the activity number from the incoming bundle from profileActivity interface
* #return
*/
private int getActivityNumFromBundle(){
Log.d(TAG, "getActivityNumFromBundle: arguments: " + getArguments());
Bundle bundle = this.getArguments();
if(bundle != null) {
return bundle.getInt(getString(R.string.activity_number));
}else{
return 0;
}
}
/**
* retrieve the photo from the incoming bundle from profileActivity interface
* #return
*/
private Photo getPhotoFromBundle(){
Log.d(TAG, "getPhotoFromBundle: arguments: " + getArguments());
Bundle bundle = this.getArguments();
if(bundle != null) {
return bundle.getParcelable(getString(R.string.photo));
}else{
return null;
}
}
/**
* BottomNavigationView setup
*/
private void setupBottomNavigationView(){
Log.d(TAG, "setupBottomNavigationView: setting up BottomNavigationView");
BottomNavigationViewHelper.setupBottomNavigationView(bottomNavigationView);
BottomNavigationViewHelper.enableNavigation(getActivity(),getActivity() ,bottomNavigationView);
Menu menu = bottomNavigationView.getMenu();
MenuItem menuItem = menu.getItem(mActivityNumber);
menuItem.setChecked(true);
}
/*
------------------------------------ Firebase ---------------------------------------------
*/
/**
* Setup the firebase auth object
*/
private void setupFirebaseAuth(){
Log.d(TAG, "setupFirebaseAuth: setting up firebase auth.");
mAuth = FirebaseAuth.getInstance();
mFirebaseDatabase = FirebaseDatabase.getInstance();
myRef = mFirebaseDatabase.getReference();
mAuthListener = new FirebaseAuth.AuthStateListener() {
#Override
public void onAuthStateChanged(#NonNull FirebaseAuth firebaseAuth) {
FirebaseUser user = firebaseAuth.getCurrentUser();
if (user != null) {
// User is signed in
Log.d(TAG, "onAuthStateChanged:signed_in:" + user.getUid());
} else {
// User is signed out
Log.d(TAG, "onAuthStateChanged:signed_out");
}
// ...
}
};
}
#Override
public void onStart() {
super.onStart();
mAuth.addAuthStateListener(mAuthListener);
}
#Override
public void onStop() {
super.onStop();
if (mAuthListener != null) {
mAuth.removeAuthStateListener(mAuthListener);
}
}
}
and it seems like this line causing problem:
UniversalImageLoader.setImage(mUserAccountSettings.getProfile_photo(), mProfileImage, null, "");
mUsername.setText(mUserAccountSettings.getUsername());
You are getting null value from singleSnapshot.getValue(UserAccountSettings.class).
You need to check the available data at the reference, you have added your your listenerForSingleValueEvent on, in your Firebase database.
In the chat functionality of the application, I am able to send and receive text messages. I am trying to implement where I am able to send and receive image messages and I am running into errors.
StudentChatActivity.java
public class StudentChatActivity extends AppCompatActivity {
private FirebaseListAdapter<ChatMessage> adapter;
private ListView listView;
public static String tutorID = "";
public String tutorName = "";
private String mChatUser;
private FirebaseAuth mAuth;
private DatabaseReference mRootRef;
FirebaseDatabase database;
private MessageAdapter mAdapter;
private static final int TOTAL_ITEMS_TO_LOAD = 10;
private int mCurrentPage = 1;
private static final int GALLERY_PICK = 1;
private FirebaseUser mCurrentUser;
private StorageReference mImageStorage;
private int itemPos = 0;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_chat);
Intent intt = getIntent();
Bundle b = intt.getExtras();
if (b != null) {
tutorID = (String) b.get("tutorID");
tutorName = (String) b.get("tutorName");
}
FloatingActionButton fab = (FloatingActionButton) findViewById(R.id.fab);
listView = (ListView) findViewById(R.id.list);
ImageButton imagebutton = (ImageButton) findViewById(R.id.image_button);
mImageStorage = FirebaseStorage.getInstance().getReference();
mCurrentUser = FirebaseAuth.getInstance().getCurrentUser();
String current_uid = mCurrentUser.getUid();
final EditText input = (EditText) findViewById(R.id.input1);
mRootRef.child("Chat").child(String.valueOf(mCurrentUser)).addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
if(!dataSnapshot.hasChild(mChatUser)){
Map chatAddMap = new HashMap();
chatAddMap.put("seen",false);
chatAddMap.put("timestamp", ServerValue.TIMESTAMP);
Map chatUserMap = new HashMap();
chatUserMap.put("Chat/" + mCurrentUser + "/" + mChatUser, chatAddMap);
chatUserMap.put("Chat/" + mChatUser + "/" + mCurrentUser, chatAddMap);
mRootRef.updateChildren(chatUserMap, new DatabaseReference.CompletionListener() {
#Override
public void onComplete(DatabaseError databaseError, DatabaseReference databaseReference) {
if (databaseError != null)
Log.d( "Chat_log: ", databaseError.getMessage().toString());
}
});
}
}
#Override
public void onCancelled(DatabaseError databaseError) {
}
});
showAllOldMessages();
imagebutton.setOnClickListener(new View.OnClickListener(){
#Override
public void onClick(View view){
Intent galleryIntent = new Intent();
galleryIntent.setType("image/*");
galleryIntent.setAction(Intent.ACTION_GET_CONTENT);
startActivityForResult(Intent.createChooser(galleryIntent,"SELECT IMAGE"),GALLERY_PICK);
}
});
fab.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
if (input.getText().toString().trim().equals("")) {
Toast.makeText(StudentChatActivity.this, "Please enter some texts!", Toast.LENGTH_SHORT).show();
} else {
FirebaseDatabase.getInstance()
.getReference()
.push()
.setValue(
new ChatMessage(input.getText().toString(),
StudentHome.info.etFirstname,
FirebaseAuth.getInstance().getCurrentUser().getUid(),
StudentChatActivity.this.tutorName,
StudentChatActivity.this.tutorID,
FirebaseAuth.getInstance().getCurrentUser().getUid()
)
);
input.setText("");
//send notification
}
}
});
}
#Override
protected void onActivityResult(int requestCode, int resultCode, Intent data){
super.onActivityResult(requestCode,resultCode,data);
mRootRef = database.getReference();
// mAuth = FirebaseAuth.getInstance();
final EditText input = (EditText) findViewById(R.id.input1);
if(requestCode == GALLERY_PICK && resultCode == RESULT_OK){
Uri imageUri = data.getData();
final String current_user_ref = "messages/" + mCurrentUser + "/" + mChatUser;
final String chat_user_ref = "messages/" + mChatUser + "/" + mCurrentUser;
DatabaseReference user_message_push = mRootRef.child("messages").child(String.valueOf(mCurrentUser)).child(mChatUser).push();
final String push_id = user_message_push.getKey();
StorageReference filepath = mImageStorage.child("message_images").child(push_id + ".jpg");
filepath.putFile(imageUri).addOnCompleteListener(new OnCompleteListener<UploadTask.TaskSnapshot>() {
#Override
public void onComplete(#NonNull Task<UploadTask.TaskSnapshot> task) {
if(task.isSuccessful()){
String download_url = task.getResult().getDownloadUrl().toString();
Map messageMap = new HashMap();
messageMap.put("message",download_url);
messageMap.put("seen",false);
messageMap.put("type","image");
messageMap.put("time", ServerValue.TIMESTAMP);
messageMap.put("from",mCurrentUser);
Map messageUserMap = new HashMap();
messageUserMap.put(current_user_ref + "/" + push_id,messageMap);
messageUserMap.put(chat_user_ref + "/" + push_id,messageMap);
input.setText("");
mRootRef.updateChildren(messageUserMap, new DatabaseReference.CompletionListener() {
#Override
public void onComplete(DatabaseError databaseError, DatabaseReference databaseReference) {
if (databaseError != null)
Log.d( "Chat_log: ", databaseError.getMessage().toString());
}
});
/* mRootRef.updateChildren(messageUserMap, databaseError, databaseReference){
if (databaseError != null){
Log.d("CHAT_LOG", databaseError.getMessage().toString());
}
}); */
}
}
});
}
}
private void showAllOldMessages() {
try {
adapter = new MessageAdapter(this, ChatMessage.class, R.layout.item_in_message,
FirebaseDatabase.getInstance().getReference());
listView.setAdapter(adapter);
} catch (Exception er) {
System.out.print(er.getMessage());
}
}
}
ChatMessage.Java
package com.rough.tuber.tuber;
import android.media.Image;
import java.util.Date;
public class ChatMessage {
private String messageText;
private String studentName;
private String studentID;
private String tutorName;
private String tutorID;
private String senderId;
private long messageTime;
public ChatMessage(String messageText, String studentName, String studentID, String tutorName, String tutorID, String senderId) {
this.messageText = messageText;
this.studentName = studentName;
this.studentID = studentID;
messageTime = new Date().getTime();
this.tutorID = tutorID;
this.tutorName = tutorName;
this.senderId = senderId;
}
public ChatMessage() {
}
public String getStudentID() {
return studentID;
}
public void setStudentID(String studentID) {
this.studentID = studentID;
}
public String getSenderId() {
return senderId;
}
public String getTutorID() {
return tutorID;
}
public void setSenderId(String senderId) {
this.senderId = senderId;
}
public void setTutorID(String tutorID) {
this.tutorID = tutorID;
}
public String getTutorName() {
return tutorName;
}
public void setTutorName(String tutorName) {
this.tutorName = tutorName;
}
public String getMessageText() {
return messageText;
}
public void setMessageText(String messageText) {
this.messageText = messageText;
}
public String getStudentName() {
return studentName;
}
public void setStudentName(String studentName) {
this.studentName = studentName;
}
public long getMessageTime() {
return messageTime;
}
public void setMessageTime(long messageTime) {
this.messageTime = messageTime;
}
}
MessageAdapter.Java
package com.rough.tuber.tuber;
import android.text.format.DateFormat;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ImageView;
import android.widget.TextView;
import com.firebase.ui.database.FirebaseListAdapter;
import com.google.firebase.auth.FirebaseAuth;
import com.google.firebase.database.DatabaseReference;
public class MessageAdapter extends FirebaseListAdapter<ChatMessage> {
private StudentChatActivity activity;
public MessageAdapter(StudentChatActivity activity, Class<ChatMessage> modelClass, int modelLayout, DatabaseReference ref) {
super(activity, modelClass, modelLayout, ref);
this.activity = activity;
}
#Override
protected void populateView(View v, ChatMessage model, int position) {
if (v != null) {
TextView messageText = (TextView) v.findViewById(R.id.message_text);
TextView messageUser = (TextView) v.findViewById(R.id.message_user);
TextView messageTime = (TextView) v.findViewById(R.id.message_time);
// ImageView messagaImage = (ImageView) v.fin
messageText.setText(model.getMessageText());
if (model.getSenderId() != null && model.getSenderId().equals(FirebaseAuth.getInstance().getCurrentUser().getUid())) {
messageUser.setText("You");
} else {
messageUser.setText(model.getTutorName());
}
// Format the date before showing it
messageTime.setText(DateFormat.format("dd-MM-yyyy (HH:mm:ss)", model.getMessageTime()));
}
}
#Override
public View getView(int position, View view, ViewGroup viewGroup) {
ChatMessage chatMessage = getItem(position);
if (chatMessage.getTutorID() != null && chatMessage.getStudentID() != null && chatMessage.getSenderId() != null && chatMessage.getStudentID().equals(FirebaseAuth.getInstance().getCurrentUser().getUid()) && chatMessage.getTutorID().equals(StudentChatActivity.tutorID)) {
if (chatMessage.getSenderId() != null && chatMessage.getSenderId().equals(FirebaseAuth.getInstance().getCurrentUser().getUid())
)
view = activity.getLayoutInflater().inflate(R.layout.item_out_message, viewGroup, false);
else
view = activity.getLayoutInflater().inflate(R.layout.item_in_message, viewGroup, false);
//generating view
populateView(view, chatMessage, position);
return view;
}
view = activity.getLayoutInflater().inflate(R.layout.item_empty, viewGroup, false);
return view;
}
#Override
public int getViewTypeCount() {
// return the total number of view types. this value should never change
// at runtime
return 2;
}
#Override
public int getItemViewType(int position) {
// return a value between 0 and (getViewTypeCount - 1)
return position % 2;
}
}
I am receiving this error.
This the error message.
FATAL EXCEPTION: main
Process: com.rough.tuber.tuber, PID: 3931
java.lang.NullPointerException: Attempt to invoke interface method 'int java.lang.CharSequence.length()' on a null object reference
at java.util.regex.Matcher.reset(Matcher.java:1052)
at java.util.regex.Matcher.(Matcher.java:180)
at java.util.regex.Pattern.matcher(Pattern.java:1006)
at com.google.android.gms.internal.zzelv.zzqh(Unknown Source:2)
at com.google.firebase.database.DataSnapshot.hasChild(Unknown Source:12)
at com.rough.tuber.tuber.StudentChatActivity$1.onDataChange(StudentChatActivity.java:92)
at com.google.android.gms.internal.zzegf.zza(Unknown Source:13)
at com.google.android.gms.internal.zzeia.zzbyc(Unknown Source:2)
at com.google.android.gms.internal.zzeig.run(Unknown Source:71)
at android.os.Handler.handleCallback(Handler.java:790)
at android.os.Handler.dispatchMessage(Handler.java:99)
at android.os.Looper.loop(Looper.java:164)
at android.app.ActivityThread.main(ActivityThread.java:6494)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:438)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:807)
Firebase enter image description hereenter image description here
On your onCreate() method, you are calling valueEventListener on mRootRef though you have not initialized it. Also database path should be from 'current_uid' as per your database structure.
Instead of initializing mRootRef on onActivityResult initialize it on onCreateMethod():
.......
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_chat);
........
mRootRef = FirebaseDatabase.getInstance().getReference();
.......
mRootRef.child("Chat").child(current_uid)
.addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
.........
Update
Updated for your persisting error.
From your error log its clear.
com.google.firebase.database.DatabaseException: Invalid Firebase
Database path: com.google.firebase.auth.internal.zzh#329c22b. Firebase
Database paths must not contain '.', '#', '$', '[', or ']'
Your Database path is containing some non expected characters in path. you need to avoid that .
So print your database path and ensure that there is no any '.', '#', '$', '[', or ']'
The project im working on allow the user to register and login and all works perfectly until I spotted something wrong with the code. It doesn't count as an error because the compiler don't think its an error. Its just a bug or whatever people call it is. So here's what happened . The user login to their account, the database transfer their data into intent extras. then on the next activities, the username, coins and gems appears on top of the page so that the user know how much coins they have left. For testing purpose, i added add coin and decrease coin button. still, the code works perfectly. But after the user log out and relogin, the coins backs to the original amount. I know the problem caused by putting a value on the coin variable in User.java class. And still while logging in I put the default value of coins and gems for the user in the intent extras. I just cant find my way on how to put the value from database to the intent extras while user logging in.
so heres the code for login activity
buttonLogin.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
//Check user input is correct or not
if (validate()) {
//Get values from EditText fields
String Email = editTextEmail.getText().toString();
String Password = editTextPassword.getText().toString();
User player1 = new User(null, null, Email, Password);
//Authenticate user
User currentUser = myDb.Authenticate(player1);
//Check Authentication is successful or not
if (currentUser != null) {
System.out.println("Success");
Bundle extras = new Bundle();
extras.putString("P_ID", currentUser.getId());
extras.putString("P_NAME", currentUser.getName());
extras.putInt("P_COINS", currentUser.getCoins());
extras.putInt("P_GEMS", currentUser.getGems());
Intent intent = new Intent(getApplicationContext(),HomeActivity.class);
intent.putExtras(extras);
startActivity(intent);
finish();
} else {
//User Logged in Failed
System.out.println("Failed");
}
}
}
});
the homeactivity
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
//Set fullscreen and no title//////////
getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN, WindowManager.LayoutParams.FLAG_FULLSCREEN);
this.requestWindowFeature(Window.FEATURE_NO_TITLE);
///////////////////////////////////////
setContentView(R.layout.home_screen);
myDb = new DatabaseHelper(this);
Intent intent = getIntent();
Bundle extras = intent.getExtras();
pid = extras.getString("P_ID");
pname = extras.getString("P_NAME");
pcoins = extras.getInt("P_COINS");
pgems = extras.getInt("P_GEMS");
nametxt = (TextView)findViewById(R.id.playernametext);
coinstxt = (TextView)findViewById(R.id.playercoinstext);
gemstxt = (TextView)findViewById(R.id.playergemstext);
addcoin = (Button)findViewById(R.id.addbtn);
decoin = (Button)findViewById(R.id.decbtn);
nametxt.setText(" " +String.valueOf(pname) +" ");
coinstxt.setText(" Coins : " +String.valueOf(pcoins) +" ");
gemstxt.setText(" Gems : " +String.valueOf(pgems) +" ");
addcoin.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
pcoins += 10;
boolean isUpdate = myDb.updateUser(pid, pname, String.valueOf(pcoins), String.valueOf(pgems));
if (isUpdate == true) {
nametxt.setText(" " +String.valueOf(pname) +" ");
coinstxt.setText(" Coins : " +String.valueOf(pcoins) +" ");
gemstxt.setText(" Gems : " +String.valueOf(pgems) +" ");
}
}
});
decoin.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
pcoins -= 10;
boolean isUpdate = myDb.updateUser(pid, pname, String.valueOf(pcoins), String.valueOf(pgems));
if (isUpdate == true) {
nametxt.setText(" " +String.valueOf(pname) +" ");
coinstxt.setText(" Coins : " +String.valueOf(pcoins) +" ");
gemstxt.setText(" Gems : " +String.valueOf(pgems) +" ");
}
}
});
}
and of course the user class
public class User {
public String id;
public String userName;
public String email;
public String password;
public int coins = 1000;
public int gems = 10;
public User(String id, String userName, String email, String password) {
this.id = id;
this.userName = userName;
this.email = email;
this.password = password;
}
public String getId() {
return this.id;
}
public String getName() {
return this.userName;
}
public void addCoins(int addAmount) {
this.coins = addAmount;
}
public void decCoins(int decAmount) {
this.coins = decAmount;
}
public int getCoins() {
return this.coins;
}
public void addGems(int addAmount) {
this.gems = addAmount;
}
public void decGems(int decAmount) {
this.gems = decAmount;
}
public int getGems() {
return this.gems;
}
}
Honestly, my brain lacks of logic. Thats why i come here, to see whether my code does make sense.
And please, if you don't understand what i mean, just ask me which parts and please just dont immediately flag my question. Im really bad at english, trust me.
I'd suggest only passing the userid (which should never change) and then always getting the values coins etc from the database and also only changing them in the database (followed by resetting the displayed values from the values in the database).
You would then not have the issue of trying to juggle two sets of data you would then rely on the real data i.e. that in the database.
Working Example
The following is some code that goes through the basics.
When it starts the MainActivity, immediately starts the LoginActivity when you login then it takes you to the HomeActivity. This display the current Userid, Username, coins (initially 0) and gems.
There are 2 buttons Add10Coins and Add10gems clicking them will apply the new values to the DB displaying the updated values. If you stop the App and rerun, login then the values will be as they were.
Passing values wise, although the LoginActivity sets 3 Intent Extra values only one is used (the userid as a long) by the HomeActivity, but as per the values display all are accessible. If another activity is started then all you have to do is pass the userid via the intent.
The code isn't what I'd call complex but I'd certainly suggest going through it and try to understand it.
user.java
I've added some methods and also added some Constants, this is now :-
public class User {
public static final int ADJUSTTYPE_ADD = 1;
public static final int ADJUSTTYPE_REPLACE = 2;
public static final int ADJUSTTYPE_MULTIPLY = 3;
public static final int ADJUSTTYPE_DIVIDE = 4;
String id;
String userName;
String email;
String password;
int coins;
int gems;
public User(String id, String userName, String email, String password) {
this.id = id;
this.email = email;
//And so on. Don't mind this
}
public void setId(String id) {
this.id = id;
}
public String getId() {
return id;
}
public void setName(String userName) {
this.userName = userName;
}
public String getName() {
return this.userName;
}
public void setEmail(String email) {
this.email = email;
}
public String getEmail() {
return email;
}
public void setPassword(String password) {
this.password = password;
}
public String getPassword() {
return password;
}
public void setCoins(int coins) {
this.coins = coins;
}
public int getCoins() {
return this.coins;
}
public void setGems(int gems) {
this.gems = gems;
}
public int getGems() {
return this.gems;
}
public long getLongId() {
long id;
try {
id = Long.valueOf(this.id);
} catch (Exception e) {
return -1;
}
return id;
}
}
DatabaseHelper.java
This has been written from scratch based upon not the most stringent inspection of your code, it will largely be affected by my styling/usage techniques but not to the extent that I'd apply for real development.
Within this is the method adjustCoinsAndOrGems this is what is used to update the gems or coins in the DB and also in the returned User (so that a synchronised version of the User is returned, not that this returned use is used (I personally prefer to access the database as long as it's not an issue (e.g. noticeably affects performance)))
public class DatabaseHelper extends SQLiteOpenHelper {
public static final String DBNAME = "mygame.db";
public static final int DBVERSION = 1;
public static final String TBL_USER = "user";
public static final String COL_USER_ID = BaseColumns._ID;
public static final String COL_USER_NAME = "user_name";
public static final String COL_USER_EMAIL = "user_email";
public static final String COL_USER_PASWWORD = "user_password";
public static final String COL_USER_COINS = "user_coins";
public static final String COL_USER_GEMS = "user_gems";
public static final String TBL_PLAYER = "player";
public static final String COL_PLYAER_ID = BaseColumns._ID;
public static final String COL_PLAYER_OWNINGUSER = "player_owninguser";
public static final String COL_PLAYER_NAME = "player_name";
//...... other columns
SQLiteDatabase mDB;
public DatabaseHelper(Context context) {
super(context, DBNAME, null, DBVERSION);
mDB = this.getWritableDatabase();
}
#Override
public void onCreate(SQLiteDatabase db) {
String crt_tbl_user = "CREATE TABLE IF NOT EXISTS " + TBL_USER + "(" +
COL_USER_ID + " INTEGER PRIMARY KEY," +
COL_USER_NAME + " TEXT NOT NULL UNIQUE," +
COL_USER_EMAIL + " TEXT NOT NULL UNIQUE," +
COL_USER_PASWWORD + " TEXT NOT NULL," +
COL_USER_COINS + " INTEGER," +
COL_USER_GEMS + " INTEGER" +
")";
String crt_tbl_player = "CREATE TABLE IF NOT EXISTS " + TBL_PLAYER + "(" +
COL_PLYAER_ID + " INTEGER PRIMARY KEY," +
COL_PLAYER_NAME + " TEXT NOT NULL," +
COL_PLAYER_OWNINGUSER + " INTEGER REFERENCES " + TBL_USER + "(" + COL_USER_ID + ")" +
")";
db.execSQL(crt_tbl_user);
db.execSQL(crt_tbl_player);
}
#Override
public void onUpgrade(SQLiteDatabase db, int i, int i1) {
}
/*
Note core add but not intended to be used directly
Note this assumes that checks are done to ensure that name, email and password
have been provided
*/
private long addUser(Long id, String name, String email, String password, int coins, int gems) {
ContentValues cv = new ContentValues();
if (id > 0) {
cv.put(COL_USER_ID,id);
}
if (name.length() > 0) {
cv.put(COL_USER_NAME,name);
}
if (email.length() > 0 ) {
cv.put(COL_USER_EMAIL,email);
}
if (password.length() > 0) {
cv.put(COL_USER_PASWWORD,password);
}
cv.put(COL_USER_COINS,coins);
cv.put(COL_USER_GEMS,gems);
if (cv.size() < 1) return -1; //<<<<<<<<<< return if nothing to add
return mDB.insert(TBL_USER,null,cv);
}
/*
For add with just name, email and password (normal usage)
*/
public long addUser(String name, String email, String password) {
return this.addUser(-1L,name,email,password,0,0);
}
/*
For adding a user setting the coins and gems (special usage)
*/
public long addUserSettingCoinsAndGems(String name, String email, String password, int coins, int gems) {
return this.addUser(-1L,name,email,password,coins,gems);
}
public User getUser(long id) {
User rv = new User("-1","",",",""); // Invalid user
String whereclause = COL_USER_ID + "=?";
String[] whereargs = new String[]{String.valueOf(id)};
Cursor csr = mDB.query(TBL_USER,null,whereclause,whereargs,null,null,null);
if (csr.moveToFirst()) {
rv.setId(String.valueOf(id));
rv.setName(csr.getString(csr.getColumnIndex(COL_USER_NAME)));
rv.setEmail(csr.getString(csr.getColumnIndex(COL_USER_EMAIL)));
rv.setPassword(csr.getString(csr.getColumnIndex(COL_USER_PASWWORD)));
rv.setCoins(csr.getInt(csr.getColumnIndex(COL_USER_COINS)));
rv.setGems(csr.getInt(csr.getColumnIndex(COL_USER_GEMS)));
}
csr.close();
return rv;
}
public User getUser(String userid) {
String whereclause = COL_USER_ID + "=?";
User rv = new User("-1","",",",""); // Invalid user
long id;
try {
id = Long.valueOf(userid);
} catch (Exception e) {
return rv;
}
String[] whereargs = new String[]{String.valueOf(id)};
Cursor csr = mDB.query(TBL_USER,null,whereclause,whereargs,null,null,null);
if (csr.moveToFirst()) {
rv.setId(String.valueOf(id));
rv.setName(csr.getString(csr.getColumnIndex(COL_USER_NAME)));
rv.setEmail(csr.getString(csr.getColumnIndex(COL_USER_EMAIL)));
rv.setPassword(csr.getString(csr.getColumnIndex(COL_USER_PASWWORD)));
rv.setCoins(csr.getInt(csr.getColumnIndex(COL_USER_COINS)));
rv.setGems(csr.getInt(csr.getColumnIndex(COL_USER_GEMS)));
}
csr.close();
return rv;
}
public User getUser(String email, String password) {
User rv = new User("-1","","","");
String whereclause = COL_USER_EMAIL + "=? AND " + COL_USER_PASWWORD + "=?";
String[] whereargs = new String[]{email,password};
Cursor csr = mDB.query(TBL_USER,null,whereclause,whereargs,null,null,null);
if (csr.moveToFirst()) {
rv.setId( String.valueOf(csr.getLong(csr.getColumnIndex(COL_USER_ID))));
rv.setName(csr.getString(csr.getColumnIndex(COL_USER_NAME)));
rv.setEmail(csr.getString(csr.getColumnIndex(COL_USER_EMAIL)));
rv.setPassword(csr.getString(csr.getColumnIndex(COL_USER_PASWWORD)));
rv.setCoins(csr.getInt(csr.getColumnIndex(COL_USER_COINS)));
rv.setGems(csr.getInt(csr.getColumnIndex(COL_USER_GEMS)));
}
csr.close();
return rv;
}
public User adjustCoinsAndOrGems(User u, int coins, int coin_adjustmode, int gems, int gem_adjustmode) {
ContentValues cv = new ContentValues();
User rv;
User user_fromDB = getUser(u.getId());
if (user_fromDB.id.equals("-1")) return u; // User not found so return
switch (coin_adjustmode) {
case User.ADJUSTTYPE_REPLACE:
cv.put(COL_USER_COINS,coins);
break;
case User.ADJUSTTYPE_ADD:
if (coins != 0) {
cv.put(COL_USER_COINS,user_fromDB.getCoins() + coins);
}
break;
case User.ADJUSTTYPE_MULTIPLY:
if (coins > 0) {
cv.put(COL_USER_COINS,user_fromDB.getCoins() * coins);
}
break;
case User.ADJUSTTYPE_DIVIDE:
if (coins > 0) {
cv.put(COL_USER_COINS,user_fromDB.getCoins() / coins);
}
break;
}
switch (gem_adjustmode) {
case User.ADJUSTTYPE_REPLACE:
cv.put(COL_USER_GEMS,gems);
break;
case User.ADJUSTTYPE_ADD:
if (gems != 0) {
cv.put(COL_USER_GEMS,user_fromDB.getGems() + gems);
}
break;
case User.ADJUSTTYPE_MULTIPLY:
if (gems > 0) {
cv.put(COL_USER_GEMS,user_fromDB.getGems() * gems);
}
break;
case User.ADJUSTTYPE_DIVIDE:
if (gems > 0) {
cv.put(COL_USER_GEMS,user_fromDB.getGems() / gems);
}
break;
}
if (cv.size() < 1) return u;
String whereclause = COL_USER_ID + "=?";
String[] whereargs = new String[]{u.getId()};
mDB.update(TBL_USER,cv,whereclause,whereargs);
return getUser(user_fromDB.getId());
}
public boolean authenticateUser(String email, String password) {
User u = getUser(email,password);
return (u.getLongId() > 0);
}
}
MainActivity.java
Very simple activity that starts the LoginActivity and when finally returned to does nothing (so you might as well kill the app).
public class MainActivity extends AppCompatActivity {
TextView mMessage;
DatabaseHelper mDB;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mMessage = this.findViewById(R.id.message);
mDB = new DatabaseHelper(this);
addSomeTestingUsers();
// Immediately start Login Activity
Intent i = new Intent(MainActivity.this,LoginActivity.class);
startActivity(i);
}
#Override
protected void onResume() {
super.onResume();
mMessage.setText("Welcome back");
}
private void addSomeTestingUsers() {
if (DatabaseUtils.queryNumEntries(mDB.getWritableDatabase(),DatabaseHelper.TBL_USER) > 0) return;
mDB.addUser("Fred","fred#fredmal.com","password");
mDB.addUser("Mary","mary#mary.email.com","password");
}
}
LoginActivity
This is pretty straightforward note that as it stands you have to Login and that the emails and passwords for the 2 users are coded in the MainActivity. When supplied correctly the HomeActivivty is started :-
public class LoginActivity extends AppCompatActivity {
public static final String INTENTKEY_USERNAME = "IK_USERNAME";
public static final String INTENTKEY_USERID = "IK_USERID";
public static final String INTENTKEY_STRINGUSERID = "IK_USERIDSTRING";
Button mloginbtn;
EditText mEmail,mPassword;
Context mContext;
DatabaseHelper mDB;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_login);
mContext = this;
mloginbtn = this.findViewById(R.id.loginbtn);
mEmail = this.findViewById(R.id.email);
mPassword = this.findViewById(R.id.password);
mDB = new DatabaseHelper(this);
mloginbtn.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
handleAuthentication();
}
});
}
private void handleAuthentication() {
if (mDB.authenticateUser(mEmail.getText().toString(),mPassword.getText().toString())) {
User u = mDB.getUser(mEmail.getText().toString(),mPassword.getText().toString());
Intent i = new Intent(mContext,HomeActivity.class);
i.putExtra(INTENTKEY_USERNAME,u.getName());
i.putExtra(INTENTKEY_USERID,u.getLongId());
i.putExtra(INTENTKEY_STRINGUSERID,u.getId());
startActivity(i);
finish();
}
}
HomeActivity
For brevity, this has been used to display the coins and gems, it to is pretty basic and relies upon methods in the DatabaseHelper to do much of the work.
public class HomeActivity extends AppCompatActivity {
TextView mUserameTextView, mUseridTextView, mCoinsTextView, mGemsTextView;
Button mAdd10Coins, mAdd10Gems,mDone;
User mUser;
long mUserid;
Context mContext;
DatabaseHelper mDB;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_home);
mContext = this;
mDB = new DatabaseHelper(mContext);
mUserameTextView = this.findViewById(R.id.username);
mUseridTextView = this.findViewById(R.id.userid);
mCoinsTextView = this.findViewById(R.id.coins);
mGemsTextView = this.findViewById(R.id.gems);
Intent i = this.getIntent();
mUserid = i.getLongExtra(LoginActivity.INTENTKEY_USERID,-1);
mUser = mDB.getUser(mUserid);
refreshDisplay();
initButtons();
}
private void initButtons() {
mAdd10Coins = this.findViewById(R.id.add10coins);
mAdd10Coins.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
mDB.adjustCoinsAndOrGems(mUser,10,User.ADJUSTTYPE_ADD,0,User.ADJUSTTYPE_ADD);
mUser = mDB.getUser(mUserid);
refreshDisplay();
}
});
mAdd10Gems = this.findViewById(R.id.add10gems);
mAdd10Gems.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
mDB.adjustCoinsAndOrGems(mUser,0, User.ADJUSTTYPE_ADD,10,User.ADJUSTTYPE_ADD);
mUser = mDB.getUser(mUserid);
refreshDisplay();
}
});
mDone = this.findViewById(R.id.done);
mDB = new DatabaseHelper(mContext);
mDone.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
finish();
}
});
}
private void refreshDisplay() {
mUseridTextView.setText(mUser.getId());
mUserameTextView.setText(mUser.getName());
mCoinsTextView.setText(String.valueOf(mUser.getCoins()));
mGemsTextView.setText(String.valueOf(mUser.getGems()));
}
}
I am using Firebase with my Android application. I am trying to use Firebase as a NOSQL database and this is my data retrieval object.
public class FirebaseManager {
private static final String DB_REF = "mainframeradio";
private static final String STREAM_REF = "streams";
public static List<MediaStream> getMediaStreams(Context context) {
final List<MediaStream> mediaStreams = new ArrayList<>();
FirebaseDatabase db = FirebaseDatabase.getInstance();
DatabaseReference dbRef = db.getReference(STREAM_REF);
dbRef.addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
Map<String, Object> streams = (Map<String, Object>) dataSnapshot.getValue();
if (!streams.isEmpty()) {
for (Object stream : streams.values()) {
String protocol = (String) ((Map) stream).get("protocol");
String host = (String) ((Map) stream).get("host");
int port = (int) ((Map) stream).get("port");
String media = (String) ((Map) stream).get("media");
String metadata = (String) ((Map) stream).get("metadata");
String streamName = (String) ((Map) stream).get("streamName");
MediaStream mediaStream = new MediaStream(protocol, host, port, media, metadata, streamName);
mediaStreams.add(mediaStream);
}
} else {
L.d("No media streams found on the server.");
}
}
#Override
public void onCancelled(DatabaseError databaseError) {
L.w("Couldn't read the stream info from Firebase.");
}
});
return mediaStreams;
}
}
The thing is the event does not get triggered from the activity I am calling it from.
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_player);
// Set components.
this.playerView = findViewById(R.id.playerView);
this.songTitleTextView = findViewById(R.id.songTitleTextView);
this.albumArt = findViewById(R.id.albumArt);
// Hide both the navigation and status bar (immersive).
ViewManager.setFullscreenImmersive(getWindow());
List<MediaStream> mediaStreams = FirebaseManager.getMediaStreams(this);
System.out.print(mediaStreams);
}
All I want to do is retrieve the data from firebase. This is the database.
Any help would be appreciated.
Try this to retrieve the data:
DatabaseReference reference = FirebaseDatabase.getInstance().getReference("streams");
reference.addListenerForSingleValueEvent(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
for(DataSnapshot datas: dataSnapshot.getChildren()){
String hosts=datas.child("host").getValue().toString();
String medias=datas.child("media").getValue().toString();
String metadata=datas.child("metadata").getValue().toString();
String ports=datas.child("port").getValue().toString();
String protocol=datas.child("protocol").getValue().toString();
String steamname=datas.child("streamName").getValue().toString();
}
#Override
public void onCancelled(DatabaseError databaseError) {
}
});
the datasnapshot is streams,you then will be able to iterate inside the child 0 and get the data