Last week I started learning Android as I needed to create an application for one of the projects at Uni.
The application is a simple barcode/QRcode scanner and it should scan the code, compare its result with the database (I'm using Firebase) and either return other data from database if the barcode is found or ask the user if he wants to add the barcode to the database if it's not found.
I thought the easiest way to do it would be to use AlertDialog, but the app crashes every single time I scan the code.
I debugged the app and checked the Logcat, what I get is:
You need to use a Theme.AppCompat theme (or descendant) with this activity.
This is exactly where I get the error and where I wanted to use AlertDialog - based on the value in the variable details.
private BarcodeCallback callback = new BarcodeCallback() {
#Override
public void barcodeResult(final BarcodeResult result) {
barcodeView.decodeSingle(callback);
dbRef.child("Items").addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
Iterator<DataSnapshot> item = dataSnapshot.getChildren().iterator();
Boolean isFound = false;
while (!isFound || item == null) {
DataSnapshot i = item.next();
String check = i.child("ID").getValue().toString();
if (result.getText().equals(check)) {
isFound = true;
details = "Consumption: " + i.child("Consumption").getValue().toString()
+ "\nCost: " + i.child("Cost").getValue().toString()
+ "\nName: " + i.child("Name").getValue().toString();
} else {
details = "Not found";
}
}
new AlertDialog.Builder(getApplicationContext())
.setMessage("This is just an example for the purpose of the question.")
.create()
.show();
}
I get the error exactly on the line with .show();.
In the previous posts I found that you can't display AlertDialog in this place, and you need to use runOnUiThread function or Handler, none of those options worked for me, and I was getting the error in the same place.
Do you guys have any advice or suggestions?
Also, I'm sorry for the way this post looks like or for any missing but required information. I know it's not an excuse, but this is my first post here.
Thanks in advance for any replies.
The problem is here:
new AlertDialog.Builder(getApplicationContext())
You can't build a Dialog using the application context. To reach this you need an Activity Context.
Read this question or this article for further understanding
Related
My project requires to save user cards and I used Stripe for that,
as per stripe's official documentation I have to use their prebuilt CardInputWidget .
Now I have some design requirements that are not matching with this Widget even after changing its theme or style.
So I am looking for any other way to save stripe card using simple edittext or create custom Card object of Stripe?
Here's the code
implementation 'com.stripe:stripe-android:14.5.0'
Fragment code
stripe = new Stripe(getActivity(), myApp.getStripePublishKey());
PaymentMethodCreateParams params = card_multiline_widget.getPaymentMethodCreateParams();
if (params == null) {
ToastUtils.makeToast(getActivity(), "Invalid Details");
return;
}
stripe.createPaymentMethod(params, new ApiResultCallback<PaymentMethod>() {
#Override
public void onSuccess(#NonNull PaymentMethod result) {
if (getActivity() != null) {
getActivity().runOnUiThread(() -> progressDialog.dismiss());
}
paymentMethodId = result.id;
LogUtils.e(paymentMethodId);
saveCard();
// Send paymentMethodId to your server for the next steps
}
#Override
public void onError(#NonNull Exception e) {
// Display the error to the user
e.printStackTrace();
LogUtils.e(e.getMessage());
if (getActivity() != null) {
getActivity().runOnUiThread(() -> progressDialog.dismiss());
}
}
});
Short
I think it's not good practice to use your own input. Prefer Stripe's one.
Explanations
Google could reject the app because of security failure.
If you use a text field for card input, you can see the card number before sending it to stripe. So you can save the full card info, in log file or else where, before getting the Stripe token.
You can do this without bad intention, but be careful if someone found it...
I create an app with Firebase. There is an issue that i can't solve, and didn't find it talked here.
In this method I want to check if some data is already in the server. If not - I want to add it (the code of adding works well. The Firebase database is being changed as I want). so I'm using onDataChange method as following:
public boolean insertNewList(String title)
{
System.out.println("start: ");
final boolean[] result = new boolean[1];
result[0]=false;
final String group = title;
mRootRef = some reference...
mRootRef.addValueEventListener(new ValueEventListener()
{
#Override
public void onDataChange(DataSnapshot dataSnapshot)
{
System.out.println(0);
if (dataSnapshot.child(group).getValue() != null)
{
System.out.println(group + " is already exist");
System.out.println(1);
}
//write the data.
else
{
mRootRef=mRootRef.child(group);
mRootRef.push().setValue("some data");
System.out.println(2);
result[0]=true;
}
}
#Override
public void onCancelled(DatabaseError databaseError)
{
}
});
System.out.println(3);
return result[0];
}
But what realy happens is this output:
begin:
3 (just skip on onDataChange method and return false).
some print after calling the function
0 (goes back to function and enter to onDataChange method)
2 (finally goes where I want it to go)
0 (for some reason enters twice :( )
1
And because of that i receive wrong results in this function.
Can you help please?
Replace
mRootRef.addValueEventListener(new ValueEventListener()
with
mRootRef.addListenerForSingleValueEvent(new ValueEventListener()
When you add the the value to firebase, "addValueEventListener" called again, not like addListenerForSingleValueEvent that shots only once anywhy.
The output that you showed us looks normal to me. Let me try to explain:
begin: // a) this comes from the System.out.println("begin")
3 // b) you DECLARE your value event listener and then you run
// the System.out.print("3") statement
0 // c) you just added a listener so firebase calls you, and
// your listener fires
2 // d) this is the first time your listener fires, so you go
// into the block called "write the data"
0 // e) since you just wrote the data, firebase calls you again
1 // f) this time, since the data has been written, you go into
// the block called "is alraedy exist"
This is normal behaviour for firebase.
In c), firebase always calls you back one time when you declare a listener.
In e), firebase calls you because the data changed.
But in b), you are only declaring your listener, not yet running it, so the statements after this declaration are executed and you see "3" before anything else happens.
I have a networkStateReceiver, that checks if I have internet or not.
If I do, I reinitiate instabug, if not, I want to deactivate. How can I do that?
I tried just setting it as null, but it doesn't work.
if(haveConnectedMobile || haveConnectedWifi){
//TODO will need to make a queue, and go through all that queue
PSLocationCenter.getInstance().initInstabug();
}else{
PSLocationCenter.getInstance().instabug = null;
}
This is my init:
public void initInstabug() {
String[] feedbackArray = getResources().getStringArray(R.array.feedback);
String randomStr = feedbackArray[new Random().nextInt(feedbackArray.length)];
Instabug.DEBUG = true;
instabug = Instabug.initialize(this)
.setAnnotationActivityClass(InstabugAnnotationActivity.class)
.setShowIntroDialog(true, PSTimelineActivity.class)
.enableEmailField(true, false)
.setEnableOverflowMenuItem(true)
.setDebugEnabled(true)
.setCommentRequired(true)
.setPostFeedbackMessage(randomStr)
.setPostBugReportMessage(randomStr) //TODO will be the post report message, random from array
.setCommentFieldHint("Please describe what went wrong")
.setPreSendingRunnable(new Runnable() {
#Override
public void run() {
String[] files = new String[2];
files[0] = Environment.getExternalStorageDirectory() + "/Passenger/passenger_log.txt";
files[1] = Environment.getExternalStorageDirectory() + "/Passenger/passenger_log2.txt";
Compress compress = new Compress(files, Environment.getExternalStorageDirectory() + "/Passenger/log.zip");
compress.zip(new CrudStateCallback() {
#Override
public void onResponse(String string) {
Log.i("", "ended making the archive");
}
});
}
})
.attachFileAtLocation(Environment.getExternalStorageDirectory() + "/Passenger/log.zip");
}
You can use this code to disable Instabug automatic invocation:
Instabug.getInstance().setInvocationEvent(IBGInvocationEvent.IBGInvocationEventNone)
This way it won't be invoked automatically. This will only affect the next Activity though (not the current one). You may force to stop and restart all listeners by calling onPause and onResume on the current Activity. (We may address that soon though, so that such changes are applied on the currently running Activity).
Don't forget to also enable the shake invocation event when internet access is restored.
Please keep in mind that Instabug SDK already caches all reports and will re-attempt to send them on next app launch until they're uploaded successfully.
Just wanted to post the updated answer.
The newer SDK has changed the name and now you can disable it by the following code:
Instabug.changeInvocationEvent(InstabugInvocationEvent.NONE)
Notice, if you want to disable it for entire application, just call this method in your Application class
I have been able to create the if statement that checks for the string and it returns the toast message that i created but it keeps showing the toast message every time i open the chat. even if the most recent message doesn't contain the string I am looking for so i am assume it isn't checking to see if it is the last message received and it doesn't check to see if it is unread. the code is below. the reason i am trying to do this is because my parents share a facebook account and i want an easy way to display if the message is signed mom or dad. the code below only has the check for mom once it works i will be adding the check for dad signature. I am using the open source message client Xabber. Thank you for help.
public void setVisibleChat(String account, String user) {
final boolean remove = !AccountManager.getInstance()
.getArchiveMode(account).saveLocally();
AbstractChat chat = getChat(account, user);
if (chat == null)
chat = createChat(account, user);
else {
// Mark messages as read and them delete from db if necessary.
final ArrayList<MessageItem> messageItems = new ArrayList<MessageItem>();
for (MessageItem messageItem : chat.getMessages()) {
if (!messageItem.isRead()) {
messageItem.markAsRead();
messageItems.add(messageItem);
}
if (chat.getLastText().contains("Mom") && (!messageItem.isRead()));{
Toast.makeText(Application.getInstance(), "Message from Mom!", Toast.LENGTH_SHORT).show();
}
}
Application.getInstance().runInBackground(new Runnable() {
#Override
public void run() {
Collection<Long> ids = getMessageIds(messageItems, remove);
if (remove)
MessageTable.getInstance().removeMessages(ids);
else
MessageTable.getInstance().markAsRead(ids);
}
});
}
visibleChat = chat;
}
You've got an extra semi-colon here
if (chat.getLastText().contains("Mom") && (!messageItem.isRead())); <------
So your next block of code containing the Toast show statement will always be executed.
Remove the semi-colon
i am attempting to implement a built in controller that is part of the scoreloop library. the documentation states:
Basic Usage:
To invoke the TOS dialog if it was not accepted previously, the following code may be used:
final TermsOfServiceController controller = new TermsOfServiceController(new TermsOfServiceControllerObserver() {
#Override
public void termsOfServiceControllerDidFinish(final TermsOfServiceController controller, final Boolean accepted) {
if(accepted != null) {
// we have conclusive result.
if(accepted) {
// user did accept
}
else {
// user did reject
}
}
}
});
controller.query(activity);
but when i paste this into my code i get the following syntax errors:
am i using this incorrectly? how and where would this be used any ideas?
EDIT: after moving the statement to the method where i want to show the dialog i now get the following error:
You seem to be calling controller.query(activity) in a class body where a declaration is expected. Move the statement controller.query(activity) to a method where you would like to show the dialog.