Android Service Creating new Instance of Singleton Class
android, android-service, java, singleton
Solution
You are running your `Service` in a different process which is not the same as your `Application` context, that's why the Queue turns out to by null in the new process.
Remove the following from your `Service` in manifest and you are good to go:
android:process=":main"
Moreover, I would suggest you to make use of `HandlerThread` in your service to offload some heavy operations.
Problem
I am using A Singleton Class for holding some data through out of application Which is some Queue. I am creating Singleton Class Instance `onCreate` method of my `Application` Class. ``` @Override public void onCreate() { super.onCreate(); mInstance = this; mContext = getApplicationContext(); Queue.getInstance(); // this is my singleton class instance } ``` After this I am adding data inside of this singleton class in my activities ``` Queue.getInstance().addItem(qItem); Log.d(Constants.TAG, "Added Item Queue Size: "+Queue.getInstance().getQueueList().size()); ``` Until this Everything working fine. I can access data in my `Activities` and `ListView Adapter` however When I Start Service and try to access data `onCreate` of service ``` Log.d(Constants.TAG, "Playing Item Queue Size: "+Queue.getInstance().getQueueList().size()+" Current Item No. "+Queue.getInstance().getCurrentPlayingItem()); String url = Queue.getInstance().getQueueItem(Queue.getInstance().getCurrentPlayingItem()).getLinkUrl(); ``` My Singleton Instance become null and my singleton creates new instance. Which cause my data loss inside of Service. Following is flow of my error. - On Start of Application Create Instance - Working - Add data from Activities and Adapters - Working - Start Service and Access Data - Not Working because Singleton Instance become null inside service Following is the code of my Singleton Class ``` import java.util.ArrayList; import com.taazi.utils.Constants; import android.util.Log; public class Queue { private ArrayList<QueueItem> mQueueList; static Queue mInstance; private int currentPlayingItem=0; private Queue(){ mQueueList = new ArrayList<QueueItem>(); } public static Queue getInstance(){ if(mInstance == null){ mInstance = new Queue(); Log.d(Constants.TAG, "New Instance"); } return mInstance; } public void addItem(QueueItem item){ mQueueList.add(item); } public void removeItem(int position){ mQueueList.remove(position); } public ArrayList<QueueItem> getQueueList(){ return mQueueList; } public QueueItem getQueueItem(int position){ return mQueueList.get(position); } public int getCurrentPlayingItem() { return currentPlayingItem; } public void setCurrentPlayingItem(int currentPlayingItem) { this.currentPlayingItem = currentPlayingItem; } } ``` AudioPlayBackService.Java ``` package com.taazi.services; import android.app.Service; import android.content.Intent; import android.media.MediaPlayer; import android.net.Uri; import android.os.IBinder; import android.util.Log; import com.taazi.helper.NotificationHelperNew; import com.taazi.models.Queue; import com.taazi.models.QueueItem; import com.taazi.utils.Constants; public class AudioPlayBackService extends Service { /** * Called to go toggle between pausing and playing the music */ public static final String TOGGLEPAUSE_ACTION = "com.taazi.services.togglepause"; /** * Called to go to pause the playback */ public static final String PAUSE_ACTION = "com.taazi.services.pause"; /** * Called to go to stop the playback */ public static final String STOP_ACTION = "com.taazi.services.stop"; /** * Called to go to the previous track */ public static final String PREVIOUS_ACTION = "com.taazi.services.previous"; /** * Called to go to the next track */ public static final String NEXT_ACTION = "com.taazi.services.next"; /** * Used to build the notification */ private NotificationHelperNew mNotificationHelper; @Override public IBinder onBind(Intent intent) { return null; } MediaPlayer player; @Override public void onCreate() { super.onCreate(); // Initialize the notification helper mNotificationHelper = new NotificationHelperNew(this); Log.d(Constants.TAG, "Playing Item Queue Size: "+Queue.getInstance().getQueueList().size()+" Current Item No. "+Queue.getInstance().getCurrentPlayingItem()); String url = Queue.getInstance().getQueueItem(Queue.getInstance().getCurrentPlayingItem()).getLinkUrl(); player = MediaPlayer.create(this, Uri.parse(url)); player.setLooping(false); // Set looping updateNotification(); } public int onStartCommand(Intent intent, int flags, int startId) { player.start(); return 1; } public void onStart(Intent intent, int startId) { // TO DO } public IBinder onUnBind(Intent arg0) { // TO DO Auto-generated method return null; } public void onStop() { } public void onPause() { } @Override public void onDestroy() { mNotificationHelper.killNotification(); player.stop(); player.release(); } @Override public void onLowMemory() { } /** * Updates the notification, considering the current play and activity state */ private void updateNotification() { QueueItem item = Queue.getInstance().getQueueItem(Queue.getInstance().getCurrentPlayingItem()); mNotificationHelper.buildNotification("", item.getArtist(), item.getTitle(), (long)50, null, true); } } ``` AndroidManifest.xml ``` <?xml version="1.0" encoding="utf-8"?> <manifest xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" package="com.taazi.android" android:versionCode="1" android:versionName="1.0" > <uses-sdk android:minSdkVersion="10" android:targetSdkVersion="20" /> <uses-permission android:name="android.permission.INTERNET" /> <uses-permission android:name="android.permission.ACCESS_WIFI_STATE" /> <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" /> <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" /> <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/> <uses-permission android:name="android.permission.READ_PHONE_STATE" /> <uses-permission android:name="android.permission.WRITE_SETTINGS" /> <uses-permission android:name="android.permission.GET_TASKS" /> <action android:name="android.net.conn.CONNECTIVITY_CHANGE" /> <uses-permission android:name="android.permission.WAKE_LOCK" /> <application android:name="com.taazi.app.AppController" android:allowBackup="true" android:hardwareAccelerated="true" android:icon="@drawable/ic_launcher" android:label="@string/app_name" android:theme="@style/Theme.Apptheme" > <activity android:name="com.taazi.activities.MainActivity" android:label="@string/app_name" android:screenOrientation="portrait" > <intent-filter> <action android:name="android.intent.action.MAIN" /> <category android:name="android.intent.category.LAUNCHER" /> </intent-filter> </activity> <!-- Music service --> <service android:name="com.taazi.services.AudioPlayBackService" android:label="@string/app_name" android:process=":main" /> </application> </manifest> ```