This question already has answers here:
What is a NullPointerException, and how do I fix it?
(12 answers)
Closed 4 years ago.
I got this from a tutorial and made some changes but I'm unable to figure out why it's pointing to a null object.
Here are the codes:
HomeActivity.java
final DatabaseReference dbRef = FirebaseDatabase.getInstance().getReference(Common.token_table).child(Common.user_workers_table).child(stringWorkerType);
dbRef.orderByKey().equalTo(workerId).addListenerForSingleValueEvent(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
for (DataSnapshot ds: dataSnapshot.getChildren()) {
Token token = ds.getValue(Token.class);
//Make raw payload - convert LatLng to json
String json_lat_lng = new Gson().toJson(new LatLng(mLastLocation.getLatitude(), mLastLocation.getLongitude()));
String workerToken = FirebaseInstanceId.getInstance().getToken();
Notification notification = new Notification(workerToken, json_lat_lng);
Sender content = new Sender(token.getToken(), notification);
//IFCMService mService;
mService.sendMessage(content).enqueue(new Callback<FCMResponse>() {
#Override
public void onResponse(Call<FCMResponse> call, Response<FCMResponse> response) {
if(response.body().success == 1) {
Log.d("LOG/I", "Request sent.");
} else {
Toast.makeText(HomeActivity.this, "Request not sent.", Toast.LENGTH_SHORT).show();
}
}
IFCMService.java
public interface IFCMService {
#Headers({
"Content-Type:application/json",
"Authorization:key=AAAAJorGt9o:APA91bFgAhEUL9oCFSD9wnLEflqw5hip6Q7kZ7E4JPX7mY5NLTb78lnvlbhMikojpa2Gp-2LnVE1pfXNhyXY25JFj-omR9_OgDN5qcj2rvqUeaYIolhi1uNKa2o3sErk-15PjojYEy7z"
})
#POST("fcm/send")
Call<FCMResponse> sendMessage(#Body Sender body);
}
FCMResponse.java
public class FCMResponse {
public long multicast_id;
public int success;
public int failure;
public int canonical_ids;
public List<Result> results;
public FCMResponse() {
}
public FCMResponse(long multicast_id, int success, int failure, int canonical_ids, List<Result> results) {
this.multicast_id = multicast_id;
this.success = success;
this.failure = failure;
this.canonical_ids = canonical_ids;
this.results = results;
}
public long getMulticast_id() {
return multicast_id;
}
public void setMulticast_id(long multicast_id) {
this.multicast_id = multicast_id;
}
public int getSuccess() {
return success;
}
public void setSuccess(int success) {
this.success = success;
}
public int getFailure() {
return failure;
}
public void setFailure(int failure) {
this.failure = failure;
}
public int getCanonical_ids() {
return canonical_ids;
}
public void setCanonical_ids(int canonical_ids) {
this.canonical_ids = canonical_ids;
}
public List<Result> getResults() {
return results;
}
public void setResults(List<Result> results) {
this.results = results;
}
}
Sender.class
public class Sender {
public String to;
public Notification notification;
public Sender() {
}
public Sender(String to, Notification notification) {
this.to = to;
this.notification = notification;
}
public String getTo() {
return to;
}
public void setTo(String to) {
this.to = to;
}
public Notification getNotification() {
return notification;
}
public void setNotification(Notification notification) {
this.notification = notification;
}
}
It's an app like uber, what this codes supposed to be doing is when the driver/client app request and a driver/worker is available, it will give a notification to the driver/worker. But it does nothing and I'm getting an error at
java.lang.NullPointerException
at
com.fixitph.client.HomeActivity$22$1.onResponse(HomeActivity.java:1129)
1129 is the if(response.body().success == 1) { line
Let me know if you need more information on this. Thank you in advance :)
The value is Null(No data). So Null pointer exception coming. Log your Response and check data is coming or not
Your response.body() might be null and you are trying to access a field of a null object.
Try this:
if(response.isSuccessful()) {
Log.d("LOG/I", "Request sent.");
} else {
Toast.makeText(HomeActivity.this, "Request not sent.", Toast.LENGTH_SHORT).show();
}
This is because either your FCMResponse class is not mapped to the class model correctly or you are returning a null value. Make sure FCMResponse is mapped and can be deserialized correctly.
You can use #SerializedName("name_here") if you need to differ serialized field names from class field names.
EDIT
I would call the endpoint using Postman or any other similar tool and see the server's response body. I would then compare the FCMResponse class fields and field names with the response body to decide if they match exactly or not.
You FCMResponse class actually represents the body of your response not the response itself. Maybe you are mistaken there.
Related
When I try to call rest API in the android studio I get an error that:
E/error: End of input at line 1 column 1 path $
I use firebase for the database and retrofit2 library.
But when I call the values a go to the firebase database and call the onFailure in call.enqueue() method.
public class APis {
public static final String URL = "http://192.168.178.43:8081/api/";
public static userService setuser() {
return client.getClient(URL).create(userService.class);
}
}
public interface userService {
#Headers("Content-Type: application/json")
#POST("signup")
Call<userlog> adduser(#Body userlog userlog);
}
public class userlog {
#SerializedName("email")
#Expose
private String emial_;
#SerializedName("password")
#Expose
private String password_;
#SerializedName("name")
#Expose
private String name_;
public userlog() {
}
public userlog(String emial_, String password, String name_) {
this.emial_ = emial_;
this.password_ = password;
this.name_ = name_;
}
public String getEmial_() {
return emial_;
}
public void setEmial_(String emial_) {
this.emial_ = emial_;
}
public String getPassword_() {
return password_;
}
public void setPassword_(String password_) {
this.password_ = password_;
}
public String getName_() {
return name_;
}
public void setName_(String name_) {
this.name_ = name_;
}
}
public void setPassword_(String password_) {
this.password_ = password_;
}
}
private void adduser_(userlog userll) {
service = APis.setuser();
Call<userlog> call = service.adduser(userll);
call.enqueue(new Callback<userlog>() {
#Override
public void onResponse(Call<userlog> call, Response<userlog> response) {
if (response.isSuccessful()) {
Toast.makeText(getApplicationContext(), "Success", Toast.LENGTH_SHORT).show();
/* userdetails.setUserid(firebaseAuth.getUid());
userdetails.setEmail_(emailId.getText().toString());
startActivity(new Intent(SignupActivity.this, MainnewActivity.class));*/
}
}
#Override
public void onFailure(Call<userlog> call, Throwable t) {
Log.e("error", t.getMessage());
Toast.makeText(getApplicationContext(), "not Successdd", Toast.LENGTH_SHORT).show();
}
});
}
when I call "adduser_(userll)" method, I get a notification that "not Successdd".
The problem related to retrofit, i think the problem because the response of the call come as null or empty
you can create NullConverterFactory.class :
public class NullConverterFactory extends Converter.Factory {
#Override
public Converter<ResponseBody, ?> responseBodyConverter(Type type, Annotation[] annotations, Retrofit retrofit) {
final Converter<ResponseBody, ?> delegate = retrofit.nextResponseBodyConverter(this, type, annotations);
return new Converter<ResponseBody, Object>() {
#Override
public Object convert(ResponseBody body) throws IOException {
if (body.contentLength() == 0) return null;
return delegate.convert(body);
}
};
}
}
and add to the create of the retrofit
baseUrl(Config.URL+"/")
.client(okHttpClient)
// -----add here-------
.addConverterFactory(new NullConverterFactory())
//---------------------
.addConverterFactory(GsonConverterFactory.create())
.build()
Today i was working on my homework, which it was making simple apps with retrofit calls and learning new things for code improvement, and somehow i saw there are so many ways to write less code and do better with OOP. So to improve my code experiment I'm trying to do my retrofit calls with OOP. So this is my issue right now:
Consider a simple retrofit call with CompositeDisposable( I'm developing my simples with MVP ) :
mView.showProgress(1);
RequestRemainingProductsRequest requestRemainingProductsRequest = new RequestRemainingProductsRequest();
requestRemainingProductsRequest.distributorId = distributorId;
requestRemainingProductsRequest.requestCode = requestCode;
requestRemainingProductsRequest.requestType = 1;
NetworkCalls.getObservableList();
compositeDisposable.add(getApi().requestRemainingProducts(requestRemainingProductsRequest)
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(new Consumer<List<Products>>() {
#Override
public void accept(List<Products> products) throws Throwable {
mView.hideProgress(1);
mView.getRemainingProducts(products);
}
}, new Consumer<Throwable>() {
#Override
public void accept(Throwable throwable) throws Exception {
mView.hideProgress(1);
mView.showLog(throwable.getMessage().toString());
}
}));
And, Another retrofit call without CompositeDisposable :
ProductSellerRequest productSellerRequest = new ProductSellerRequest();
productSellerRequest.centralId = centralsList.get(i).requestCentralId;
productSellerRequest.requestType = 0;
productSellerRequest.productId = Constant.currentProduct.productId;
getApi().checkProductExistInRequest(productSellerRequest)
.enqueue(new Callback<ProductSellerCallback>() {
#Override
public void onResponse(Call<ProductSellerCallback> call, Response<ProductSellerCallback> response) {
hideProgress(myViewHolder);
showAddDialog(myViewHolder, v, response, i);
}
#Override
public void onFailure(Call<ProductSellerCallback> call, Throwable t) {
hideProgress(myViewHolder);
}
});
So let's say I created a java class with NetworkCalls.java, and created 2 voids like this:
public static void getObservableList()
{
}
public static void getWithoutObservableList()
{
}
How to handle my response to return to my Presenter/Activity?
This is how i using StringBuilder and returning my String, but I'm trying do similiar way to make repository for my Network Calls, then learn all all i should know about Repository Pattern.
public static String TotalPriceStringBuilder(int Price){
String DecimalPrice = String.format("%,d", Price);
String FinalString = new StringBuilder("Price : ").append(DecimalPrice).append(" $").toString();
return String.valueOf(FinalString);
}
This is what I've tried, but i still don't know how to fix it or make it work, what to return, and how to return and etc... :
private static ApiClient mApi;
private List<Products> receivedProducts;
private int hideProgress;
private boolean status;
private String message;
public void getObservableList(RequestRemainingProductsRequest requestRemainingProductsRequest, CompositeDisposable compositeDisposable)
{
compositeDisposable.add(getApi().requestRemainingProducts(requestRemainingProductsRequest)
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(new Consumer<List<Products>>() {
#Override
public void accept(List<Products> products) throws Throwable {
hideProgress = 1;
receivedProducts = products;
status = TRUE;
}
}, new Consumer<Throwable>() {
#Override
public void accept(Throwable throwable) throws Exception {
hideProgress = 1;
status = FALSE;
message = throwable.getMessage().toString();
}
}));
if (status == TRUE) {
return hideProgress, receivedProducts, status;
} else {
return hideProgress, message, status;
}
}
public ApiClient getApi() {
if (mApi == null) {
mApi = ApiService.getClient().create(ApiClient.class);
}
return mApi;
}
If i use static method I'll get bunch of errors like can't be refrenced from a static context or etc...
I am trying to send a POST request using Retrofit library.
Here is my MarketApiCalls interface and my networking method doing the work -
public interface MarketApiCalls {
#POST("api/Search/Vendor/Multiple")
Call<String> getVendors(
#Query("take") int take,
#Query("page") int page,
#Body String json
);
}
private void initNetworking() {
String body = "[{ \"filters\": { \"VendorName\": { \"value\": [\"*\"], \"cretiria\": 0, \"type\": 5 } } }]"
Retrofit retrofit = new Retrofit.Builder()
.baseUrl("https://search.myverte.com/")
.addConverterFactory(GsonConverterFactory.create())
.build();
marketApiCalls = retrofit.create(MarketApiCalls.class);
Call<String> vendorsCall = marketApiCalls.getVendors(9, 0, body);
vendorsCall.enqueue(new Callback<String>() {
#Override
public void onResponse(Call<String> call, Response<String> response) {
if (!response.isSuccessful()) {
Toast.makeText(getContext(), "Not successful", Toast.LENGTH_SHORT).show();
return;
}
Log.d("response body", response.body());
}
#Override
public void onFailure(Call<String> call, Throwable t) {
}
});
}
Here is the JSON I need to attach to the POST request as a body -
[{
"filters": {
"VendorName": {
"value": ["*"],
"cretiria": 0,
"type": 5
}
}
}]
The issue is that I am getting error code 400. It does not specify that the body is missing or corrupt , just gives 400 error saying the following error -
What am I missing? I am suspicious that I am not giving the body as needed.
edit -
I have tried the following solution yet the same error occurs -
public class VendorBodyModel {
private Filters filters;
public VendorBodyModel() {
}
public VendorBodyModel(Filters filters) {
this.filters = filters;
}
public Filters getFilters() {
return filters;
}
public void setFilters(Filters filters) {
this.filters = filters;
}
public class Filters {
private VendorName vendorName;
public Filters() {
}
public Filters(VendorName vendorName) {
this.vendorName = vendorName;
}
}
public class VendorName {
private String[] value;
private int cretiria;
private int type;
public VendorName(String[] value, int cretiria, int type) {
this.value = value;
this.cretiria = cretiria;
this.type = type;
}
public String[] getValue() {
return value;
}
public void setValue(String[] value) {
this.value = value;
}
public int getCretiria() {
return cretiria;
}
public void setCretiria(int cretiria) {
this.cretiria = cretiria;
}
public int getType() {
return type;
}
public void setType(int type) {
this.type = type;
}
}
}
public interface MarketApiCalls {
#POST("api/Search/Vendor/Multiple")
Call<String> getVendors(
#Query("take") int take,
#Query("page") int page,
#Body VendorBodyModel bodyModel
);
}
private void initNetworking() {
Retrofit retrofit = new Retrofit.Builder()
.baseUrl("https://search.myverte.com/")
.addConverterFactory(GsonConverterFactory.create())
.build();
marketApiCalls = retrofit.create(MarketApiCalls.class);
String[] array = {"*"};
int cretiria = 5;
int type = 0;
VendorBodyModel.VendorName vendorName = new VendorBodyModel().new VendorName(array, 5, 0);
VendorBodyModel.Filters filters = new VendorBodyModel().new Filters(vendorName);
VendorBodyModel vendorBodyModel = new VendorBodyModel(filters);
Call<String> vendorsCall = marketApiCalls.getVendors(9, 0, vendorBodyModel);
vendorsCall.enqueue(new Callback<String>() {
#Override
public void onResponse(Call<String> call, Response<String> response) {
if (!response.isSuccessful()) {
Toast.makeText(getContext(), "Not successful", Toast.LENGTH_SHORT).show();
return;
}
Toast.makeText(getContext(), "FUCKING SUCCESS!!!", Toast.LENGTH_SHORT).show();
Log.d("response body", response.body());
}
#Override
public void onFailure(Call<String> call, Throwable t) {
}
});
}
What am I missing?
Just simply create post model class like this:
class Body {
Filters filters;
int parameter2;
}
class Filters {
VendorName VendorName;
.......
.......
.......
}
and use it like this:
#POST("api/Search/Vendor/Multiple")
Call<String> getVendors(
#Query("take") int take,
#Query("page") int page,
#Body Body json
);
And also make sure that Body class field namings matches required namings, also dont forget that list or array is marked with [...], simple pojo {...}
Here is full body class in Kotlin:
data class Body(
#SerializedName("filters")
val filters: Filters? = Filters()
)
data class Filters(
#SerializedName("VendorName")
val vendorName: VendorName? = VendorName()
)
data class VendorName(
#SerializedName("value")
val value: List<String?>? = listOf(),
#SerializedName("cretiria")
val cretiria: Int? = 0,
#SerializedName("type")
val type: Int? = 0
)
Instead of string create JsonObject and send it as #Body JsonObject request
I am using Google Books API to display a list of various books by searching for terms, queries....
So far everything is working as it is supposed to be, one problem though, I need to get a book by it's id, I believe the problem is with my BookResponse class
UPDATE I figured I should add a Serialized id in BookItems class but I don't know where to go from there
PS. below you will find every class and a an image attached to display the JSON structure
Search in MainActivity
ApiInterface apiService =
RetrofitInstance.getRetrofitInstance().create(ApiInterface.class);
retrofit2.Call<BookResponce> call = apiService.getBooksById("zyTCAlFPjgYC", BOOKS_API_KEY);
call.enqueue(new Callback<BookResponce>() {
#Override
public void onResponse(retrofit2.Call<BookResponce> call, Response<BookResponce> response) {
bookResp = response.body();
for (int i = 0; i == 0; i++){
bookList.add(i, bookResp.getBooks().get(i).getBookData());
}
cAdapter.notifyDataSetChanged();
}
#Override
public void onFailure(retrofit2.Call<BookResponce> call, Throwable t) {
Toast.makeText(this, "failed", Toast.LENGTH_LONG).show();
}
});
BookResponse class
public class BookResponce {
#SerializedName(value="items")
ArrayList<BookItems> bookItems;
#SerializedName(value="totalItems")
int totalItems;
public int getTotalItems() { return totalItems; }
public ArrayList<BookItems> getBooks() { return bookItems; }
}
BookItems class
public class BookItems {
//This is what I added
#SerializedName(value = "id")
String id;
#SerializedName(value="volumeInfo")
Book bookData;
//and this...
public String getId() {
return id;
}
public Book getBookData(){return bookData; }
}
API Interface class
public interface ApiInterface {
#GET("volumes/{id}")
Call<BookResponce> getBooksById(#Path("id") String bookId,
#Query("API_KEY") String apiKey);
#GET("volumes")
Call<BookResponce> getBooksByQuery(#Query("q") String query,
#Query("API_KEY") String apiKey, #Query("maxResults") int maxResults);
}
when ever you're performing a search, after adding items in your bookList just add:
bookList.get(i).setBookId(bookResp.getBooks().get(i).getId());
Here's the full example in your case:
ApiInterface apiService =
RetrofitInstance.getRetrofitInstance().create(ApiInterface.class);
retrofit2.Call<BookResponce> call = apiService.getBooksById("zyTCAlFPjgYC", BOOKS_API_KEY);
call.enqueue(new Callback<BookResponce>() {
#Override
public void onResponse(retrofit2.Call<BookResponce> call, Response<BookResponce> response) {
bookResp = response.body();
for (int i = 0; i == 0; i++){
bookList.add(i, bookResp.getBooks().get(i).getBookData());
//This is what you must add
bookList.get(i).setBookId(bookResp.getBooks().get(i).getId());
}
cAdapter.notifyDataSetChanged();
}
#Override
public void onFailure(retrofit2.Call<BookResponce> call, Throwable t) {
Toast.makeText(this, "failed", Toast.LENGTH_LONG).show();
}
});
If anyone has a more optimal solution is welcome to edit/add his!
I am trying to save an object to Parse cloud and getting its objectId if it was successfully saved. I am printing the Exceptions in the logs if there is any. After clicking the save button, there is no ParseException shown in the logs but the objectId returned is always null.
this is my subclass:
#ParseClassName("PetOwner")
public class PetOwner extends ParseObject {
public PetOwner(){ super(); }
public String getOwnerId(){
return getString("objectId");
}
public String getOwnerName(){
return getString("name");
}
public ParseGeoPoint getLocation(){
return getParseGeoPoint("location");
}
public String getPhoneNumber(){
return getString("phoneNumber");
}
public Number getRadius(){
return getNumber("searchRadius");
}
public Installation getInstallation(){
return (Installation) getParseObject("installation");
}
public String getBackupEmail(){
return getString("backupemail");
}
public String getEmail(){
return getString("email");
}
public Date createdAt(){
return getDate("createdAt");
}
public Date updatedAt(){
return getDate("updatedAt");
}
public void setOwnerName(String name){ put("name", name); }
public void setPhoneNumber(String phone){ put("phoneNumber", phone); }
public void setEmail(String email){ put("email", email); }
public static ParseQuery<PetOwner> getQuery(){
return ParseQuery.getQuery(PetOwner.class);
}
}
This is the code I am writing to save the object to the cloud after getting the values of the name, phone number and email fields entered by the users in EditText view.
FloatingActionButton saveProfile = (FloatingActionButton) findViewById(R.id.save_button);
saveProfile.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
if (nameChanged && checkPhoneNumber() && checkEmail()) {
final PetOwner petOwner = new PetOwner();
petOwner.setOwnerName(userName.getText().toString());
petOwner.setPhoneNumber(phoneNumber.getText().toString());
petOwner.setEmail(email.getText().toString());
petOwner.saveInBackground(new SaveCallback() {
#Override
public void done(ParseException e) {
if (e == null) {
Log.d(TAG, "after saveinbackground is done");
Log.d(TAG, petOwner.getOwnerId() + " is the saved object id");
} else {
Log.d(TAG, "saveinbackground NOT done");
Log.e(TAG, "exception", e);
}
}
});
}
}
});
The logs show this:
04-09 19:33:50.385 31818-31818/us.furalert.Furalert D/PetOwnerDetails: after saveinbackground is done
04-09 19:33:50.385 31818-31818/us.furalert.Furalert D/PetOwnerDetails: null is the saved object id
I am not able to make out what is wrong with my code. Why is the objectId null?
Please help!
Replace getString("objectId") with getObjectId() as ParseObjects has a built-in method to retrieve the objectId