The following function is called from an addChildEventListener to remove a specific node from my Firebase database when it's needed.
The issue here is that the function launches the "Item removed." toast, indicating the task was successfully executed, but the node keeps existing on the database.
Can someone tell me what is wrong?
private void showData(DataSnapshot ds) {
String keyValue = null;
if(ds.hasChildren()) {
keyValue = ds.getKey();
Toast.makeText(getActivity().getApplicationContext(), "Removing item...", Toast.LENGTH_SHORT).show();
ds.getRef().child(keyValue).removeValue().addOnCompleteListener(new OnCompleteListener<Void>() {
#Override
public void onComplete(#NonNull Task<Void> task) {
if (task.isSuccessful()) {
Toast.makeText(getActivity().getApplicationContext(), "Item removed.", Toast.LENGTH_SHORT).show();
} else {
Toast.makeText(getActivity().getApplicationContext(), "Something bad happened while removing item.", Toast.LENGTH_SHORT).show();
}
}
});
}
}
EDIT
If it helps, my query is the following:
orderItemsByTime = db.getInstance().getReference().child("items").orderByChild("time");
A likely explanation is that ds.getRef().child(keyValue) is not pointing to the location you intend. When remove() is performed on a non-existent location, it's not an error. task.isSuccessful() returns true.
Add some debug logging (or toasting) to show the path for ds.getRef().child(keyValue):
Toast.makeText(getActivity().getApplicationContext(), "Removing item at " +
ds.getRef().child(keyValue), Toast.LENGTH_SHORT).show();
or
Log.d(TAG, "Removing item at " + ds.getRef().child(keyValue));
Related
I need to have something similar to Facebook Messenger's chat heads in my app, basically a bubble that can be viewed over other apps. I can't find anything online on this topic besides this question. So is there any way to make something like this with RN?
this feature is not support directly from react native and also this is not supported in ios therefore only you could implement it with java native code in android. to do that you should write a service in android which handle this element life cycle.
You could find here simple implementation of that in an android project. it's such a straightforward example and you can use it's service for your react native project and just change it's xml file to customize your view.
And just to start your service you must write a very simple react native module look like this
#ReactMethod
public void startService(Promise promise) {
String result = "Success";
Activity activity = getCurrentActivity();
if (activity != null) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M && !Settings.canDrawOverlays(getReactApplicationContext())) {
Intent intent = new Intent(Settings.ACTION_MANAGE_OVERLAY_PERMISSION,
Uri.parse("package:" + getCurrentActivity().getPackageName()));
getCurrentActivity().startActivityForResult(intent, MainActivity.DRAW_OVER_OTHER_APP_PERMISSION_REQUEST_CODE);
}
}
try {
Intent intent = new Intent(FloatingWidgetService.FLOATING_WIDGET_ID);
intent.setClass(this.getReactApplicationContext(), FloatingWidgetService.class);
getReactApplicationContext().startService(intent);
FloatingWidgetService.setUri(uri);
} catch (Exception e) {
promise.reject(e);
return;
}
promise.resolve(result);
}
in Android-8Oreo you must ask for canDrawOverlays and you can wait for result in your MainActivity like this:
private static final int DRAW_OVER_OTHER_APP_PERMISSION_REQUEST_CODE = 1222;
....
private void startFloatingWidgetService() {
if (!mStarted) {
Intent intent = new Intent(this, FloatingWidgetService.class);
ContextCompat.startForegroundService(this, intent);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
this.startForegroundService(intent);
}else{
startService(intent);
}
mStarted = true;
finish();
}
}
....
#Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
if (requestCode == DRAW_OVER_OTHER_APP_PERMISSION_REQUEST_CODE) {
//Check if the permission is granted or not.
if (resultCode == RESULT_OK)
//If permission granted start floating widget service
startFloatingWidgetService();
else
//Permission is not available then display toast
Toast.makeText(this,
getResources().getString(R.string.draw_other_app_permission_denied),
Toast.LENGTH_SHORT).show();
} else {
super.onActivityResult(requestCode, resultCode, data);
}
}
And after that to come back again to your app from that service with the same appstate(not to create new activity) first define your activity launchmode as a singleInstance in manifest:
<activity
...
android:launchMode="singleInstance"
...
>
And use this kind of intent(!) in your service:
ReactApplicationContext reactContext = VideoViewModule.getReactContext();
Intent activityIntent = createSingleInstanceIntent();
reactContext.startActivity(activityIntent);
private Intent createSingleInstanceIntent() {
ReactApplicationContext reactContext = VideoViewModule.getReactContext();
String packageName = reactContext.getPackageName();
Intent launchIntent = reactContext.getPackageManager().getLaunchIntentForPackage(packageName);
String className = launchIntent.getComponent().getClassName();
Intent activityIntent = null;
try {
Class<?> activityClass = Class.forName(className);
activityIntent = new Intent(reactContext, activityClass);
activityIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
} catch (Exception e) {
stopCurrentService();
Log.e("POIFOIWEGBF", "Class not found", e);
}
return activityIntent;
}
I hope it helps.
I have a simple HTML page printed out inside a Servlet. Here I have setup firebase admin sdk and have set a value event listener for a path.
When the events fire, I wish to change a Div element and display the results there.
EDIT: The listener does work on further testing with logs.
But I still do not know how to reflect the changes inside the div element as the Listeners are Asynchronous. That's most likely why the script isn't working.
Can someone please guide me as to what I should do. The code is as follows:
import java.io.IOException;
import java.io.InputStream;
import java.io.PrintWriter;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.Date;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import com.google.firebase.FirebaseApp;
import com.google.firebase.FirebaseOptions;
import com.google.firebase.auth.FirebaseCredentials;
import com.google.firebase.database.DataSnapshot;
import com.google.firebase.database.DatabaseError;
import com.google.firebase.database.DatabaseReference;
import com.google.firebase.database.FirebaseDatabase;
import com.google.firebase.database.ValueEventListener;
#WebServlet("/WebWaitlistViewServelet")
public class WebWaitlistViewServelet extends HttpServlet {
private static final long serialVersionUID = 1L;
public WebWaitlistViewServelet() {
super();
}
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
PrintWriter pw = response.getWriter();
try {
String cityName=request.getParameter("city");
String restId = request.getParameter("restid");
String userId = request.getParameter("userid");
if(cityName == null || restId == null || userId == null){
System.out.println("Error getting values");
return;
}else{
System.out.println(cityName+" "+restId+" "+userId);
}
pw.println("<HTML>");
pw.println("<HEAD>");
pw.println("<script>");
pw.println("function changePosition(position){ document.getElementById(\"positionInList\").innerHTML = position };");
pw.println("function changeTimeTillTurn(timetillturn){ document.getElementById(\"timeTillTurn\").innerHTML = timetillturn };");
pw.println("function showTimeTillTurn(){ document.getElementById(\"timeDiv\").style.display = \"visible\" };");
pw.println("function hideTimeTillTurn(){ document.getElementById(\"timeDiv\").style.display = \"hidden\" };");
pw.println("</script>");
pw.println("</HEAD>");
pw.println("<BODY>");
pw.println("<DIV align=\"center\">");
pw.println("<B>Your position in the waitlist is:</B>");
pw.println("</DIV><br/>");
pw.println("<DIV id=\"positionInList\" align=\"center\" style=\"color:blue\">");
pw.println("Loading...");
pw.println("</DIV><br/>");
pw.println("<DIV id=\"timeDiv\" align=\"center\">");
pw.println("<B>Approximate time till your turn is: </B><span id=\"timeTillTurn\" style=\"color:blue\">Loading...</span>");
pw.println("</DIV>");
pw.println("<BODY>");
pw.println("</HTML>");
pw.flush();
InputStream is = getServletContext().getResourceAsStream("/WEB-INF/firebaseauth/firebase_admin_sdk_key.json");
// Initialize the app with a service account, granting admin privileges
FirebaseOptions options = new FirebaseOptions.Builder()
.setCredential(FirebaseCredentials.fromCertificate(is))
.setDatabaseUrl("https://restaurantrepo.firebaseio.com")
.build();
try {
FirebaseApp.initializeApp(options);
} catch (Exception e) {
//
}
// As an admin, the app has access to read and write all data, regardless of Security Rules
DatabaseReference waitlistRef = FirebaseDatabase.getInstance().getReference().child(cityName).child(restId).child("waitlist");
Comparator<WaitlistedPerson> sortComparator = new Comparator<WaitlistedPerson>() {
#Override
public int compare(WaitlistedPerson lhs, WaitlistedPerson rhs) {
//sort ascending... the bigger the time entered, the later the person has joined... thus the higher the time entered the lower the position
//on waitlist
if(lhs.getTimeentered()<rhs.getTimeentered()){
//if time entered is lower, keep the person higher in the list
return -1;
}else if(lhs.getTimeentered()==rhs.getTimeentered()){
//if the time entered is the same, there are two cases possible
//1.. one person is remotely entered and one has entered at the resto POS... in this case, give priority to POS entered user
//2.. both people have remotely entered ... in this case, give preference to the person with lowest userid (he/she started using our app earlier)
//
//cases that will never happen are
//1.. two people with same userid entered remotely at same time .. can't happen as a second entry simply overwrites the old entry
//2.. two people with same time entered at POS ... can't happen as the resto host can only enter one party at a time..
if(!lhs.isRemotelyEntered() && rhs.isRemotelyEntered()){
//Log.d("FragmentCreate","lhs userid "+lhs.getUserid()+" lhs remotelyentered "+lhs.isRemotelyEntered());
//Log.d("FragmentCreate","rhs userid "+rhs.getUserid()+" rhs remotelyentered "+rhs.isRemotelyEntered());
return -1;
}else if(lhs.isRemotelyEntered() && rhs.isRemotelyEntered()){
//return the lowest user id
//userid is of format Uxx ... so get the xx part begining from index 1 of the string and get the number
int lhsuserid = Integer.parseInt(lhs.getUserid().substring(1));
int rhsuserid = Integer.parseInt(rhs.getUserid().substring(1));
//Log.d("FragmentCreate"," The userids are lhsuserid "+lhsuserid+" rhsuserid"+rhsuserid);
//Do not get tempted to use String compareto function as this will give wrong results
// U11 will get priority over U4 in string compareto due to 1 being lexicographically smaller
//Thus never use lexicographical sorting ever.
//The user ids can never be equal as two remotely entered users will never have two entries (can't... it's impossible due to firebase)
if(lhsuserid<rhsuserid){
return -1;
}else if(lhsuserid==rhsuserid){
//can never happen in real life... two remotely entered users can never have same id ever... just made for safeguard
return 0;
}else{
return 1;
}
}else if(!lhs.isRemotelyEntered() && !rhs.isRemotelyEntered()){
//both entered at POS and have same time
//can never happen in real life...
//made this just for testing scenarios in case i screw up and give wrong inputs
return 0;
}else{
//Log.d("FragmentCreate","lhs userid "+lhs.getUserid()+" lhs remotelyentered "+lhs.isRemotelyEntered());
//Log.d("FragmentCreate","rhs userid "+rhs.getUserid()+" rhs remotelyentered "+rhs.isRemotelyEntered());
return 1;
}
}else{
return 1;
}
}
};
ArrayList<WaitlistedPerson> listOfPeople = new ArrayList<>();
ValueEventListener eventListener = new ValueEventListener(){
#Override
public void onCancelled(DatabaseError error) {
pw.println("<script>hideTimeTillTurn();</script>");
pw.println("<script>changePosition('Sorry, some error occured');</script>");
System.out.println("Sorry. some error occured");
}
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
int positionCounter=0;
if(dataSnapshot.getChildrenCount()==1 || dataSnapshot.getChildrenCount() == 0 ){
//Log.d("FragmentCreate","This indicates that the restaurant probably closed down and removed all customers from the list");
pw.println("<script>hideTimeTillTurn();</script>");
pw.println("<script>changePosition('You are no longer in the waitlist');</script>");
System.out.println("You are no longer in the waitlist");
}else{
if(dataSnapshot.hasChild(userId)){
double averageWaitTime=0.0d;
long timeEnteredInMillis=0;
listOfPeople.clear();
Iterable<DataSnapshot> peopleInList = dataSnapshot.getChildren();
for(DataSnapshot currentPerson : peopleInList){
if(currentPerson.getKey().equals("dummy")){
continue;
}
if(currentPerson.getKey().equals(userId)){
//This is our node.... break the loop and enjoy using the counter
averageWaitTime = currentPerson.child("averagewaittimeperparty").getValue(Double.class);
timeEnteredInMillis = currentPerson.child("timeentered").getValue(Long.class);
listOfPeople.add(new WaitlistedPerson(currentPerson));
}else{
listOfPeople.add(new WaitlistedPerson(currentPerson));
}
}
//sort the list using our custom comparator and the get the index
Collections.sort(listOfPeople,sortComparator);
//find the position of the user now
for(WaitlistedPerson person : listOfPeople){
++positionCounter;
if(person.getUserid().equals(userId)){
break;
}
}
double timetillturn = Math.round(averageWaitTime * ((double)positionCounter));
long timeShouldComeAt = timeEnteredInMillis + (long)(timetillturn*60000);
Date timeWhenTurnArrives = new Date(timeShouldComeAt);
SimpleDateFormat sdf = new SimpleDateFormat("HH:mm");
pw.println("<script>showTimeTillTurn();</script>");
pw.println("<script>changePosition('"+positionCounter+"');</script>");
pw.println("<script>changeTimeTillTurn('"+sdf.format(timeWhenTurnArrives)+"');</script>");
System.out.println(positionCounter+" "+sdf.format(timeWhenTurnArrives));
}else{
pw.println("<script>hideTimeTillTurn();</script>");
pw.println("<script>changePosition('You are no longer in the waitlist');</script>");
System.out.println("You are no longer in the waitlist");
}
}
}
};
waitlistRef.addValueEventListener(eventListener);
} catch (Exception e) {
e.printStackTrace();
}finally{
try {
pw.close();
} catch (Exception e) {
//do nothing here
}
}
}
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
doGet(request, response);
}
}
With servlets, your clients won't see any page updates until they send a new request to your application server. What you can do is get your ValueEventListener to update the state of an in-memory object. Then your servlet can read the latest state of that object whenever constructing the HTML output.
So i managed to solve this using a JSP instead of a Servelet.
In either case, the solution was to tranfer all the logic to a JavaScript function. Then calling the said function on body load.
onload=callthefunction()
The firebase listeners were converted from java to the JavaScript version:
on()
off()
This way there is need to call ajax or anything and the elements that need to be changed can be directly altered from JavaScript
I have a simple HTML page printed out inside a Servlet. Here I have setup firebase admin sdk and have set a value event listener for a path.
When the events fire, I wish to change a Div element and display the results there.
EDIT: The listener does work on further testing with logs.
But I still do not know how to reflect the changes inside the div element as the Listeners are Asynchronous. That's most likely why the script isn't working.
Can someone please guide me as to what I should do. The code is as follows:
import java.io.IOException;
import java.io.InputStream;
import java.io.PrintWriter;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.Date;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import com.google.firebase.FirebaseApp;
import com.google.firebase.FirebaseOptions;
import com.google.firebase.auth.FirebaseCredentials;
import com.google.firebase.database.DataSnapshot;
import com.google.firebase.database.DatabaseError;
import com.google.firebase.database.DatabaseReference;
import com.google.firebase.database.FirebaseDatabase;
import com.google.firebase.database.ValueEventListener;
#WebServlet("/WebWaitlistViewServelet")
public class WebWaitlistViewServelet extends HttpServlet {
private static final long serialVersionUID = 1L;
public WebWaitlistViewServelet() {
super();
}
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
PrintWriter pw = response.getWriter();
try {
String cityName=request.getParameter("city");
String restId = request.getParameter("restid");
String userId = request.getParameter("userid");
if(cityName == null || restId == null || userId == null){
System.out.println("Error getting values");
return;
}else{
System.out.println(cityName+" "+restId+" "+userId);
}
pw.println("<HTML>");
pw.println("<HEAD>");
pw.println("<script>");
pw.println("function changePosition(position){ document.getElementById(\"positionInList\").innerHTML = position };");
pw.println("function changeTimeTillTurn(timetillturn){ document.getElementById(\"timeTillTurn\").innerHTML = timetillturn };");
pw.println("function showTimeTillTurn(){ document.getElementById(\"timeDiv\").style.display = \"visible\" };");
pw.println("function hideTimeTillTurn(){ document.getElementById(\"timeDiv\").style.display = \"hidden\" };");
pw.println("</script>");
pw.println("</HEAD>");
pw.println("<BODY>");
pw.println("<DIV align=\"center\">");
pw.println("<B>Your position in the waitlist is:</B>");
pw.println("</DIV><br/>");
pw.println("<DIV id=\"positionInList\" align=\"center\" style=\"color:blue\">");
pw.println("Loading...");
pw.println("</DIV><br/>");
pw.println("<DIV id=\"timeDiv\" align=\"center\">");
pw.println("<B>Approximate time till your turn is: </B><span id=\"timeTillTurn\" style=\"color:blue\">Loading...</span>");
pw.println("</DIV>");
pw.println("<BODY>");
pw.println("</HTML>");
pw.flush();
InputStream is = getServletContext().getResourceAsStream("/WEB-INF/firebaseauth/firebase_admin_sdk_key.json");
// Initialize the app with a service account, granting admin privileges
FirebaseOptions options = new FirebaseOptions.Builder()
.setCredential(FirebaseCredentials.fromCertificate(is))
.setDatabaseUrl("https://restaurantrepo.firebaseio.com")
.build();
try {
FirebaseApp.initializeApp(options);
} catch (Exception e) {
//
}
// As an admin, the app has access to read and write all data, regardless of Security Rules
DatabaseReference waitlistRef = FirebaseDatabase.getInstance().getReference().child(cityName).child(restId).child("waitlist");
Comparator<WaitlistedPerson> sortComparator = new Comparator<WaitlistedPerson>() {
#Override
public int compare(WaitlistedPerson lhs, WaitlistedPerson rhs) {
//sort ascending... the bigger the time entered, the later the person has joined... thus the higher the time entered the lower the position
//on waitlist
if(lhs.getTimeentered()<rhs.getTimeentered()){
//if time entered is lower, keep the person higher in the list
return -1;
}else if(lhs.getTimeentered()==rhs.getTimeentered()){
//if the time entered is the same, there are two cases possible
//1.. one person is remotely entered and one has entered at the resto POS... in this case, give priority to POS entered user
//2.. both people have remotely entered ... in this case, give preference to the person with lowest userid (he/she started using our app earlier)
//
//cases that will never happen are
//1.. two people with same userid entered remotely at same time .. can't happen as a second entry simply overwrites the old entry
//2.. two people with same time entered at POS ... can't happen as the resto host can only enter one party at a time..
if(!lhs.isRemotelyEntered() && rhs.isRemotelyEntered()){
//Log.d("FragmentCreate","lhs userid "+lhs.getUserid()+" lhs remotelyentered "+lhs.isRemotelyEntered());
//Log.d("FragmentCreate","rhs userid "+rhs.getUserid()+" rhs remotelyentered "+rhs.isRemotelyEntered());
return -1;
}else if(lhs.isRemotelyEntered() && rhs.isRemotelyEntered()){
//return the lowest user id
//userid is of format Uxx ... so get the xx part begining from index 1 of the string and get the number
int lhsuserid = Integer.parseInt(lhs.getUserid().substring(1));
int rhsuserid = Integer.parseInt(rhs.getUserid().substring(1));
//Log.d("FragmentCreate"," The userids are lhsuserid "+lhsuserid+" rhsuserid"+rhsuserid);
//Do not get tempted to use String compareto function as this will give wrong results
// U11 will get priority over U4 in string compareto due to 1 being lexicographically smaller
//Thus never use lexicographical sorting ever.
//The user ids can never be equal as two remotely entered users will never have two entries (can't... it's impossible due to firebase)
if(lhsuserid<rhsuserid){
return -1;
}else if(lhsuserid==rhsuserid){
//can never happen in real life... two remotely entered users can never have same id ever... just made for safeguard
return 0;
}else{
return 1;
}
}else if(!lhs.isRemotelyEntered() && !rhs.isRemotelyEntered()){
//both entered at POS and have same time
//can never happen in real life...
//made this just for testing scenarios in case i screw up and give wrong inputs
return 0;
}else{
//Log.d("FragmentCreate","lhs userid "+lhs.getUserid()+" lhs remotelyentered "+lhs.isRemotelyEntered());
//Log.d("FragmentCreate","rhs userid "+rhs.getUserid()+" rhs remotelyentered "+rhs.isRemotelyEntered());
return 1;
}
}else{
return 1;
}
}
};
ArrayList<WaitlistedPerson> listOfPeople = new ArrayList<>();
ValueEventListener eventListener = new ValueEventListener(){
#Override
public void onCancelled(DatabaseError error) {
pw.println("<script>hideTimeTillTurn();</script>");
pw.println("<script>changePosition('Sorry, some error occured');</script>");
System.out.println("Sorry. some error occured");
}
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
int positionCounter=0;
if(dataSnapshot.getChildrenCount()==1 || dataSnapshot.getChildrenCount() == 0 ){
//Log.d("FragmentCreate","This indicates that the restaurant probably closed down and removed all customers from the list");
pw.println("<script>hideTimeTillTurn();</script>");
pw.println("<script>changePosition('You are no longer in the waitlist');</script>");
System.out.println("You are no longer in the waitlist");
}else{
if(dataSnapshot.hasChild(userId)){
double averageWaitTime=0.0d;
long timeEnteredInMillis=0;
listOfPeople.clear();
Iterable<DataSnapshot> peopleInList = dataSnapshot.getChildren();
for(DataSnapshot currentPerson : peopleInList){
if(currentPerson.getKey().equals("dummy")){
continue;
}
if(currentPerson.getKey().equals(userId)){
//This is our node.... break the loop and enjoy using the counter
averageWaitTime = currentPerson.child("averagewaittimeperparty").getValue(Double.class);
timeEnteredInMillis = currentPerson.child("timeentered").getValue(Long.class);
listOfPeople.add(new WaitlistedPerson(currentPerson));
}else{
listOfPeople.add(new WaitlistedPerson(currentPerson));
}
}
//sort the list using our custom comparator and the get the index
Collections.sort(listOfPeople,sortComparator);
//find the position of the user now
for(WaitlistedPerson person : listOfPeople){
++positionCounter;
if(person.getUserid().equals(userId)){
break;
}
}
double timetillturn = Math.round(averageWaitTime * ((double)positionCounter));
long timeShouldComeAt = timeEnteredInMillis + (long)(timetillturn*60000);
Date timeWhenTurnArrives = new Date(timeShouldComeAt);
SimpleDateFormat sdf = new SimpleDateFormat("HH:mm");
pw.println("<script>showTimeTillTurn();</script>");
pw.println("<script>changePosition('"+positionCounter+"');</script>");
pw.println("<script>changeTimeTillTurn('"+sdf.format(timeWhenTurnArrives)+"');</script>");
System.out.println(positionCounter+" "+sdf.format(timeWhenTurnArrives));
}else{
pw.println("<script>hideTimeTillTurn();</script>");
pw.println("<script>changePosition('You are no longer in the waitlist');</script>");
System.out.println("You are no longer in the waitlist");
}
}
}
};
waitlistRef.addValueEventListener(eventListener);
} catch (Exception e) {
e.printStackTrace();
}finally{
try {
pw.close();
} catch (Exception e) {
//do nothing here
}
}
}
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
doGet(request, response);
}
}
With servlets, your clients won't see any page updates until they send a new request to your application server. What you can do is get your ValueEventListener to update the state of an in-memory object. Then your servlet can read the latest state of that object whenever constructing the HTML output.
So i managed to solve this using a JSP instead of a Servelet.
In either case, the solution was to tranfer all the logic to a JavaScript function. Then calling the said function on body load.
onload=callthefunction()
The firebase listeners were converted from java to the JavaScript version:
on()
off()
This way there is need to call ajax or anything and the elements that need to be changed can be directly altered from JavaScript
I am trying to set up in-app billing in my application. I have it in alpha testing. I keep getting crash reports from all my testers with the same logcat, shown here:
java.lang.RuntimeException: Unable to start activity
ComponentInfo{autonote.six.padc.autonote/autonote.six.padc.autonote.SaveScreen}:
java.lang.NullPointerException
at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2305)
at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2359)
at android.app.ActivityThread.access$700(ActivityThread.java:165)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1326)
at android.os.Handler.dispatchMessage(Handler.java:99)
at android.os.Looper.loop(Looper.java:137)
at android.app.ActivityThread.main(ActivityThread.java:5455)
at java.lang.reflect.Method.invokeNative(Native Method)
at java.lang.reflect.Method.invoke(Method.java:525)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1187)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1003)
at dalvik.system.NativeStart.main(Native Method)
Caused by: java.lang.NullPointerException
at autonote.six.padc.autonote.SaveScreen.onCreate(SaveScreen.java:59)
at android.app.Activity.performCreate(Activity.java:5372)
at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1104)
at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2267)
... 11 more
It seems like a simple solution, just go to Line Line 59, right? Wrong. When I go there, the line that is throwing the exception is:
mHelper.queryInventoryAsync(mGotInventoryListener);
And this is where I lose it.
Here are the relevant parts of my code:
public class SaveScreen extends ActionBarActivity {
Button EMAIL_NOTES;
IabHelper mHelper;
String UPGRADE_CODE = "upgrade_autonote";
public static int VERSION_NUMBER = 534985739;
boolean mIsPremium;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_savescreen);
//Query Inventory to see if user is premium
IabHelper.QueryInventoryFinishedListener mGotInventoryListener
= new IabHelper.QueryInventoryFinishedListener() {
public void onQueryInventoryFinished(IabResult result,
Inventory inventory) {
if (result.isFailure()) {
// handle error here
}
else {
// does the user have the premium upgrade?
mIsPremium = inventory.hasPurchase(UPGRADE_CODE);
VERSION_NUMBER = 434975736;
}
}
};
mHelper.queryInventoryAsync(mGotInventoryListener);
//^^^^^^^^^^^^^^^null pointer^^^^^^^^^^^^^^^^^^^^^^^^
EMAIL_NOTES.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
if(VERSION_NUMBER == 534985736){
Toast.makeText(getBaseContext(), "You must upgrade to unlock this feature", Toast.LENGTH_LONG).show();
}else if(VERSION_NUMBER == 434975739){
Intent EMAIL_NOTES = new Intent(getBaseContext(), Email_Notes.class);
EMAIL_NOTES.putExtra("serialized",cNotes_serialized);
EMAIL_NOTES.putExtra("class_Name", cName);
startActivity(EMAIL_NOTES);
}
}
});
}
Any ideas how to fix this issue? For the record I already went in and bought the product. It said the purchase was successful. Thanks everyone!
here:
mHelper.queryInventoryAsync(mGotInventoryListener);
NPE because mHelper is null.
Initialize mHelper object by calling IabHelper constructor with current Acitivty context and with public key:
mHelper = new IabHelper(this, base64EncodedPublicKey);
For more information What is base64EncodedPublicKey? see:
Preparing Your In-app Billing Application
What are the best practices to build an app's database schema on first execution?
In other words what I am trying to find out is:
SQLite does not support comma separated queries to be executed as a one statement batch. How to replace that so that the code stays future proof? (I don't see myself putting all the create statements in tx.executeSQL("") chained sequentially it would turn my code into a horrible piece of cr*p).
What I do, in native code as well as in Sencha/Phonegap is to use a DatabaseHelper Class that I refer to. In that class you can see the version of the Database with :
public DataBaseHelper(Context context) {
super(context, DB_NAME, null, 2);
this.myContext = context;
}
public void createDataBase() throws IOException {
boolean dbExist = checkDataBase();
if (dbExist) {
// do nothing - database already exist
openDataBase();
int cVersion = myDataBase.getVersion();
if(cVersion != 2){
onUpgrade(myDataBase, myDataBase.getVersion(), 2);}
close();
} ....}
#Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
this.getReadableDatabase();
try{
db.execSQL("ADD SQL QUERY HERE TO ADD TABLE");
}
catch(Exception e){}
}
private boolean checkDataBase() {
SQLiteDatabase checkDB = null;
try {
String myPath = DB_PATH + DB_NAME;
checkDB = SQLiteDatabase.openDatabase(myPath, null, SQLiteDatabase.OPEN_READWRITE);
} catch (SQLiteException e) {
// database does't exist yet.
}
if (checkDB != null) {
checkDB.close();
}
return checkDB != null ? true : false;
}
Although this is tedious it keeps your database future proof and the query is called at run time. This covers both your needs.
I hope this helps :)