Android Volley Error - java

I get Android volley error suddenly when i run my program.here i paste my AppController class for handling the volley objects.
AppController.java
public class AppController extends Application {
public static final String TAG = AppController.class.getSimpleName();
private RequestQueue mRequestQueue;
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 <T> void addToRequestQueue(Request<T> req, String tag) {
req.setTag(TextUtils.isEmpty(tag) ? TAG : tag);
getRequestQueue().add(req);
}
public <T> void addToRequestQueue(Request<T> req) {
req.setTag(TAG);
getRequestQueue().add(req);
}
public void cancelPendingRequests(Object tag) {
if (mRequestQueue != null) {
mRequestQueue.cancelAll(tag);
}
}
}
and i call this class in some another class of my program like
AppController.getInstance().addToRequestQueue(strReq, tag_string_req);
it will executed without any errors in so many days but now it shows error
like
Error:
java.lang.NoSuchMethodError: No virtual method setTag(Ljava/lang/Object;)Lcom/android/volley/Request; in class Lcom/android/volley/Request or its super classes (declaration of 'com.android.volley.Request'; appears in /data/app/com.example.rninja4.rookie-1/split_lib_dependencies_apk.apk:classes6.dex)
at com.example.packagename.App.AppController.addToRequestQueue(AppController.java:39)

You have not declared application class in manifest like below.
<application
android:name="AppController"
android:icon="#drawable/ic_launcher"
android:label="#string/app_name" >

Related

How memory of an instance variable is shared between processes within an application in Android?

I've a singleton class which looks something like this,
public class MyHomeFactory {
public static final String TAG = "sddsd";
private static MyHomeFactory myHomeFactory = null;
private MyHomeFactory() {
Log.i(TAG, "Inside my home factory");
}
public static MyHomeFactory getInstance() {
if(myHomeFactory == null) {
myHomeFactory = new MyHomeFactory();
}
return myHomeFactory;
}
}
I'm invoking MyHomeFactory.getInstance() in my application class and in my service class (which runs under different process) something like this,
public class CornetApplication extends Application {
#Override
public void onCreate() {
super.onCreate();
Log.i(TAG, "The value of instance is : " + MyHomeFactory.getInstance());
}
}
and from service inside it's onBind like,
#Override
public IBinder onBind(Intent intent) {
return new IMyAidlInterface.Stub() {
#Override
public void printTime(long time) throws RemoteException {
Log.i(TAG, "Instance value is : " + MyHomeFactory.getInstance());
}
};
}
Service declaration in AndroidManifest looks something like this,
<service
android:name=".OnDisConnectedService"
android:enabled="true"
android:exported="true"
android:process=":separate_process"/>
To my surprise both the instance value is printed something like this,
com.example.circa.MyHomeFactory#63b959e
in place of getInstance(). How this instance is shared between process? I'm getting confused here.

Getting raw resource (sound) in non-activity class

I'm trying to create a singleton class that will be responsible for playing game sounds. I created a singleton class GameSounds with a method playSound(). In the res folder I have a a subfolder 'raw' with a file letter_found.mp3.
This is the source code of the GameSounds class I wrote:
import android.app.Application;
import android.content.Context;
import android.media.MediaPlayer;
public class GameSounds extends Application {
private static GameSounds gameSounds = new GameSounds();
private static MediaPlayer soundPlayer;
private static Context mContext;
private static int mySoundId = R.raw.letter_found;
private GameSounds() {
mContext = this;
}
public static GameSounds getInstance() {
return gameSounds;
}
public static void playSound() {
soundPlayer = MediaPlayer.create(mContext, mySoundId);
soundPlayer.start();
}
}
This doesn't seem to work as I'm getting the following error message:
"java.lang.NullPointerException: Attempt to invoke virtual method 'android.content.res.Resources android.content.Context.getResources()' on a null object reference"
I don't understand why this is happening. I tried to search Stackoverflow but couldn't find a solution.
Any help/explanation is greatly appreciated.
You can have a Singleton holding an Application Context (NOT Activity context) but practically you have to set this context before you use your singleton which can be enforced by throwing exceptions. See below example code.
public class GameSounds {
private static Context sContext;
public static void setContext(Context context) {
if (context == null) {
throw new IllegalArgumentException("context cannot be null!");
}
// In order to avoid memory leak, you should use application context rather than the `activiy`
context = context.getApplicationContext();
if (context == null) {
throw new IllegalArgumentException("context cannot be null!");
}
sContext = context;
}
private static Context getContext() {
if (sContext != null) {
return (Context)sContext;
}
throw new IllegalStateException("sContext was not set yet! Please call method setContext(Context context) first.");
}
// the rest of other methods. e.g. playSounds()
private static GameSounds gameSounds = new GameSounds();
private GameSounds() {
}
public static GameSounds getInstance() {
return gameSounds;
}
public void playSound() {
Context context = getContext();
soundPlayer = MediaPlayer.create(context, mySoundId);
soundPlayer.start();
}
}
You shouldn't inherit Application class unless you try to use Singleton pattern. Because Application is base class which contains all other components such as activities and services.
Instead, GameSound class should contain Context object and proper constructor.
Example)
public class GameSounds {
private GameSounds gameSounds;
private MediaPlayer soundPlayer;
private WeakReference<Context> mContext;
private int mySoundId = R.raw.letter_found;
private GameSounds(Context context) {
mContext = new WeakReference<>(context);
}
public GameSounds getInstance(Context context) {
if (gameSounds == null) {
gameSounds = new GameSounds(context);
}
return gameSounds;
}
public void playSound() {
soundPlayer = MediaPlayer.create(mContext.get(), mySoundId);
soundPlayer.start();
}
}
In this code, there is WeakReference<Context> instead of Context. WeakReference is used to prevent memory leaks because memory leaks can occur if you have an instance outside the activity.
To play sound, execute GameSounds.getInstance(this).playSound(); is fine.
If Context can't provide when try to play sound, implement initialize methods and called in Application class can be ok.
public class GameSounds {
private static GameSounds gameSounds;
private MediaPlayer soundPlayer;
private WeakReference<Context> mContext;
private int mySoundId = R.raw.letter_found;
private GameSounds(Application context) {
mContext = new WeakReference<>(context);
}
public static void initialize(Application context) {
if (gameSounds == null) {
gameSounds = new GameSounds(context);
}
}
public static GameSounds getInstance() {
if (gameSounds == null) {
throw new NullPointerException("You need to initialize this code by GameSound.initialize(this) in application class");
}
return gameSounds;
}
public void playSound() {
soundPlayer = MediaPlayer.create(mContext.get(), mySoundId);
soundPlayer.start();
}
}
In this case, you should make Application class and initialize GameSound class by GameSound.initialize(this) in Application class.
To play sound, GameSound.getInstance().playSound() is fine.

Volley attach access token to evey request using singleton

I am doing the following which perfectly works
//else proceed with the checks
JsonObjectRequest jsonObjectRequest = new JsonObjectRequest(
Request.Method.GET,
checkauthurl,
null,
new Response.Listener<JSONObject>() {
#Override
public void onResponse(String response) {
//do stuff here
}
},
new Response.ErrorListener() {
#Override
public void onErrorResponse(VolleyError error) {
// do stuff here
}
}) {
#Override
public Map<String, String> getHeaders() throws AuthFailureError {
HashMap<String, String> headers = new HashMap<String, String> ();
TokenService tokenservice = new TokenService(ctx);
String accesstoken = tokenservice.getToken(ApiHelper.ACCESS_TOKEN_SHARED_PREF);
headers.put("Authorization", "Bearer " + accesstoken);
return headers;
}
};
// Access the RequestQueue through your singleton class.
ApiSingleton strngle = new ApiSingleton(ctx);
strngle.addToRequestQueue(jsonObjectRequest);
For every request, I have to add the request header. How can I set request headers directly in the singleton.
This is my singleton
private static ApiSingleton mInstance;
private RequestQueue mRequestQueue;
public static Context mCtx;
private ImageLoader mImageLoader;
public ApiSingleton(Context context) {
mCtx = context;
mRequestQueue = getRequestQueue();
//do stuff
}
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;
}
How do I avoid the above code duplication when attaching the bearer token in every request?
public class CustomJsonRequest extends JsonRequest<Object>{
public CustomJsonRequest(String url, String requestBody, Response.Listener<Object> listener,
Response.ErrorListener errorListener) {
super(url, requestBody, listener, errorListener);
}
public CustomJsonRequest(int method, String url, String requestBody, Response.Listener<Object> listener,
Response.ErrorListener errorListener) {
super(method, url, errorListener);
}
#Override
protected Response<Object> parseNetworkResponse(NetworkResponse response) {
return Response.success(Object, HttpHeaderParser.parseCacheHeaders(response));
}
#Override
public Map<String, String> getHeaders() throws AuthFailureError {
Map<String, String> headers = new HashMap<String, String> ();
TokenService tokenservice = new TokenService(ctx);
String accesstoken = tokenservice.getToken(ApiHelper.ACCESS_TOKEN_SHARED_PREF);
headers.put("Authorization", "Bearer " + accesstoken);
return headers;
}
}
You can extend JsonRequest class and override getHeaders() method.
Pass instance of CustomJsonRequest object when you are adding volley requests in queue.
VolleyUtils.getInstance().addToRequestQueue(customJsonRequest);
You can write a "Factory" with a method that takes your checkauthurl and ctx and returns you an instance of the JsonObjectRequest. Your factory could implement some logic for re-use of objects that have the same auth Url if that makes sense in your case.
You can sub-class JsonObjectRequest and provide your checkauthurl and ctx as a parameter to the constructor. Similarly, you can implement a scheme to re-use the objects
The factory would be the suggested approach if you want Dependency Injection.
I would recommend against pre-allocating the Token and using it in multiple requests. Tokens expire. If the TokenService is written well, it should know when tokens will expire and refresh as needed (if possible).
Make an AppController.java file and mention this file name as android:app in manifest tag.
public class AppController extends Application {
public static final String TAG = AppController.class.getSimpleName();
private RequestQueue mRequestQueue;
private static AppController mInstance;
private ImageLoader mImageLoader;
#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 LruBitmapCache());
}
return this.mImageLoader;
}
public <T> void addToRequestQueue(Request<T> req, String tag) {
req.setTag(TextUtils.isEmpty(tag) ? TAG : tag);
getRequestQueue().add(req);
}
public <T> void addToRequestQueue(Request<T> req) {
req.setTag(TAG);
getRequestQueue().add(req);
}
public void cancelPendingRequests(Object tag) {
if (mRequestQueue != null) {
mRequestQueue.cancelAll(tag);
}
}
}
Do the networking code
StringRequest strReq = new StringRequest(Request.Method.POST, AppConfig.URL_BUYER_LOGIN,
new Response.Listener<String>() {
#Override
public void onResponse(String response) {
}
}, new Response.ErrorListener() {
#Override
public void onErrorResponse(VolleyError error) {
}
}) {
#Override
protected Map<String, String> getParams() {
}
};
// Adding request to request queue
AppController.getInstance().addToRequestQueue(strReq, tag_string_req);
}

why the volley class uses singleton pattern design?

to use the volley library i found the following code:
public class AppController extends Application {
public static final String TAG = AppController.class
.getSimpleName();
private RequestQueue mRequestQueue;
private static AppController mInstance;
#Override
public void onCreate() {
super.onCreate();
mInstance = this;
}
public static synchronized AppController getInstance() {
return mInstance;
}
public RequestQueue getRequestQueue() {
//baraye avalin bar ejra mishe
if (mRequestQueue == null) {
mRequestQueue = Volley.newRequestQueue(getApplicationContext());
}
return mRequestQueue;
}
public <T> void addToRequestQueue(Request<T> req, String tag) {
// set the default tag if tag is empty
req.setTag(TextUtils.isEmpty(tag) ? TAG : tag);
getRequestQueue().add(req);
}
public void cancelPendingRequests(Object tag) {
if (mRequestQueue != null) {
mRequestQueue.cancelAll(tag);
}
}
}
i want to understand why this class uses Singleton pattern design?if we create two objects of the class what problems occur?
This is not the singleton pattern. The singleton pattern enforces that there can only ever be (at most) a single instance of a particular class. That's not true here. You could have many RequestQueues across many AppControllers.
What this is, in fact, is lazy initialisation. It is probably employed because instantiating a RequestQueue is somewhat of a large operation, and you don't want to instantiate it unnecessarily if you don't have to.

Android Volley error using Singleton pattern

I am trying to follow this guide on how to work with Volley using a Singleton. The goal is to use this Singleton to have my RequestQueue in an Application context so it won't be affected by shifting from landscape to portrait and such.
But I get the following error:
java.lang.NullPointerException: Attempt to invoke virtual method 'java.io.File android.content.Context.getCacheDir()' on a null object reference
at com.android.volley.toolbox.Volley.newRequestQueue(Volley.java:45)
at com.android.volley.toolbox.Volley.newRequestQueue(Volley.java:105)
at com.android.volley.toolbox.Volley.newRequestQueue(Volley.java:115)
at se.ccconsulting.arenaui3.VolleySingleton.(VolleySingleton.java:20)
at se.ccconsulting.arenaui3.VolleySingleton.getInstance(VolleySingleton.java:34)
at se.ccconsulting.arenaui3.AdventureFragment.onCreateView(AdventureFragment.java:62)
...
And it points towards this line:
mRequestQueue = Volley.newRequestQueue(HelperApplication.getAppContext());
I am not sure what is wrong here as from what I can see in the code the getInstance() method in VolleySingleton.java is not supposed to
VolleySingleton.java
public class VolleySingleton {
private static VolleySingleton mInstance = null;
private RequestQueue mRequestQueue;
private ImageLoader mImageLoader;
private VolleySingleton(){
mRequestQueue = Volley.newRequestQueue(HelperApplication.getAppContext());
mImageLoader = new ImageLoader(this.mRequestQueue, new ImageLoader.ImageCache() {
private final LruCache<String, Bitmap> mCache = new LruCache<String, Bitmap>(10);
public void putBitmap(String url, Bitmap bitmap) {
mCache.put(url, bitmap);
}
public Bitmap getBitmap(String url) {
return mCache.get(url);
}
});
}
public static VolleySingleton getInstance(){
if(mInstance == null){
mInstance = new VolleySingleton();
}
return mInstance;
}
public RequestQueue getRequestQueue(){
return this.mRequestQueue;
}
public ImageLoader getImageLoader(){
return this.mImageLoader;
}
}
HelperApplication.java
public class HelperApplication extends Application{
private static HelperApplication mInstance;
private static Context mAppContext;
#Override
public void onCreate() {
super.onCreate();
mInstance = this;
this.setAppContext(getApplicationContext());
}
public static HelperApplication getInstance(){
return mInstance;
}
public static Context getAppContext() {
return mAppContext;
}
public void setAppContext(Context mAppContext) {
this.mAppContext = mAppContext;
}
}
This is the line of code I used from Volley before implementing the Singlton which worked perfectly but do not meet my needs:
RequestQueue queue = Volley.newRequestQueue(getActivity());
I am debugging on Genymotion.
Fruthermore, row of code from Volley.java mentioned in the exception:
File cacheDir = new File(context.getCacheDir(), DEFAULT_CACHE_DIR);
I need help getting passed this error.
If you read the README of the Github repo that code links to, it specifically mentions, you need to add this to your manifest XML.
<application android:name="com.company.MyApplication">
</application>
In your case, change com.company.MyApplication to xxx.yyy.HelperApplication, though.

Categories

Resources