Data communication between service and activity - android

I am trying to provide communication between activity and service but I have a problem. Inspite of initializing id on onStartCommand method, I am getting this error
java.lang.RuntimeException: Unable to create service com.a.b.c.Services.LocationService:
java.lang.NullPointerException: println needs a message
public class LocationService extends Service {
Context context;
Timer timer;
Double latitude, longitude;
private String id;
public LocationService() {
}
#Override
public void onCreate() {
super.onCreate();
context = getApplicationContext();
Log.i("servis", "Service working...");
Log.i("id", id);
timer = new Timer();
timer.schedule(new TimerTask() {
#Override
public void run() {
int isHere = isHere();
updateUserStatus(isHere);
}
}, 0, 200000);
}
#Override
public IBinder onBind(Intent intent) {
// TODO: Return the communication channel to the service.
throw new UnsupportedOperationException("Not yet implemented");
}
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
id = intent.getStringExtra("id");
return START_STICKY;
}
private int isHere() {
GPSTracker gps = new GPSTracker(this);
if (!gps.canGetLocation()) {
gps.showSettingsAlert();
} else {
latitude = gps.getLatitude();
longitude = gps.getLongitude();
if(Math.abs(xxx - latitude) <= 0.001 || Math.abs(yyy - longitude) <= 0.001)
return 1;
else
return 0;
}
return 0;
}
private void updateUserStatus(int isHere){
Call<Kisi> x = ManagerAll.getInstance().updateLocation(id, isHere);
x.enqueue(new Callback<Kisi>() {
#Override
public void onResponse(Call<Kisi> call, Response<Kisi> response) {
if(response.isSuccessful())
Log.i("status", "succesful");
}
#Override
public void onFailure(Call<Kisi> call, Throwable t) {
}
});
}
}

In your onCreate() method you try to log the variable id, but it is not initialized before the onStartCommand method is run, which happens after `onCreate():
Service lifecycle
Move your logging till after id is initialized and it should work fine.

Related

Application will be slow when service runs in the background

I am using a service in my application in order to get data from the server and save received data in my local database.
But when I am using the application and my service will run in the background the application works too slow.
This is my service class that I used:
public class InternetService extends Service implements Loader.OnLoadCompleteListener<Cursor> {
public static final int notify = 5 * 60 * 60 * 1000; //interval between two services(Here Service run every 1 Minute)
private Handler mHandler = new Handler(); //run on another Thread to avoid crash
private Timer mTimer = null; //timer handling
private ArrayList<FileModel> failedIDDownloads = new ArrayList<>();
private static final String TAG = "BroadcastService";
public static final String BROADCAST_ACTION = "my_package";
Intent intent;
int counter = 0;
private CursorLoader cursorLoader;
private EncycDatabase encycDB;
#Override
public IBinder onBind(Intent intent) {
throw new UnsupportedOperationException("Not yet implemented");
}
#Override
public void onCreate() {
intent = new Intent(BROADCAST_ACTION);
}
#Override
public void onStart(Intent intent, int startId) {
cursorLoader = new CursorLoader(this, Uri.parse(EncycDatabase.CONTENT_PROVIDER_URL),
null, null, null, null);
cursorLoader.registerListener(1, this);
cursorLoader.startLoading();
mHandler.removeCallbacks(sendUpdatesToUI);
mHandler.postDelayed(sendUpdatesToUI, 1000); // 1 second
}
#Override
public void onDestroy() {
super.onDestroy();
// Stop the cursor loader
if (cursorLoader != null) {
cursorLoader.unregisterListener(this);
cursorLoader.cancelLoad();
cursorLoader.stopLoading();
}
}
#Override
public void onLoadComplete(Loader<Cursor> loader, Cursor cursor) {
encycDB = new EncycDatabase();
try {
while (cursor.moveToNext()) {
G.TOKEN = (cursor.getString(cursor.getColumnIndex("user_session_token")));
}
populateEncyclopediaData();
Thread searchTagThread = new Thread(new Runnable() {
#Override
public void run() {
populateSearchTagsEncyc();
populateSearchTags();
}
});
G.handler.postDelayed(new Runnable() {
#Override
public void run() {
checkForDownloadFiles();
}
},10 *60* 1000);
searchTagThread.start();
} catch (Exception e) { //When happened an error in getting Token!
e.printStackTrace();
}
}
private void populateEncyclopediaData() {
final APIService service = ServiceGenerator.createService(APIService.class,
new PreferenceManager(G.context).getLastUpdateForEncyclopediaData(), G.TOKEN);
service.getLastChanges()
.subscribeOn(Schedulers.newThread())
.observeOn(Schedulers.io())
.subscribe(new Observer<Response<ArrayList<ServerLastChangesModel>>>() {
#Override
public void onSubscribe(Disposable d) {
}
#Override
public void onNext(Response<ArrayList<ServerLastChangesModel>> response) {
Log.i("LOGO_Encycloedia", "Request code: " + response.code());
if (response.code() == 200) {
G.encyclopediaArray.clear();
for (int i = 0; i < response.body().size(); i++) {
EncyclopediaModel lcModel = new EncyclopediaModel();
lcModel.setEncyclopedia_id(response.body().get(i).getEncyclopediaId());
lcModel.setEncyclopedia_title(response.body().get(i).getEncyclopediaTitle());
lcModel.setEncyclopedia_modified_date(response.body().get(i).getEncyclopediaModifiedDate());
lcModel.setEncyclopedia_deleted(response.body().get(i).getEncyclopediaDeleted());
lcModel.setEncyclopedia_content_id(response.body().get(i).getEncyclopediaContentId());
lcModel.setEncyclopedia_out_desc_text_id(response.body().get(i).getEncyclopediaOutDescTextId());
lcModel.setEncyclopedia_in_desc_text_id(response.body().get(i).getEncyclopediaInDescTextId());
lcModel.setEncyclopedia_order_in_parent(response.body().get(i).getEncyclopediaOrderInParent());
lcModel.setEncyclopedia_parent_id(response.body().get(i).getEncyclopediaParentId());
lcModel.setEncyclopedia_is_inline_parent(response.body().get(i).getEncyclopediaIsInlineParent());
lcModel.setEncyclopedia_style_sheet(response.body().get(i).getEncyclopediaStyleSheet());
G.encyclopediaArray.add(lcModel);
}
}
}
#Override
public void onError(Throwable e) {
}
#Override
public void onComplete() {
try {
encycDB.insertIntoEncyclopediaDB(G.encyclopediaArray);
new PreferenceManager(G.context).writeLastUpdateForEncyclopediaData();
} catch (Exception e) {
e.printStackTrace();
}
populateContentData(encycDB.getContentIdsFromEncyclopedia());
}
});
}
As you can see, I used threads, but it doesn't help!
I can't find out where is the problem.
The Service runs in background but it runs on the Main Thread of the application. And IntentService runs on separate worker thread.
Move your code to IntentService.

why restart the service

i have a problem in my service, the service is runnig from MainActivity (i am doing test) and extends of service.
i want to use the service from foreground and background (when the app is closed) and i already have my first problem:
my service(have a counter that is displayed by LOG) is restarting when i close the app.
also i want to be able to use the service with the open app and close app, in other words to use both the Service Started and Link Service
public class MyService extends Service {
private Thread backgroundThread;
private boolean isRunning;
public MyService() {
Log.e("MyService","constructor");
}
#Override
public void onCreate() {
super.onCreate();
isRunning = false;
}
#Override
public IBinder onBind(Intent intent) {
// TODO: Return the communication channel to the service.
throw new UnsupportedOperationException("Not yet implemented");
}
#Override
public int onStartCommand(final Intent intent, int flags, int startId) {
Log.e("onStartCommand","Servicio Llamado");
if (!this.isRunning) {
Log.e("onStartCommand","hilo iniciandose");
this.backgroundThread = new Thread(myTask);
runTask();
}
return super.onStartCommand(intent, flags, startId);
}
#Override
public void onDestroy() {
super.onDestroy();
Log.e("onDestroy","servicio destuido");
}
private void runTask(){
this.isRunning = true;
this.backgroundThread.start();
}
private Runnable myTask = new Runnable() {
public void run() {
Log.e("myTask","hilo iniciado");
int i = 0;
do{
pauseService();
Log.e("myTask","hilo contador: "+i);
//Toast.makeText(getApplicationContext(),"CONTADOR = "+j, Toast.LENGTH_SHORT).show(); //no working :(
i++;
}while (i<10);
/*
//linea de detencion del servicio
//stopSelf();
isRunning=false;
backgroundThread.interrupt();
//backgroundThread = new Thread(myTask);
*/
Log.e("myTask","hilo cerrado");
}
};
private void pauseService(){
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
In main Activity
Intent intent = new Intent(MainActivity.this,MyService.class);
intent.putExtra("iteraciones",10);
startService(intent);
why because the service restarts when I close the application and how can I avoid it?

Save data to firebase Realtime database from Android service

I want to save user's location after every 30 seconds to firebase realtime database from android service,my service stops when i add firebase, there is no crash log, any suggestions? or best solution to achieve this? Thanks
public class LocationService extends Service {
double pLatitude, pLongitude;
private DatabaseReference mDatabase;
FirebaseUser user;
#Nullable
#Override
public IBinder onBind(Intent intent) {
return null;
}
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
Toast.makeText(getApplicationContext(),"Service Started", Toast.LENGTH_SHORT).show();
return START_STICKY;
}
#Override
public void onCreate() {
super.onCreate();
//service stops(crashes) on below two lines
mDatabase = FirebaseDatabase.getInstance().getReference();
user = FirebaseAuth.getInstance().getCurrentUser();
final Handler handler = new Handler();
Timer timer = new Timer();
TimerTask doAsynchronousTask = new TimerTask() {
#Override
public void run() {
handler.post(new Runnable() {
public void run() {
try {
Toast.makeText(getApplicationContext(), "Service Started", Toast.LENGTH_LONG).show();
pushtofirebase(getLocation());
} catch (Exception e) {
}
}
});
}
};
timer.schedule(doAsynchronousTask, 0, 30000);
}
private void pushtofirebase(GPSTracker gps) {
pLatitude = gps.getLatitude();
pLongitude = gps.getLongitude();
mDatabase.child("location").child(user.getUid()).push().setValue(String.valueOf(pLatitude));
mDatabase.child("location").child(user.getUid()).setValue(pLongitude);
}
#Override
public void onDestroy() {
super.onDestroy();
Toast.makeText(this, "Service Destroyed", Toast.LENGTH_LONG).show();
}
private GPSTracker getLocation() {
GPSTracker gps = new GPSTracker(getApplicationContext());
if (gps.canGetLocation()) {
Toast.makeText(getApplicationContext(), gps.getLongitude() + " " + gps.getLatitude(), Toast.LENGTH_SHORT).show();
} else {
gps.showSettingsAlert();
}
return gps;
}
}
it may be a native crash change the logcat crash level to verbose and application to no filter

Android: Trying to move a location finder and volley request into a service

I'm a bit new to Android and I'm trying to move some location finding and volley methods out of my fragment into a service, but now sure where to put what. It's basically a weather app that gets your current location and uses volley to pull forecast.io api data.
Here is my fragment now:
public class WeatherListFragment extends ListFragment implements LocationListener {
private final String initialURL = "https://api.forecast.io/forecast/8fc2b0556e166fa4670d4014d318152a/";
Weather[] myWeatherArray = {};
Weather myWeatherObject;
WeatherAdapter weatherAdapter;
LocationManager mLocationManager;
String currentLoc;
JSONArray data;
JSONObject day;
#Override
public void onLocationChanged(Location location) {
// Called when a new location is found by the network location provider.
makeUseOfNewLocation(location);
// Remove the listener you previously added
mLocationManager.removeUpdates(this);
}
#Override
public void onStatusChanged(String provider, int status, Bundle extras) {
}
#Override
public void onProviderEnabled(String provider) {
}
#Override
public void onProviderDisabled(String provider) {
}
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
mLocationManager = (LocationManager) getActivity().getSystemService(Context.LOCATION_SERVICE);
makeUseOfNewLocation(mLocationManager.getLastKnownLocation(LocationManager.GPS_PROVIDER));
mLocationManager.requestLocationUpdates(LocationManager.NETWORK_PROVIDER, 1, 1, this);
mLocationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER, 1, 1, this);
}
public void getData() {
String API_URL = setLatLong(initialURL, currentLoc);
RequestQueue requestQueue = Volley.newRequestQueue(getActivity());
JsonObjectRequest jsonObjectRequest = new JsonObjectRequest(Request.Method.GET, API_URL, null, new Response.Listener<JSONObject>() {
#Override
public void onResponse(JSONObject response) {
try {
JSONObject daily = response.getJSONObject("daily");
data = daily.getJSONArray("data");
myWeatherArray = new Weather[data.length()];
for (int i = 0; i < myWeatherArray.length; i++) {
day = data.getJSONObject(i);
myWeatherObject = new Weather();
myWeatherObject.setmDate(day.getInt("time"));
myWeatherObject.setmTempMin(day.getInt("temperatureMin"));
myWeatherObject.setmTempMax(day.getInt("temperatureMax"));
myWeatherObject.setIcon(day.getString("icon"));
myWeatherArray[i] = myWeatherObject;
}
} catch (JSONException e) {
e.printStackTrace();
}
if (weatherAdapter != null) {
weatherAdapter.setData(myWeatherArray);
}
}
}, new Response.ErrorListener() {
#Override
public void onErrorResponse(VolleyError error) {
Toast.makeText(getActivity(), "volley died", Toast.LENGTH_SHORT).show();
}
}
);
requestQueue.add(jsonObjectRequest);
}
public void makeUseOfNewLocation(Location location) {
if (location == null) {
return;
}
mLocationManager.removeUpdates(this);
double latDouble = location.getLatitude();
double longDouble = location.getLongitude();
String latString = String.valueOf(latDouble);
String longString = String.valueOf(longDouble);
String latLong = latString + "," + longString;
Log.e("gps", latLong);
currentLoc = latLong;
getData();
}
public String setLatLong(String roughURL, String loc) {
return roughURL + loc;
}
and here is the blank Service class using a Handler:
public class NotificationService extends Service {
private Looper mServiceLooper;
private ServiceHandler mServiceHandler;
// Handler that receives messages from the thread
private final class ServiceHandler extends Handler {
public ServiceHandler(Looper looper) {
super(looper);
}
#Override
public void handleMessage(Message msg) {
// Normally we would do some work here, like download a file.
// For our sample, we just sleep for 5 seconds.
long endTime = System.currentTimeMillis() + 5*1000;
while (System.currentTimeMillis() < endTime) {
synchronized (this) {
try {
wait(endTime - System.currentTimeMillis());
} catch (Exception e) {
}
}
}
Notification n = new Notification(getApplicationContext());
// Stop the service using the startId, so that we don't stop
// the service in the middle of handling another job
stopSelf(msg.arg1);
}
}
#Override
public void onCreate() {
// Start up the thread running the service. Note that we create a
// separate thread because the service normally runs in the process's
// main thread, which we don't want to block. We also make it
// background priority so CPU-intensive work will not disrupt our UI.
HandlerThread thread = new HandlerThread("ServiceStartArguments",
Thread.MIN_PRIORITY);
thread.start();
// Get the HandlerThread's Looper and use it for our Handler
mServiceLooper = thread.getLooper();
mServiceHandler = new ServiceHandler(mServiceLooper);
}
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
Toast.makeText(this, "service starting", Toast.LENGTH_SHORT).show();
// For each start request, send a message to start a job and deliver the
// start ID so we know which request we're stopping when we finish the job
Message msg = mServiceHandler.obtainMessage();
msg.arg1 = startId;
mServiceHandler.sendMessage(msg);
// If we get killed, after returning from here, restart
return START_STICKY;
}
#Override
public IBinder onBind(Intent intent) {
// We don't provide binding, so return null
return null;
}
#Override
public void onDestroy() {
Toast.makeText(this, "service done", Toast.LENGTH_SHORT).show();
}
}

Android remote service doesn't call service methods

I'm developing a GPS tracking software on android. I need IPC to control the service from different activities. So I decide to develop a remote service with AIDL. This wasn't a big problem but now it's always running into the methods of the interface and not into those of my service class. Maybe someone could help me?
Here my AIDL file:
package test.de.android.tracker
interface ITrackingServiceRemote {
void startTracking(in long trackId);
void stopTracking();
void pauseTracking();
void resumeTracking(in long trackId);
long trackingState();
}
And the here a short version of my service class:
public class TrackingService extends Service implements LocationListener{
private LocationManager mLocationManager;
private TrackDb db;
private long trackId;
private boolean isTracking = false;
#Override
public void onCreate() {
super.onCreate();
mNotificationManager = (NotificationManager) this
.getSystemService(NOTIFICATION_SERVICE);
mLocationManager = (LocationManager) getSystemService(LOCATION_SERVICE);
db = new TrackDb(this.getApplicationContext());
}
#Override
public void onStart(Intent intent, int startId) {
super.onStart(intent, startId);
}
#Override
public void onDestroy(){
//TODO
super.onDestroy();
}
#Override
public IBinder onBind(Intent intent){
return this.mBinder;
}
private IBinder mBinder = new ITrackingServiceRemote.Stub() {
public void startTracking(long trackId) throws RemoteException {
TrackingService.this.startTracking(trackId);
}
public void pauseTracking() throws RemoteException {
TrackingService.this.pauseTracking();
}
public void resumeTracking(long trackId) throws RemoteException {
TrackingService.this.resumeTracking(trackId);
}
public void stopTracking() throws RemoteException {
TrackingService.this.stopTracking();
}
public long trackingState() throws RemoteException {
long state = TrackingService.this.trackingState();
return state;
}
};
public synchronized void startTracking(long trackId) {
// request updates every 250 meters or 0 sec
this.trackId = trackId;
mLocationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER,
0, 250, this);
isTracking = true;
}
public synchronized long trackingState() {
if(isTracking){
return trackId;
} else
return -1;
}
public synchronized void stopTracking() {
if(isTracking){
mLocationManager.removeUpdates(this);
isTracking = false;
} else
Log.i(TAG, "Could not stop because service is not tracking at the moment");
}
public synchronized void resumeTracking(long trackId) {
if(!isTracking){
this.trackId = trackId;
mLocationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER,
0, 250, this);
isTracking = true;
} else
Log.i(TAG, "Could not resume because service is tracking already track " + this.trackId);
}
public synchronized void pauseTracking() {
if(isTracking){
mLocationManager.removeUpdates(this);
isTracking = false;
} else
Log.i(TAG, "Could not pause because service is not tracking at the moment");
}
public void onLocationChanged(Location location) {
//TODO
}
For easier access from the client I wrote a ServiceManager class which sets up the ServiceConnection and you can call the service methods. Here my code for this:
public class TrackingServiceManager{
private static final String TAG = "TrackingServiceManager";
private ITrackingServiceRemote mService = null;
private Context mContext;
private Boolean isBound = false;
private ServiceConnection mServiceConnection;
public TrackingServiceManager(Context ctx){
this.mContext = ctx;
}
public void start(long trackId) {
if (isBound && mService != null) {
try {
mService.startTracking(trackId);
} catch (RemoteException e) {
Log.e(TAG, "Could not start tracking!",e);
}
} else
Log.i(TAG, "No Service bound! 1");
}
public void stop(){
if (isBound && mService != null) {
try {
mService.stopTracking();
} catch (RemoteException e) {
Log.e(TAG, "Could not stop tracking!",e);
}
} else
Log.i(TAG, "No Service bound!");
}
public void pause(){
if (isBound && mService != null) {
try {
mService.pauseTracking();
} catch (RemoteException e) {
Log.e(TAG, "Could not pause tracking!",e);
}
} else
Log.i(TAG, "No Service bound!");
}
public void resume(long trackId){
if (isBound && mService != null) {
try {
mService.resumeTracking(trackId);
} catch (RemoteException e) {
Log.e(TAG, "Could not resume tracking!",e);
}
} else
Log.i(TAG, "No Service bound!");
}
public float state(){
if (isBound && mService != null) {
try {
return mService.trackingState();
} catch (RemoteException e) {
Log.e(TAG, "Could not resume tracking!",e);
return -1;
}
} else
Log.i(TAG, "No Service bound!");
return -1;
}
/**
* Method for binding the Service with client
*/
public boolean connectService(){
mServiceConnection = new ServiceConnection() {
#Override
public void onServiceConnected(ComponentName name, IBinder service) {
TrackingServiceManager.this.mService = ITrackingServiceRemote.Stub.asInterface(service);
}
}
#Override
public void onServiceDisconnected(ComponentName name) {
if (mService != null) {
mService = null;
}
}
};
Intent mIntent = new Intent("test.de.android.tracker.action.intent.TrackingService");
this.isBound = this.mContext.bindService(mIntent, mServiceConnection, Context.BIND_AUTO_CREATE);
return this.isBound;
}
public void disconnectService(){
this.mContext.unbindService(mServiceConnection);
this.isBound = false;
}
}
If i now try to call a method from an activity for example start(trackId) nothing happens. The binding is OK. When debugging it always runs into the startTracking() in the generated ITrackingServiceRemote.java file and not into my TrackingService class. Where is the problem? I can't find anything wrong.
Thanks in advance!
Tobias
I need IPC to control the service from
different activities. So I decide to
develop a remote service with AIDL.
You do not need IPC to control the service from different activities. You may need IPC to control the service from different applications (i.e., separate APKs).
When debugging it always runs into the
startTracking() in the generated
ITrackingServiceRemote.java file and
not into my TrackingService class.
Your activity has a client-side proxy representing the service interface. The service itself is supposed to be running in a completely separate process from a completely separate APK.
I recommend that you get rid of the AIDL and switch back to the local binding pattern, at least long enough to get your activity and service working. Then, and only then, should you pull them apart into separate APKs, if that is indeed the desired end.

Categories

Resources