Volley AppController class object returning null - java

I am making an app that makes a JsonObjectRequest and retrieves a JSON data from an URL using the Volley Networking Library for android.
AppController.java
public class AppController extends AppCompatActivity {
public static final String TAG = AppController.class.getSimpleName();
private RequestQueue mRequestQueue;
private static AppController mInstance;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
mInstance = this;
}
public static synchronized AppController getInstance(){
return mInstance;
}
public RequestQueue getRequestQueue(){
if(mRequestQueue == null){
mRequestQueue = Volley.newRequestQueue(getApplicationContext());
}
return mRequestQueue;
}
public <T> void addToRequestQueue(Request<T> req) {
req.setTag(TAG);
getRequestQueue().add(req);
}
}
Method in MainActivity.class
private void makeJSONObjectRequest() {
showDialog();
JsonObjectRequest jsonObjReq = new JsonObjectRequest(Request.Method.GET,
urlJsonObj, (String) null, new Response.Listener<JSONObject>() {
#Override
public void onResponse(JSONObject response) {
Log.d(TAG, response.toString());
try {
//Parsing JSON Object response
String name = response.getString("name");
String email = response.getString("email");
JSONObject phone = response.getJSONObject("phone");
String home = phone.getString("home");
String mobile = phone.getString("mobile");
jsonResponse = "";
jsonResponse += "Name: " + name + "\n\n";
jsonResponse += "Email: " + email + "\n\n";
jsonResponse += "Home: " + home + "\n\n";
jsonResponse += "Mobile: " + mobile + "\n\n";
txtResponse.setTag(jsonResponse);
}
catch (JSONException e) {
e.printStackTrace();
Toast.makeText(getApplicationContext(), "Error: " + e.getMessage(), Toast.LENGTH_SHORT).show();
}
hideDialog();
}
},
new ErrorListener() {
#Override
public void onErrorResponse(VolleyError volleyError) {
VolleyLog.d(TAG+"Error:"+ volleyError.getMessage());
Toast.makeText(getApplicationContext(), volleyError.getMessage(), Toast.LENGTH_SHORT).show();
hideDialog();
}
});
/*THE ERROR OCCURS HERE! */
//adding request to the RequestQueue
AppController.getInstance().addToRequestQueue(jsonObjReq);
}
It gives the following error:
java.lang.NullPointerException: Attempt to invoke virtual method 'void com.example.h8pathak.volleyjson.AppController.addToRequestQueue(com.android.volley.Request)' on a null object reference
How can I rectify this code?

Your AppController class needs to extend Application class instead of the AppCompatActivity class.
And remember to update your Manifest as well. ie. Add this class in your AndroidManifest.xml using name attribute for <application> tag.
<application
android:name=".AppController"/>

i think you should create the "AppController" like this :
public class AppController {
private static AppController mInstance;
private RequestQueue mRequestQueue;
private static Context mCtx;
private AppController(Context context){
mCtx = context;
mRequestQueue = getRequestQueue();
}
public static synchronized AppController getInstance(Context context) {
if (mInstance == null) {
mInstance = new AppController(context);
}
return mInstance;
}
public RequestQueue getRequestQueue() {
if (mRequestQueue == null) {
mRequestQueue = Volley.newRequestQueue(mCtx.getApplicationContext());
}
return mRequestQueue;
}
public <T> void addToRequestQueue(#NonNull final Request<T> request) {
getRequestQueue().add(request);
}
public <T> void addToRequestQueueWithTag(#NonNull final Request<T> request, String tag) {
request.setTag(tag);
getRequestQueue().add(request);
}
}
and the MainActivity.class
//adding request to the RequestQueue
AppController.getInstance(this).addToRequestQueue(jsonObjReq);

you can't use an Activity like a Singleton. An Activity is a screen of your app and it could be in different states during the usage of your app. You are also leaking it, since you keep a static reference to it. For your purpose, if you need a Context, extend Application instead of AppCompatActivity, and register it in your Manifest.

Don't you forget to initialize the RequestQueue Object. You need to initialize the RequestQueue inside the onCreate method, like you can see in the example:
(Else when you call request.add(jsonObjectRequest) the application will try to reference the null object)
RequestQueue request;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
//request qwe
request= Volley.newRequestQueue(this);
}

Related

Volley Request Queue in Android Fragment (getApplicationContext may produce NullPointerException)

I just want to load data from my localhost using recyclerview inside fragment but nothing shows and it says getApplicationContext may produce NullPointerException.
The error is on the
Volley.newRequestQueue(getActivity().getApplicationContext()).add(stringRequest);
I tried the code on main activity and it works fine.
public class UpdateFragment extends Fragment {
private static final String URL = "http://192.168.1.32/CAGELCOII_APP/api.php";
RecyclerView recyclerView;
ItemAdapter adapter;
List<Item> itemList;
public UpdateFragment() {
// Required empty public constructor
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
// Inflate the layout for this fragment
View view = inflater.inflate(R.layout.fragment_update, container, false);
itemList = new ArrayList<>();
recyclerView = (RecyclerView) view.findViewById(R.id.recyclerView);
recyclerView.setHasFixedSize(true);
recyclerView.setLayoutManager(new LinearLayoutManager(getActivity()));
loadItem();
adapter = new ItemAdapter(getActivity(), itemList);
recyclerView.setAdapter(adapter);
return view;
}
private void loadItem(){
StringRequest stringRequest = new StringRequest(Request.Method.GET, URL,
new Response.Listener<String>() {
#Override
public void onResponse(String response) {
try {
JSONArray products = new JSONArray(response);
for(int i =0; i < products.length(); i++){
JSONObject productObject = products.getJSONObject(i);
int id = productObject.getInt("id");
String description = productObject.getString("description");
String agency = productObject.getString("agency");
String date = productObject.getString("date");
String time = productObject.getString("time");
String image = productObject.getString("image");
Item item = new Item(id, description, agency, date, time, image);
itemList.add(item);
}
adapter = new ItemAdapter(getActivity(), itemList);
recyclerView.setAdapter(adapter);
} catch (JSONException e) {
e.printStackTrace();
}
}
},
new Response.ErrorListener() {
#Override
public void onErrorResponse(VolleyError error) {
Toast.makeText(getActivity(), error.getMessage(), Toast.LENGTH_SHORT).show();
}
});
Volley.newRequestQueue(getActivity().getApplicationContext()).add(stringRequest);
}
}
You'll have to make sure your fragment isAdded() to activity when calling getActivity() otherwise you'll get a NullPointerException since getActivity() returns the activity hosting the fragment.
If you always want to use application context, due to its non-dying lifecycle you can retrieve it across the entire app using this static function:
App.java
public class App extends Application {
private static Context sAppContext;
public void onCreate() {
super.onCreate();
sAppContext = this;
}
public static Context getContext() {
return sAppContext;
}
}
AndroidManifest.xml
...
<application
android:name=".App"
...>
</application>
And you can use it in your code as:
Volley.newRequestQueue(App.getContext()).add(stringRequest);
Please Try This code
RequestQueue mRequestQueue = Volley.newRequestQueue(getActivity());
mRequestQueue.add(jsonObjReq);
There are two way to hit volley request:
First
use app controller class
AppController
public class AppController extends Application {
public static final String TAG = AppController.class.getSimpleName();
private RequestQueue mRequestQueue;
private ImageLoader mImageLoader;
private static AppController mInstance;
#Override
public void onCreate() {
super.onCreate();
mInstance = this;
}
public static synchronized AppController getInstance() {
return mInstance;
}
public RequestQueue getRequestQueue() {
if (mRequestQueue == null) {
mRequestQueue = Volley.newRequestQueue(getApplicationContext());
}
return mRequestQueue;
}
public ImageLoader getImageLoader() {
getRequestQueue();
if (mImageLoader == null) {
mImageLoader = new ImageLoader(this.mRequestQueue,
new ImageClass());
}
return this.mImageLoader;
}
public void addToRequestQueue(Request req, String tag) {
// set the default tag if tag is empty
req.setTag(TextUtils.isEmpty(tag) ? TAG : tag);
getRequestQueue().add(req);
}
public void addToRequestQueue(Request req) {
req.setTag(TAG);
getRequestQueue().add(req);
}
public void cancelPendingRequests(Object tag) {
if (mRequestQueue != null) {
mRequestQueue.cancelAll(tag);
}
}
}
**ImageClass **
public class ImageClass extends LruCache<String, Bitmap> implements
ImageCache {
public static int getDefaultLruCacheSize() {
final int maxMemory = (int) (Runtime.getRuntime().maxMemory() / 1024);
final int cacheSize = maxMemory / 8;
return cacheSize;
}
public ImageClass() {
this(getDefaultLruCacheSize());
}
public ImageClass(int sizeInKiloBytes) {
super(sizeInKiloBytes);
}
#Override
protected int sizeOf(String key, Bitmap value) {
return value.getRowBytes() * value.getHeight() / 1024;
}
#Override
public Bitmap getBitmap(String url) {
return get(url);
}
#Override
public void putBitmap(String url, Bitmap bitmap) {
put(url, bitmap);
}
}
manifest
<application
android:allowBackup="true"
android:name=".AppController"
android:icon="#mipmap/ic_launcher"
android:label="#string/app_name"
android:roundIcon="#mipmap/ic_launcher_round"
android:supportsRtl="true"
android:theme="#style/AppTheme">
android:name=".AppController"
add in menifest
MainActivity
String url = Global.BASE_URL + "api/";
StringRequest jsonObjReq = new StringRequest(Request.Method.POST, url,
new com.android.volley.Response.Listener<String>() {
#Override
public void onResponse(String response) {
Log.e(TAG, response.toString());
}
}, new com.android.volley.Response.ErrorListener() {
#Override
public void onErrorResponse(VolleyError error) {
//Error Log
VolleyLog.d(TAG, "Error: " + error.getMessage());
}
}) {
#Override
protected Map<String, String> getParams() {
//Pass the parameters to according to the API.
Map<String, String> params = new HashMap<String, String>();
params.put("API_HASH", "hasKey");
Log.e(TAG, "splash paramsTest----" + params);
return params;
}
};
/* ----Adding request to request queue----*/
AppController.getInstance().addToRequestQueue(jsonObjReq,
GlobalString.cancel_login_api);
Second
RequestQueue mRequestQueue = Volley.newRequestQueue(getActivity());
mRequestQueue.add(jsonObjReq);

Android volley singleton getInstance(this) fails when performing a http request

Am new to android and i have just checked out volley android library and i want to use it in my custom http request bu this fails with error in android studio at .getInstance
I have tried the following
So am using android studio and have the following folder structure
com.geowan .....
frontend
1.LoginActivity
helpers
ApiSingleTon
So in my ApiSingleton i have
public class ApiSingleton {
private static ApiSingleton mInstance;
private RequestQueue mRequestQueue;
private static Context mCtx;
private ImageLoader mImageLoader;
private ApiSingleton(Context context) {
mCtx = context;
mRequestQueue = getRequestQueue();
....stuff copy pasted from volley docs on IMage disc cache loader
}
public RequestQueue getRequestQueue() {
if (mRequestQueue == null) {
// getApplicationContext() is key, it keeps you from leaking the
// Activity or BroadcastReceiver if someone passes one in.
mRequestQueue = Volley.newRequestQueue(mCtx.getApplicationContext());
}
return mRequestQueue;
}
public <T> void addToRequestQueue(Request<T> req) {
getRequestQueue().add(req);
}
public ImageLoader getImageLoader() {
return mImageLoader;
}
}
Now to my java login code i have
ApiSingleton singleton;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_login);
login_btn.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
trylogin(); //login method
}
});
}
tryLogin(){ //trying to emulate a http request
//proceed with authentication
JsonObjectRequest jsonObjectRequest = new JsonObjectRequest
(Request.Method.GET, loginurl, null, new Response.Listener<JSONObject>() {
#Override
public void onResponse(JSONObject response) {
Log.i(TAG, response.toString());
}
}, new Response.ErrorListener() {
#Override
public void onErrorResponse(VolleyError error) {
// TODO: Handle error
Log.i(TAG, error.toString());
}
});
}
singleton.getInstance(this).addToRequestQueue(jsonObjectRequest); //fails
The above throws an error at
singleton.getInstance(this)
Where could i be going wrong.
First I guess you Need To Read More About Singleton
Second
singleton.getInstance(this)
this Means You Have A Function Called getInstance return the class type in your class
So I guess You Need to Add this
public static synchronized AppSingleton getInstance(Context context) {
if (mAppSingletonInstance == null) {
mAppSingletonInstance = new AppSingleton(context);
}
return mAppSingletonInstance;
}

Expression expected error on Volley requests

I am getting an error called expression expected inside the bracket in this line. Volley.newRequestQueue(MainActivity); . This class is on another activity other than my MainActivity. Here is the snippet of my code:
public void youFunctionForVolleyRequest(final ServerCallbackJava callback) {
RequestQueue queue = Volley.newRequestQueue(MainActivity);
String url = "https://maps.googleapis.com/maps/api/distancematrix/json?units=metric&origins=22.2913,113.947&destinations=WanChai&mode=driving&key="REMOVED";
JsonObjectRequest jsonObjReq = new JsonObjectRequest(Request.Method.POST,
url, null, new Response.Listener<JSONObject>()
{
#Override
public void onResponse(JSONObject response) {
callback.onSuccess(response); // call call back function here
}
}, new Response.ErrorListener() {
#Override
public void onErrorResponse(VolleyError error) {
//VolleyLog.d("Volley error json object ", "Error: " + error.getMessage());
}
})
{
#Override
public String getBodyContentType ()
{
return "application/json";
}
};
// Adding request to request queue
queue.add(jsonObjReq);
}
}
As you have created a class inside a activity/fragment, while calling the class you must pass the context of the activity and same pass to this function and replace the RequestQueue queue = Volley.newRequestQueue(MainActivity); with RequestQueue queue = Volley.newRequestQueue(mContext); the declared context inside your class.
You can do it with the help of following code snippet :
public class Main2Activity extends AppCompatActivity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main2);
Button button = (Button)findViewById(R.id.btn);
button.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
request r = new request(Main2Activity.this);
r.youFunctionForVolleyRequest();
}
});
}
class request{
Context ctx;
public request(Context mContext) {
ctx = mContext;
}
public void youFunctionForVolleyRequest() {
RequestQueue queue = Volley.newRequestQueue(ctx);
String url = "https://maps.googleapis.com/maps/api/distancematrix/json?units=metric&origins=22.2913,113.947&destinations=WanChai&mode=driving&key=";
JsonObjectRequest jsonObjReq = new JsonObjectRequest(Request.Method.POST,
url, null, new Response.Listener<JSONObject>()
{
#Override
public void onResponse(JSONObject response) {
// callback.onSuccess(response); // call call back function here
System.out.println("success");
}
}, new Response.ErrorListener() {
#Override
public void onErrorResponse(VolleyError error) {
//VolleyLog.d("Volley error json object ", "Error: " + error.getMessage());
System.out.println("failed");
}
})
{
#Override
public String getBodyContentType ()
{
return "application/json";
}
};
// Adding request to request queue
queue.add(jsonObjReq);
}
}
}
If your code in Activity.class:
RequestQueue queue = Volley.newRequestQueue(this);//or
RequestQueue queue = Volley.newRequestQueue(Activity.this);//or
RequestQueue queue = Volley.newRequestQueue(getApplicationContext());
If your code in Fragment.class:
RequestQueue queue = Volley.newRequestQueue(getContext());//or
RequestQueue queue = Volley.newRequestQueue(getApplicationContext());//or
RequestQueue queue = Volley.newRequestQueue(Fragment.this.getContext());//or
RequestQueue queue = Volley.newRequestQueue(Fragment.this.getApplicationContext());
make global variable in class VolleyRequests
Context context;
and initialize it on constructor
public VolleyRequests(Context mcontext) { this.context= mcontext; }
then use this
RequestQueue queue = Volley.newRequestQueue(context);
when you call it in MainActivity use :
VolleyRequests volleyrequests = new VolleyRequests (this);
Inside that new class constructor, pass the context so that you use it with volley.
public class ClassWithVolley{
private Context context;
public ClassWithVolley(Context context){
this.context = context;
}
// continue

Unable to get a response from the backend as to my query. How can I fix this issue?

I am trying to create a register activity which uses volley and PHP to connect to mySQL. I have attached some of the code. The code works perfectly fine till i try to get the response back from the Database. While using StringRequest, the control is not entering this section of the code. How can i fix this problem? Please Help.
public class RegisterActivity extends AppCompatActivity {
String rurl = "http://102.160.2.104/register.php";
String message;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_register);
final EditText etName = (EditText) findViewById(R.id.etName);
....
final EditText weig = (EditText) findViewById(R.id.weight);
final Button bRegister = (Button) findViewById(R.id.bRegister);
bRegister.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
final String name = etName.getText().toString();
final String username = etUsername.getText().toString();
...
if(!(conpassword.equals(password))){
etPassword.setText("");
etconpas.setText("");
Toast.makeText(getApplicationContext(),"Passwords don't match",Toast.LENGTH_LONG).show();
}
//The problem arises over here as it does not enter the onResponse() method.
StringRequest stringRequest = new StringRequest(Request.Method.POST, rurl, new Response.Listener<String>() {
#Override
public void onResponse(String response) {
try {
JSONArray jsonArray = new JSONArray(response);
JSONObject jsonObject = jsonArray.getJSONObject(0);
message = jsonObject.getString("message");
fin();
} catch (JSONException e) {
System.out.println("hhellooo");
e.printStackTrace();
}
}
private void fin() {
System.out.println(message);
if(message.equals("User already exists")){
etName.setText("");
etPassword.setText("");
contact.setText("");
etUsername.setText("");
age.setText("");
heig.setText("");
weig.setText("");
Toast.makeText(getApplicationContext(),"User already Exists",Toast.LENGTH_LONG).show();
}
else
{
Intent intent = new Intent(RegisterActivity.this,MainActivity.class);
startActivity(intent);
finish();
}
}
}, new Response.ErrorListener() {
#Override
public void onErrorResponse(VolleyError error) {
}
}){
#Override
protected Map<String, String> getParams() throws AuthFailureError {
Map<String,String> params = new HashMap<>();
params.put("name",name);
params.put("username",username);
params.put("password",password);
params.put("value", finalValue);
params.put("phone", String.valueOf(phone));
params.put("years", String.valueOf(years));
params.put("height", String.valueOf(height));
params.put("weight", String.valueOf(weight));
return params;
}
};
MySingleton.getInstance(RegisterActivity.this).addtoRQ(stringRequest);
}
});
}
The MySingleton class file to add the request into the queue.
class MySingleton {
private static MySingleton mInstance;
private static RequestQueue requestQueue;
private Context context;
private MySingleton(Context ctx) {
context = ctx;
requestQueue = getRequestQueue();
}
private RequestQueue getRequestQueue() {
if(requestQueue==null)
{
requestQueue = Volley.newRequestQueue(context.getApplicationContext());
}
return requestQueue;
}
static synchronized MySingleton getInstance(Context con){
if(mInstance==null)
{
mInstance = new MySingleton(con);
}
return mInstance;
}
<T>void addtoRQ(Request<T> request) {
requestQueue.add(request);
}
I think your request is not being sent because you haven't added it to a request queue.
RequestQueue mRequestQueue;
// Instantiate the cache
Cache cache = new DiskBasedCache(getCacheDir(), 1024 * 1024); // 1MB cap
// Set up the network to use HttpURLConnection as the HTTP client.
Network network = new BasicNetwork(new HurlStack());
// Instantiate the RequestQueue with the cache and network.
mRequestQueue = new RequestQueue(cache, network);
// Start the queue
mRequestQueue.start();
<Your request setup>
// Add the request to the RequestQueue.
mRequestQueue.add(stringRequest);
From: Android Developer

Context Service race condition

My application seems to be experiencing a race condition and I am unsure why. It only happens when I first open the application. According to the error the static variable instance in MainActivity is null but I set the variable before I start the service. It almost seems that the service starts running before the onCreate finishes within the activity but I don't believe that is possible. Any ideas what is happening?
Error message
E/AndroidRuntime: FATAL EXCEPTION: Timer-
java.lang.NullPointerException
at NetworkCalls.getRequestQueue(NetworkCalls.java:42)
at NetworkCalls.addToRequestQueue(NetworkCalls.java:48)
at NetworkCalls.createLocationPost(NetworkCalls.java:72)
at StaticMethods.handleWarnings(StaticMethods.java:84)
at LocationService.checkInPost(LocationService.java:73)
at LocationService$1.run(LocationService.java:66)
at java.util.Timer$TimerImpl.run(Timer.java:284)
Networks Class
public class NetworkCalls {
private static NetworkCalls singleton;
private RequestQueue mRequestQueue;
private static Context warningCtx = WarningActivity.instance;
private static Context mCtx = MainActivity.instance;
private NetworkCalls() {
}
public static synchronized NetworkCalls getInstance() {
if (singleton == null) {
singleton = new NetworkCalls();
}
return singleton;
}
private RequestQueue getRequestQueue() {
if (mRequestQueue == null) {
//Problem here is that mCtx is null
if(mCtx == null){
Log.e("Error", "It's FUBAR");
}else {
Log.e("Error", "It's Okay");
}
mRequestQueue = Volley.newRequestQueue(mCtx.getApplicationContext());
}
return mRequestQueue;
}
private <T> void addToRequestQueue(Request<T> req) {
getRequestQueue().add(req);
}
public void createLocationPost(LocationData locationData) {
String url = "http://httpbin.org/post";
HashMap<String, String> params = new HashMap<>();
params.put("Token", "key");
JsonObjectRequest jsObj = new JsonObjectRequest(url, new JSONObject(params), new Response.Listener<JSONObject>() {
#Override
public void onResponse(JSONObject response) {
try {
Log.i("NetworkCalls Successful", response.getJSONObject("json").toString());
} catch (JSONException ex) {
Log.i("Parsing response", "Unable to get json string");
}
// On Response recieved
}
}, new Response.ErrorListener() {
#Override
public void onErrorResponse(VolleyError error) {
Log.i("NetworkCalls Error", error.toString());
}
});
addToRequestQueue(jsObj);
}
Main acivity
public class MainActivity extends AppCompatActivity {
public static MainActivity instance = null;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
ColorDrawable colorDrawable = new ColorDrawable(Color.parseColor("#000000"));
getSupportActionBar().setBackgroundDrawable(colorDrawable);
this.setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LOCKED);
instance = MainActivity.this;
startService(new Intent(getBaseContext(), QueuePostService.class));
}
}
}
private static Context mCtx = MainActivity.instance;
This is initialized when the class is loaded. It takes the value of the field at that time, not when you subsequently use it.
That means that if it is null when the classloader loads NetworkCalls, it remains null until it is reassigned.
You would need to use MainActivity.instance instead of mCtx to get the field's current value.

Categories

Resources