Ich benutze braintree api, um Karte in App für Zahlungen zu bekommen. Es funktioniert Bußgelder und manchmal stürzt zufällig,BraintreeHttpClient.setBaseUrl (java.lang.String) auf eine Null-Objekt Referenz
Das ist mein stacktrace,
E/AndroidRuntime: FATAL EXCEPTION: Thread-833
Process: cl.tempclick, PID: 29509
java.lang.NullPointerException: Attempt to invoke virtual method 'com.braintreepayments.api.internal.HttpClient com.braintreepayments.api.internal.BraintreeHttpClient.setBaseUrl(java.lang.String)' on a null object reference
at com.braintreepayments.api.BraintreeFragment.setConfiguration(BraintreeFragment.java:488)
at com.braintreepayments.api.BraintreeFragment$5.onConfigurationFetched(BraintreeFragment.java:415)
at com.braintreepayments.api.ConfigurationManager.getConfiguration(ConfigurationManager.java:46)
at com.braintreepayments.api.BraintreeFragment.fetchConfiguration(BraintreeFragment.java:412)
at com.braintreepayments.api.BraintreeFragment.waitForConfiguration(BraintreeFragment.java:458)
at com.braintreepayments.api.TokenizationClient.tokenize(TokenizationClient.java:72)
at com.braintreepayments.api.Card.tokenize(Card.java:29)
at cl.tk.ui.activities.sub_activity.AddPayment$UIThreadHandler$1.run(AddPayment.java:364)
at java.lang.Thread.run(Thread.java:818)
Dies ist mein Code für die Aktivität,
package cl.tk.ui.activities.sub_activity;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import android.content.IntentFilter;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.support.v4.content.ContextCompat;
import android.support.v4.content.LocalBroadcastManager;
import android.support.v7.app.AppCompatActivity;
import android.view.MotionEvent;
import android.view.View;
import android.widget.Button;
import android.widget.ImageView;
import android.widget.TextView;
import com.braintreepayments.api.BraintreeFragment;
import com.braintreepayments.api.exceptions.InvalidArgumentException;
import com.braintreepayments.api.interfaces.PaymentMethodNonceCreatedListener;
import com.braintreepayments.api.models.CardBuilder;
import com.braintreepayments.api.models.PaymentMethodNonce;
import cl.tk.R;
import cl.tk.controllers.constants.Constants;
import cl.tk.controllers.constants.Enums_String;
import cl.tk.controllers.listeners.ProcessedResult;
import cl.tk.controllers.rest_api.RetrofitAdapters;
import cl.tk.ui.activities.Register;
import cl.tk.ui.fragments.dialog.DTDialog;
import cl.tk.ui.iBAPViews.editext.pattern.PatternedEditText;
import cl.tk.utility.CreditCard;
import cl.tk.utility.CustomException;
import cl.tek.utility.GeneralFunctions;
import cl.tk.utility.MonthYearPicker;
import cl.tk.utility.Validation;
import cl.tk.utility.fonts.FontsManager;
import retrofit.Callback;
import retrofit.RetrofitError;
import retrofit.client.Response;
public class AddPayment extends AppCompatActivity implements View.OnClickListener,View.OnTouchListener, ProcessedResult,PaymentMethodNonceCreatedListener
{
private Handler uiThreadHandler;
private TextView tvExpiryDate;
//private EditText edCvv,ed_cardHOlderName,edZip;
private PatternedEditText edCardNumber;
private MonthYearPicker myp;
private String mClientToken=null;
private CreditCard creditCard =null;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_add_payment);
uiThreadHandler = new UIThreadHandler();
initialze();
downloadBraintreeTOken();
}
private void downloadBraintreeTOken()
{
RetrofitAdapters.get().getBraintreeToken(new Callback<Response>() {
@Override
public void success(Response response, Response response2) {
parseResult(response);
}
@Override
public void failure(RetrofitError error) {
uiThreadHandler.sendEmptyMessage(Constants.ActivityBasicsCode.HIDEDIALOG);
Message message = uiThreadHandler.obtainMessage(Constants.ActivityBasicsCode.SHOWTOAST);
message.obj = error.getLocalizedMessage();
uiThreadHandler.sendMessage(message);
}
});
}
private void initialze()
{
GeneralFunctions.setToolbarMsgIconHide(this, Constants.ToolbarConstants.PAYMENTS, true);
Button buttonAdd=GeneralFunctions.findViewByIdAndCast(this,R.id.payment_bt_addCard);
buttonAdd.setOnClickListener(this);
GeneralFunctions.setColorSelector(ContextCompat.getColor(this, R.color.color175), ContextCompat.getColor(this, R.color.color1A9), buttonAdd);
TextView tv_defult=GeneralFunctions.findViewByIdAndCast(this,R.id.payment_ct_default);
tv_defult.setOnClickListener(this);
FontsManager.initFormAssets(this, Enums_String.FontsNameLato.SEMIBOLD.toString());
FontsManager.changeFonts(tv_defult);
edCardNumber=GeneralFunctions.findViewByIdAndCast(this,R.id.payment_ed_cardNumber);
tvExpiryDate=GeneralFunctions.findViewByIdAndCast(this,R.id.payment_tv_expiryDate);
tvExpiryDate.setOnTouchListener(this);
myp = new MonthYearPicker(this);
myp.build(new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
tvExpiryDate.setText(myp.getSelectedMonth() + 1 + "/" + myp.getSelectedYear());
}
}, null);
}
@Override
protected void onResume() {
super.onResume();
IntentFilter filter = new IntentFilter(Enums_String.LocalReceiver.INTERENT.toString());
LocalBroadcastManager.getInstance(this).registerReceiver(mMessageReceiver, filter);
}
@Override
protected void onPause() {
super.onPause();
LocalBroadcastManager.getInstance(this).unregisterReceiver(mMessageReceiver);
}
@Override
public void onClick(View v) {
switch (v.getId())
{
case R.id.payment_bt_addCard:
uiThreadHandler.sendEmptyMessage(Constants.ActivityBasicsCode.VALIDATION);
break;
}
}
@Override
public boolean onTouch(View v, MotionEvent event) {
if(event.getAction() == MotionEvent.ACTION_UP)
{
if(v.getId()==R.id.payment_tv_expiryDate)
{
if(myp.pickerDialog != null && !myp.pickerDialog.isShowing())
myp.pickerDialog.dismiss();
myp.show();
}
return true;
}
return false;
}
@Override
public <IResponse, IMethod, IExtra> void processedResult(IResponse iResponse, IMethod iMethod, IExtra iExtra) {
}
@Override
public <IResponse, IMethod> void processedResult(IResponse iResponse, IMethod iMethod) {
switch (iMethod.toString())
{
case Constants.CallbackConstants.VIEW_ERROR: {
Message message = uiThreadHandler.obtainMessage(Constants.ActivityBasicsCode.SETERROR);
message.obj=iResponse;
uiThreadHandler.sendMessage(message);
}
break;
case Constants.CallbackConstants.BACK:
finish();
break;
}
}
@Override
public void onPaymentMethodNonceCreated(final PaymentMethodNonce paymentMethodNonce) {
}
private void setError(String errorMsg) {
if (errorMsg.equalsIgnoreCase("cardNumber"))
GeneralFunctions.setError(null,String.format(getString(R.string.ed_error_invalid),edCardNumber.getTag().toString()),edCardNumber);
else if (errorMsg.equalsIgnoreCase("cardDate"))
GeneralFunctions.setError(null,String.format(getString(R.string.ed_error_invalid),tvExpiryDate.getTag().toString()),tvExpiryDate);
}
private class UIThreadHandler extends Handler {
@Override
public void handleMessage(Message msg)
{
switch (msg.what) {
case Constants.ActivityBasicsCode.CARDERROR:
GeneralFunctions.setError((CustomException)msg.obj,null,null);
break;
case Constants.ActivityBasicsCode.SETERROR:
setError(msg.obj.toString());
break;
case Constants.ActivityBasicsCode.SHOWTOAST:
{
String text=(String)msg.obj;
GeneralFunctions.showToast(text,AddPayment.this);
}
break;
case Constants.ActivityBasicsCode.HIDEDIALOG:
GeneralFunctions.hideProgressDialog(Constants.DialogConstants.Transparent, AddPayment.this);
break;
case Constants.ActivityBasicsCode.SHOWDIALOG:
{
DTDialog dtDialog=DTDialog.newInstance();
GeneralFunctions.showProgressDialog(dtDialog, Constants.DialogConstants.Transparent, AddPayment.this);
}break;
case Constants.ActivityBasicsCode.VALIDATION: {
new Thread(new Runnable() {
@Override
public void run()
{
try {
if(Validation.validate(AddPayment.this)) {
creditCard = new CreditCard(GeneralFunctions.getText(edCardNumber),GeneralFunctions.getText(tvExpiryDate),AddPayment.this);
boolean validation = creditCard.validateCard();
if (validation) {
if(mClientToken==null) {
downloadBraintreeTOken();
Message message = uiThreadHandler.obtainMessage(Constants.ActivityBasicsCode.SHOWTOAST);
message.obj = getString(R.string.toast_payment_token);
uiThreadHandler.sendMessage(message);
return;
}
BraintreeFragment braintreeFragment= BraintreeFragment.newInstance(AddPayment.this, mClientToken);
if(null==braintreeFragment)
{
Message message = uiThreadHandler.obtainMessage(Constants.ActivityBasicsCode.SHOWTOAST);
message.obj = getString(R.string.toast_payment_fragment);
uiThreadHandler.sendMessage(message);
uiThreadHandler.sendEmptyMessage(Constants.ActivityBasicsCode.SHOWDIALOG);
}
else {
CardBuilder cardBuilder = new CardBuilder()
.cardNumber(creditCard.getNumber().replaceAll("-", "").trim())
.expirationDate(creditCard.getExpriyDate());
com.braintreepayments.api.Card.tokenize(braintreeFragment, cardBuilder); //On this line my app crashes randomly
}
}
}
}catch (CustomException e)
{
Message message = uiThreadHandler.obtainMessage(Constants.ActivityBasicsCode.CARDERROR);
message.obj=e;
uiThreadHandler.sendMessage(message);
} catch (InvalidArgumentException e) {
e.printStackTrace();
}
}
}).start();
break;
}
}
super.handleMessage(msg);
}
}
}
Dies ist meine gradle Version, kompilieren 'com.braintreepayments.api: braintree: 2. +'
ja, zuerst lade ich das Braintree-Token vom Server in onCreate() und überprüfe dann noch einmal, ob es null ist, dann versuch nochmal Token zu downloaden .... und die Karte ist wohlgeformt .... wie diese nur stürzt weniger oft ab. – TheReprator
Wir haben das Problem erkannt und einen Fix veröffentlicht. Bitte aktualisiere deine Version des Android v.zero SDK auf 2.2.4. Weitere Informationen finden Sie hier: https://github.com/braintree/braintree_android/issues/89 –