I have an application containing Activity A, Service S and BroadcastReceiver BR. What I want the application to do is to listen to when the user unlocks the phone. This is currently achieved by having A start S and bind to it. S will start and register BR to listen for "android.intent.action.USER_PRESENT".
The application should theoretically be able to listen for phone unlocks indefinitely in the background. My application completes its purpose, but i have seen in the Android Monitor that memory usage steadily increases, and will increase by approximately 0,033MB for each unlock (every time onReceive is called(?)).
Following is the code.
Activity:
public class MainActivity extends Activity implements BackgroundService.ServiceCallbacks
{
private TextView lastUnlock;
private boolean isBound = false;
private BackgroundService backgroundService;
private ServiceConnection serviceConnection = new ServiceConnection()
{
#Override
public void onServiceConnected(ComponentName name, IBinder service)
{
BackgroundService.LocalBinder binder = (BackgroundService.LocalBinder) service;
backgroundService = binder.getServiceInstance();
backgroundService.registerActivity(MainActivity.this);
}
#Override
public void onServiceDisconnected(ComponentName name)
{
isBound = false;
backgroundService = null;
}
};
/** Activity is created, start service and bind to it **/
#Override
protected void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
lastUnlock = (TextView) findViewById(R.id.lastUnlock_TW);
Intent serviceIntent = new Intent(this, BackgroundService.class);
startService(serviceIntent);
bindService(serviceIntent, serviceConnection, BIND_AUTO_CREATE);
isBound = true;
}
/** Activity is destroyed, it should unbind from the service **/
#Override
protected void onDestroy()
{
super.onDestroy();
if (isBound)
{
backgroundService.unregisterActivity();
unbindService(serviceConnection);
isBound = false;
}
}
/** The service can call this method to update the lastUnlock TextView **/
#Override
public void updateClient(String data)
{
lastUnlock.setText(data);
}
}
Service:
public class BackgroundService extends Service
{
ServiceCallbacks activity;
private final IBinder LOCAL_BINDER = new LocalBinder();
private UserPresentReceiver userPresentReceiver;
SharedPreferences sharedPreferences;
/** The service is created, receivers are registered here **/
#Override
public void onCreate()
{
super.onCreate();
userPresentReceiver = new UserPresentReceiver();
registerReceiver(userPresentReceiver, new IntentFilter("android.intent.action.USER_PRESENT"));
sharedPreferences = PreferenceManager.getDefaultSharedPreferences(this);
}
/** An activity called startService() or the process was killed, returning START_STICKY
** which restarts the service and this method is called **/
#Override
public int onStartCommand(Intent intent, int flags, int startId)
{
return START_STICKY;
}
/** An activity just bound to the service **/
#Override
public IBinder onBind(Intent intent)
{
return LOCAL_BINDER;
}
/** Service is destroyed, unregister the receivers **/
#Override
public void onDestroy()
{
super.onDestroy();
unregisterReceiver(userPresentReceiver);
}
/** **/
public class LocalBinder extends Binder
{
public BackgroundService getServiceInstance()
{
return BackgroundService.this;
}
}
/** Update the activity if it is connected, and save the unlockStatus in the preferences **/
public void updateActivity(String unlockStatus)
{
if (activity != null)
{
this.activity.updateClient(unlockStatus);
}
SharedPreferences.Editor spEditor = sharedPreferences.edit();
spEditor.putString("saved_last_unlock", unlockStatus);
spEditor.apply();
}
/** Methods an activity can call to register or unregister itself to the service **/
public void registerActivity(Activity activity)
{
this.activity = (ServiceCallbacks) activity;
// If the last unlock is saved in the preferences, retrieve it from there
String savedLastUnlock = sharedPreferences.getString("saved_last_unlock", null);
if (savedLastUnlock != null)
{
this.activity.updateClient(savedLastUnlock);
}
}
public void unregisterActivity()
{
activity = null;
}
/** An activity has to implement this interface so that the service can send commands to it **/
public interface ServiceCallbacks
{
void updateClient(String data);
}
}
BroadcastReceiver:
public class UserPresentReceiver extends BroadcastReceiver
{
private final String TAG = "UserPresentReceiver";
UnlockStatus unlockStatus;
public UserPresentReceiver()
{
unlockStatus = new UnlockStatus();
}
#Override
public void onReceive(Context context, Intent intent)
{
unlockStatus.setStatus(new Date());
BackgroundService service = (BackgroundService) context;
service.updateActivity(unlockStatus.getStatus());
}
}
UnlockStatus:
public class UnlockStatus
{
private Calendar calendar;
private final SimpleDateFormat SDF = new SimpleDateFormat("dd.MM.yyyy' kl. 'HH:mm:ss");
private boolean unlockRegistered = false;
public UnlockStatus()
{
calendar = Calendar.getInstance();
}
public String getStatus()
{
if (unlockRegistered)
return SDF.format(calendar.getTime());
else
return null;
}
public void setStatus(Date date)
{
unlockRegistered = true;
calendar.setTime(date);
}
}
Please find the solution
public class MyApplication extends Application implements HM_Constants, Application.ActivityLifecycleCallbacks, ComponentCallbacks2 {
public static String stateOfLifeCycle = "";
public static boolean wasInBackground = false;
private static HydratemateApplication mInstance;
private static String TAG = HydratemateApplication.class.getName();
boolean status;
ScreenOffReceiver screenOffReceiver = new ScreenOffReceiver();
public static synchronized HydratemateApplication getInstance() {
return mInstance;
}
#Override
public void onCreate() {
super.onCreate();
mInstance = this;
registerActivityLifecycleCallbacks(this);
registerReceiver(screenOffReceiver, new IntentFilter("android.intent.action.SCREEN_OFF"));
// new HM_PrefsManager(mInstance).save(Prefs_Keys.SERVICE_THREAD_STOP,"NO");
}
#Override
public void onActivityCreated(Activity activity, Bundle arg1) {
// Log.d(TAG, "onActivityCreated " + activity.getLocalClassName());
wasInBackground = false;
status = false;
stateOfLifeCycle = "Create";
}
#Override
public void onActivityStarted(Activity activity) {
// Log.d(TAG, "onActivityStarted " + activity.getLocalClassName());
stateOfLifeCycle = "Start";
}
#Override
public void onActivityResumed(Activity activity) {
Log.d(TAG, "onActivityResumed " + activity.getLocalClassName());
stateOfLifeCycle = "Resume";
try {
Intent service = new Intent(getApplicationContext(), VolumeService.class);
stopService(service);
} catch (Exception e) {
e.printStackTrace();
}
try {
if (BatteryHealthActivity.mBluetoothLeForegroundService != null && status) {
//BatteryHealthActivity.mBluetoothLeForegroundService.indicateCharacteristic(UUID.fromString(GattAttributes.BATTERY_LEVEL_SERVICE_UUID), UUID.fromString(GattAttributes.BATTERY_LEVEL_CHARACTERSTIC_UUID), true);
status = false;
}
} catch (Exception e) {
e.printStackTrace();
}
}
#Override
public void onActivityPaused(Activity activity) {
// Log.d(TAG, "onActivityPaused " + activity.getLocalClassName());
stateOfLifeCycle = "Pause";
}
#Override
public void onActivityStopped(Activity activity) {
// Log.d(TAG, "onActivityStopped " + activity.getLocalClassName());
stateOfLifeCycle = "Stop";
}
#Override
public void onActivitySaveInstanceState(Activity activity, Bundle arg1) {
//Log.d(TAG, "onActivitySaveInstanceState " + activity.getLocalClassName());
}
#Override
public void onActivityDestroyed(Activity activity) {
// Log.d(TAG, "onActivityDestroyed " + activity.getLocalClassName());
Log.d("iam", "calling");
wasInBackground = false;
stateOfLifeCycle = "Destroy";
}
#Override
public void onTrimMemory(int level) {
if (stateOfLifeCycle.equals("Stop")) {
wasInBackground = true;
}
super.onTrimMemory(level);
Log.d(TAG, "onTrimMemory " + level);
onBackground();
}
public void onBackground(){
if (!isMyServiceRunning(VolumeService.class)) {
try {
status = true;
if (BatteryHealthActivity.mBluetoothLeForegroundService != null) {
BatteryHealthActivity.mBluetoothLeForegroundService.indicateCharacteristic(UUID.fromString(GattAttributes.BATTERY_LEVEL_SERVICE_UUID), UUID.fromString(GattAttributes.BATTERY_LEVEL_CHARACTERSTIC_UUID), false);
}
new ForegroundCheckTask().execute(mInstance).get();
} catch (InterruptedException e) {
e.printStackTrace();
} catch (ExecutionException e) {
e.printStackTrace();
}
}
}
private boolean isMyServiceRunning(Class<?> serviceClass) {
ActivityManager manager = (ActivityManager) getSystemService(Context.ACTIVITY_SERVICE);
for (ActivityManager.RunningServiceInfo service : manager.getRunningServices(Integer.MAX_VALUE)) {
if (serviceClass.getName().equals(service.service.getClassName())) {
return true;
}
}
return false;
}
class ScreenOffReceiver extends BroadcastReceiver {
#Override
public void onReceive(Context context, Intent intent) {
wasInBackground = true;
onBackground();
}
}}
Related
run time exception:
System.err:java.lang.RuntimeException: Stub!
at com.google.android.things.pio.PeripheralManager.getInstance(PeripheralManager.java:21)
at com.afollestad.remotedemo.RemoteService$1.testPeripheralManager(RemoteService.java:33)
at com.afollestad.remotedemo.IRemoteAIDL$Stub.onTransact(IRemoteAIDL.java:56)
at android.os.Binder.execTransact(Binder.java:697)
Remote service's Manifest file:
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.afollestad.remotedemo">
<uses-permission android:name="com.google.android.things.permission.USE_PERIPHERAL_IO" />
<application>
<service
android:name=".RemoteService"
android:process=":remote">
<intent-filter>
<action android:name="service.remote" />
</intent-filter>
</service>
</application>
MainActivity:
public class MainActivity extends Activity {
private IRemoteAIDL mService;
private TextView result;
private Button connectRemote;
private Button disconnectRemote;
private ServiceConnection mConnection = new ServiceConnection() {
public void onServiceConnected(ComponentName className, IBinder service) {
Log.d("aidl", "onServiceConnected" + service + " className " + className);
mService = IRemoteAIDL.Stub.asInterface(service);
try {
mService.testPeripheralManager();
} catch (RemoteException e) {
e.printStackTrace();
}
}
public void onServiceDisconnected(ComponentName className) {
Log.d("aidl", "onServiceDisconnected");
mService = null;
}
};
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
result = (TextView) findViewById(R.id.result);
connectRemote = (Button) findViewById(R.id.connect_remote);
disconnectRemote = (Button) findViewById(R.id.disconnect_remote);
connectRemote.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
Log.d("aidl", "onClick new thread");
Intent intent = new Intent();
intent.setAction("service.remote");
intent.setPackage("com.afollestad.remotedemo");
bindService(intent, mConnection, Context.BIND_AUTO_CREATE);
}
});
disconnectRemote.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
Log.d("aidl", "onClick");
unbindService(mConnection);
}
});
}}
remote service:
public class RemoteService extends Service {
private I2cDevice mI2cDevice = null;
private static final String I2C_DEVICE_NAME = "I2C1";
private static final int I2C_ADDRESS = 0x5c;
public Context mContext;
private boolean flag;
#Override
public void onCreate() {
super.onCreate();
}
private final IRemoteAIDL.Stub remoteBinder = new IRemoteAIDL.Stub() {
#Override
public void testPeripheralManager(){
Log.d("aidl", "RemoteService PeripheralManager");
try {
PeripheralManager manager = PeripheralManager.getInstance();
Log.d("aidl", "PeripheralManager2");
mI2cDevice = manager.openI2cDevice(I2C_DEVICE_NAME, I2C_ADDRESS);
if (mI2cDevice != null) Log.i("aidl", "I2C device open successful!");
}catch(RuntimeException e){
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
};
#Override
public IBinder onBind(Intent intent) {
Log.d("aidl", "onBind");
mContext = this;
return remoteBinder;
}
#Override
public boolean onUnbind(Intent intent) {
flag = true;
return super.onUnbind(intent);
}
I bulid remote service in android things module, call PeripheralManager.getInstance() in remote service.
If any solve this problem, Please help me.
You should have a uses-library as part of the Manifest declaration, that would prevent you from installing an apk that requires Android Things in a device that does not have it, which looks like is what is happening here.
My app uses a service which I have designed. Problem is the app works fine on some phones (like Gionee, Asus phones) but does not work on Nexus, One Plus or Moto. On theses devices the service pauses on minimising the app. These are my corresponding classes.
public class Sync extends AppCompatActivity {
Button listen;
Button stopListen;
SyncService syncService;
boolean syncServiceBound = false;
/* CreateActivity */
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_discoverer);
/*
Initialise
*/
listen = (Button)findViewById(R.id.btn_listen);
stopListen = (Button)findViewById(R.id.btn_stop_listener);
/*
* Check if device is connected via wifi
*/
ConnectivityManager connectivityManager = (ConnectivityManager)getSystemService(Context.CONNECTIVITY_SERVICE);
NetworkInfo networkInfo = connectivityManager.getNetworkInfo(ConnectivityManager.TYPE_WIFI);
if(networkInfo.isConnected()){
displayToast("Connected via wifi");
}else{
displayToast("Not connected");
}
/**
* Start broadcasting if device is not already broadcasting
* Start listening for broadcasts if not already listening
*/
listen.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
final Intent syncServiceIntent = new Intent(getBaseContext(), SyncService.class);
bindService(syncServiceIntent, syncServiceConnection, Context.BIND_AUTO_CREATE);
startService(syncServiceIntent);
startPeerListUIThread();
}
});
stopListen.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
final Intent syncServiceIntent = new Intent(getBaseContext(), SyncService.class);
if(syncServiceBound) {
unbindService(syncServiceConnection);
}
syncServiceBound = false;
stopService(syncServiceIntent);
stopPeerListUIThread();
}
});
}
#Override
protected void onResume() {
super.onResume();
}
#Override
protected void onPause() {
super.onPause();
}
#Override
protected void onDestroy(){
unbindService(syncServiceConnection);
super.onDestroy();
}
private ServiceConnection syncServiceConnection = new ServiceConnection() {
#Override
public void onServiceConnected(ComponentName className,
IBinder service) {
SyncService.SyncServiceBinder binder = (SyncService.SyncServiceBinder) service;
syncService = binder.getService();
syncServiceBound = true;
}
#Override
public void onServiceDisconnected(ComponentName arg0) {
syncServiceBound = false;
}
};
}
and
public class SyncService extends Service {
private final IBinder syncServiceBinder = new SyncServiceBinder();
public SyncService() {
// initialise
}
#Override
public void onCreate() {
}
#Override
public int onStartCommand(Intent intent, int flags, int startId){
// do something
return START_STICKY;
}
#Override
public IBinder onBind(Intent intent) {
return syncServiceBinder;
}
#Override
public boolean stopService(Intent name) {
// do something
return super.stopService(name);
}
#Override
public void onDestroy() {
// do something
super.onDestroy();
}
public class SyncServiceBinder extends Binder {
SyncService getService() {
// Return this instance of SyncService so activity can call public methods
return SyncService.this;
}
}
}
Initially I thought using android M was the problem (the doze feature may have been interfering) but is not the case apparently.
I'm using following code to stop my service
Intent intent = new Intent(MainActivity.this, UsageRecorderService.class);
stopService(intent);
And this is my service that works indefinitely
public class UsageRecorderService extends IntentService {
public UsageRecorderService() {
super("UsageRecorder");
}
#Override
protected void onHandleIntent(Intent intent) {
while (true) {
UsageRecorder.recordUsages(this, false);
SystemClock.sleep(10000);
}
}
}
Why does not stop my service?
This code would work
public class UsageRecorderService extends IntentService {
private boolean mStop = false;
public UsageRecorderService() {
super("UsageRecorder");
}
public final Object sLock = new Object();
public void onDestroy() {
synchronized (sLock) {
mStop = true;
}
}
#Override
protected void onHandleIntent(Intent intent) {
while (true) {
synchronized (sLock) {
if (mStop) break;
}
UsageRecorder.recordUsages(this, false);
SystemClock.sleep(10000);
}
}
}
You can use stopService
Intent intent = new Intent(MainActivity.this, UsageRecorderService.class);
stopService(intent);
Also I recommend to read Services guide to understand what is going there.
Activity:
sendBroadcast(new Intent(ACTION_STOP));
IntentService
public class UsageRecorderService extends IntentService {
private static final String TAG = "UsageRecorderService";
String ACTION_STOP = "com.xxx.UsageRecorderService.ACTION_STOP";
boolean stop;
public UsageRecorderService() {
super("UsageRecorder");
}
private BroadcastReceiver receiver = new BroadcastReceiver() {
#Override public void onReceive(Context context, Intent intent) {
if (ACTION_STOP.equals(intent.getAction())) {
stop = true;
}
}
};
#Override public void onCreate() {
super.onCreate();
IntentFilter intentFilter = new IntentFilter(ACTION_STOP);
registerReceiver(receiver, intentFilter);
}
#Override
protected void onHandleIntent(Intent intent) {
Log.i(TAG,"onHandleIntent");
while (true && !stop) {
Log.i(TAG,"----running----");
//UsageRecorder.recordUsages(this, false);
SystemClock.sleep(10000);
}
}
#Override public void onDestroy() {
super.onDestroy();
unregisterReceiver(receiver);
}
}
An IntentService is designed to stop itself only when all the requests present in the work queue have been handled.Android stops the service after all start requests have been handled.
I have the following abstract class:
public abstract class AbstractService extends Service {
#Override
public IBinder onBind(Intent intent) {
return null;
}
}
This class is extended by two other classes:
public abstract class AbstractMessengerService extends AbstractService {
static final int MSG_REGISTER_CLIENT = 9991;
static final int MSG_UNREGISTER_CLIENT = 9992;
ArrayList<Messenger> mClients = new ArrayList<Messenger>(); // Keeps track of all current registered clients.
final Messenger mMessenger = new Messenger(new IncomingHandler()); // Target we publish for clients to send messages to IncomingHandler.
private class IncomingHandler extends Handler { // Handler of incoming messages from clients.
#Override
public void handleMessage(Message msg) {
switch (msg.what) {
case MSG_REGISTER_CLIENT:
Log.i("MyService", "Client registered: " + msg.replyTo);
mClients.add(msg.replyTo);
break;
case MSG_UNREGISTER_CLIENT:
Log.i("MyService", "Client un-registered: "+msg.replyTo);
mClients.remove(msg.replyTo);
break;
default:
//super.handleMessage(msg);
onReceiveMessage(msg);
}
}
}
#Override
public void onCreate() {
super.onCreate();
onStartService();
Log.i("MyService", "Service Started.");
}
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
Log.i("MyService", "Received start id " + startId + ": " + intent);
return START_STICKY; // run until explicitly stopped.
}
#Override
public IBinder onBind(Intent intent) {
return mMessenger.getBinder();
}
#Override
public void onDestroy() {
super.onDestroy();
onStopService();
Log.i("MyService", "Service Stopped.");
}
protected void send(Message msg) {
for (int i=mClients.size()-1; i>=0; i--) {
try {
Log.i("MyService", "Sending message to clients: "+msg);
mClients.get(i).send(msg);
}
catch (RemoteException e) {
// The client is dead. Remove it from the list; we are going through the list from back to front so this is safe to do inside the loop.
Log.e("MyService", "Client is dead. Removing from list: "+i);
mClients.remove(i);
}
}
}
public abstract void onStartService();
public abstract void onStopService();
public abstract void onReceiveMessage(Message msg);
}
And:
public abstract class AbstractAIDLService extends AbstractService {
private Handler handler;
ArrayList<Messenger> mClients = new ArrayList<Messenger>(); // Keeps track of all current registered clients.
private final IRemoteService.Stub mBinder = new IRemoteService.Stub() {
public int getPid(){
return android.os.Process.myPid();
}
#Override
public void setActivityColor(String color, long startTime) throws RemoteException {
long elpsedTime = (System.nanoTime() - startTime) / (1000 * 1000);
showElpesedTime(String.valueOf(elpsedTime));
}
public void basicTypes(int anInt, long aLong, boolean aBoolean,
float aFloat, double aDouble, String aString) {
// Does nothing
}
};
private void showElpesedTime(final String time)
{
handler.post(new Runnable() {
public void run() {
Toast toast = Toast.makeText(AbstractAIDLService.this, "Time passed reaching the server: "+time+"ms", Toast.LENGTH_SHORT);
toast.show();
}
});
}
#Override
public void onCreate() {
super.onCreate();
onStartService();
Log.i("MyService", "Service Started.");
}
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
Log.i("MyService", "Received start id " + startId + ": " + intent);
return START_STICKY; // run until explicitly stopped.
}
#Override
public IBinder onBind(Intent intent) {
return mBinder;
}
#Override
public void onDestroy() {
super.onDestroy();
onStopService();
Log.i("MyService", "Service Stopped.");
}
public abstract void onStartService();
public abstract void onStopService();
public abstract void onReceiveMessage(Message msg);
}
Now I created a ServiceManager class which is a factory class that I want to create concrete version of those class and passed them to this manager class. I have a constructor in this ServiceManager:
public class ServiceManager {
private static final String TAG = ServiceManager.class.getSimpleName();
private Class<? extends AbstractService> mServiceClass;
public ServiceManager(Context context, ServiceType type, Class<? extends AbstractService> serviceClass, Handler incomingHandler) {
this.mActivity = context;
this.mIncomingHandler = incomingHandler;
if (type.equals(ServiceType.AIDL)) {
this.mServiceClass = (AbstractAIDLService) serviceClass;
} else if (type.equals(ServiceType.MESSENGER)) {
this.mServiceClass = (AbstractMessengerService) serviceClass;
}
if (isRunning()) {
doBindService();
}
}
But for some reason, those lines: this.mServiceClass = (AbstractAIDLService) serviceClass;, this.mServiceClass = (AbstractMessengerService) serviceClass; give me a casting problem. How can this be done?
I think in your ServiceManager you cannot assign a AbstractAIDLService or AbstractMessengerService to Class<? extends AbstractService> mServiceClass because they are different classes and Class is not the father class of the other two.
I don't know what are you trying to do but this should work:
public class ServiceManager {
private static final String TAG = ServiceManager.class.getSimpleName();
private AbstractService mServiceClass;
public ServiceManager(Context context, ServiceType type, AbstractService serviceClass, Handler incomingHandler) {
this.mActivity = context;
this.mIncomingHandler = incomingHandler;
this.mServiceClass = serviceClass;
if (isRunning()) {
doBindService();
}
}
And save the ServiceType in other variable.
I got the problem that I don't know how can I fetch return value from services. Why I want return value from services is I want to show this return value in Activity page. Following is my services file and return value is retvalue.
public class SyncService extends Service{
private String forSync, lastrecordfromlocal, userdefined;
DatabaseUtil dbUtil = new DatabaseUtil(this);
#Override
public IBinder onBind(Intent arg0) {
// TODO Auto-generated method stub
return null;
}
#SuppressWarnings("deprecation")
#Override
public void onStart(Intent intent, int startId) {
// TODO Auto-generated method stub
super.onStart(intent, startId);
forSync = common.getInfoForSync(this);
String[] getlist = forSync.split(":");
lastrecordfromlocal = getlist[0].toString();
userdefined = getlist[1].toString();
if (common.isNetAvailable(this) == true) {
SyncServiceTask InstallData = new SyncServiceTask(this);
try {
String (((retvalue))) = InstallData.execute(lastrecordfromlocal, userdefined).get();
} catch (InterruptedException e) {
e.printStackTrace();
} catch (ExecutionException e) {
e.printStackTrace();
}
}
this.stopSelf();
}
#Override
public void onDestroy() {
super.onDestroy();
}
}
As far as I know, the common way for service to communicate with activity is by BROADCAST.
You can send a broadcast at the position you want to "return retvalue" by something like:
Intent retIntent = new Intent(ServiceReturnIntent);
retIntent.putExtra("retvalue", retvalue);
sendBroadcast(retIntent);
which ServiceReturnIntent and "retvalue" are all self-defined strings to identify the broadcast and value name.
And in your activity which wishes to catch the return value, you should have a broadcast receiver, with something like:
public class myActivity extends Activity implements BroadcastReceiver {
TextView myTextView;
#Override
OnCreate(Bundle savedInstanceState) {
setContentView(R.layout.simple_layout);
myTextView = (TextView) findViewByID(R.id.simple_textview);
}
#Override
public void onReceive(Context context, Intent intent) {
int action = jumpTable.get(intent.getAction());
switch (action) {
case ServiceReturnIntent:
String valueFromService = intent.getStringExtra("retvalue");
myTextView.setText(valueFromService);
break;
// handle other action
......
}
}
You can read this tutorial for more about broadcast in android.
EDIT
modify sample code with setting it to a textview
You can bind service to the Activity:link
Your Service:
public class SyncService extends Service {
private final IBinder mBinder = new MyBinder();
private String;
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
forSync = common.getInfoForSync(this);
String[] getlist = forSync.split(":");
lastrecordfromlocal = getlist[0].toString();
userdefined = getlist[1].toString();
if (common.isNetAvailable(this) == true) {
SyncServiceTask InstallData = new SyncServiceTask(this);
try {
String (((retvalue))) = InstallData.execute(lastrecordfromlocal, userdefined).get();
} catch (InterruptedException e) {
e.printStackTrace();
} catch (ExecutionException e) {
e.printStackTrace();
}
}
return Service.START_NOT_STICKY;
}
#Override
public IBinder onBind(Intent arg0) {
return mBinder;
}
public class MyBinder extends Binder {
SyncService getService() {
return SyncService .this;
}
}
public String getRetValue() {
return retvalue;
}
}
And in Activity check the value:
SyncService mService;
#Override
protected void onStart() {
super.onStart();
// Bind to LocalService
Intent intent = new Intent(this, SyncService .class);
bindService(intent, mConnection, Context.BIND_AUTO_CREATE);
}
#Override
protected void onStop() {
super.onStop();
// Unbind from the service
if (mBound) {
unbindService(mConnection);
mBound = false;
}
}
/** Called when a button is clicked (the button in the layout file attaches to
* this method with the android:onClick attribute) */
public void onButtonClick(View v) {
if (mBound) {
Toast.makeText(this, "number: " + num, Toast.LENGTH_SHORT).show();
}
}
/** Defines callbacks for service binding, passed to bindService() */
private ServiceConnection mConnection = new ServiceConnection() {
#Override
public void onServiceConnected(ComponentName className,
IBinder service) {
LocalBinder binder = (LocalBinder) service;
mService = binder.getService();
mBound = true;
}
#Override
public void onServiceDisconnected(ComponentName arg0) {
mBound = false;
}
};
if you want service to communicate with activity.we have two method.
1, you can use BROADCAST. you can send BROADCAST in service and use BroadcastReceiver in activity.
2, you also can use bindService to communicate activity.
public class LocalService extends Service {
// This is the object that receives interactions from clients. See
// RemoteService for a more complete example.
private final IBinder mBinder = new LocalBinder();
public class LocalBinder extends Binder {
LocalService getService() {
return LocalService.this;
}
}
#Override
public IBinder onBind(Intent intent) {
return mBinder;
}
}
you can use iBinder to communicate with service