Manifest:
<service android:name="com.example.MainService" android:process=":main_service"/>
Trying to bind service in Activity:
public class MainActivity extends Activity {
MainService mMainService;
private boolean mBound;
#Override
protected void onCreate(Bundle savedInstanceState) {
bindService(intentForMainService, mConnection, Context.BIND_AUTO_CREATE)
}
private ServiceConnection mConnection = new ServiceConnection() {
public void onServiceConnected(ComponentName className,
IBinder service) {
MainService.MainServiceBinder binder = (MainService.MainServiceBinder) service;//HERE IS EXCEPTION
mMainService = (MainService) binder.getService();
mBound = true;
}
public void onServiceDisconnected(ComponentName className) {
mMainService = null;
mBound = false;
}
};
#Override
protected void onStop() {
doUnbindService();
super.onStop();
}
void doUnbindService() {
if (mBound) {
unbindService(mConnection);
}
}
}
Error:
FATAL EXCEPTION: main
Process: com.hos.android, PID: 9001
java.lang.ClassCastException: android.os.BinderProxy cannot be cast to com.example.service.main.MainService$MainServiceBinder
at com.example.ui.base.BaseServiceActivity$1.onServiceConnected(MainActivity.java:34)
at android.app.LoadedApk$ServiceDispatcher.doConnected(LoadedApk.java:1335)
at android.app.LoadedApk$ServiceDispatcher$RunConnection.run(LoadedApk.java:1352)
at android.os.Handler.handleCallback(Handler.java:739)
at android.os.Handler.dispatchMessage(Handler.java:95)
at android.os.Looper.loop(Looper.java:158)
at android.app.ActivityThread.main(ActivityThread.java:7224)
But when I delete this android:process=":main_service" all works properly
Step #1: Write an AIDL file that describes the interface to be exported by the service that clients can bind to. For the purposes of this answer, I will call this interface Foo, and so the AIDL file would be Foo.aidl. Note that if the client and service are in separate Android Studio modules that both need the same Foo.aidl content.
Step #2: Have your service's binder extend Foo.Stub and override the methods on Foo.Stub, instead of extending IBinder.
Step #3: In your client, in onServiceConnected(), convert the raw binder to a Foo instance via Foo.Stub.asInterface(service), and Foo has the client side of the AIDL-defined API.
This pair of sample projects illustrates this, where in my case the client and the service are in separate apps.
I think so if you do it will be good
Frist of all create Servic
public class MyService extends Service {
MyReceiver receiver = new MyReceiver();
#Override
public void onCreate() {
super.onCreate();
}
#Nullable
#Override
public IBinder onBind(Intent intent) {
return null;
}
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
receiver.startAlarm(this);
return START_STICKY;
}
#Override
public void onStart(Intent intent, int startId) {
receiver.startAlarm(this);
}
}
after start alarm listen to alarm create BroadcastReceiver
public class MyReceiver extends BroadcastReceiver {
#Override
public void onReceive(final Context context, Intent intent) {
Log.e("Receiver", "end alarm")
}
}
public void setAlarm(Context context) {
AlarmManager am = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE);
Intent i = new Intent(context, BootReceiver.class);
PendingIntent pi = PendingIntent.getBroadcast(context, 0, i, 0);
am.setRepeating(AlarmManager.RTC_WAKEUP, System.currentTimeMillis(), 1000 * 10, pi); // Millisec * Second * Minute
}
public void cancelAlarm(Context context) {
Intent intent = new Intent(context, BootReceiver.class);
PendingIntent sender = PendingIntent.getBroadcast(context, 0, intent, 0);
AlarmManager alarmManager = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE);
alarmManager.cancel(sender);
}
add manifest this
<service android:name=".MyService"
android:enabled="true"
android:process=":my_service"/>
<receiver
android:name="MyReceiver"
android:exported="false" >
<intent-filter>
<action android:name="com.parse.push.intent.RECEIVE" />
<action android:name="com.parse.push.intent.DELETE" />
<action android:name="com.parse.push.intent.OPEN" />
</intent-filter>
</receiver>
Related
I want to show local notification on specific time. So that I am using alarm manager to set pending intent for specific time. But in my case Broadcast/Service is not getting called if application killed by user.
Check the below code and help me out why am not getting notification after application killed.
public class MainActivity extends AppCompatActivity {
#RequiresApi(api = Build.VERSION_CODES.M)
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Intent notifyIntent = new Intent(this,MyReceiver.class);
PendingIntent pendingIntent = PendingIntent.getBroadcast
(MainActivity.this, 1, notifyIntent, PendingIntent.FLAG_UPDATE_CURRENT);
AlarmManager alarmManager = (AlarmManager) getSystemService(Context.ALARM_SERVICE);
alarmManager.setExactAndAllowWhileIdle(AlarmManager.RTC_WAKEUP, System.currentTimeMillis()+30000, pendingIntent);
}
}
public class MyReceiver extends BroadcastReceiver {
public MyReceiver() {
}
#Override
public void onReceive(Context context, Intent intent) {
Intent intent1 = new Intent(context, MyNewIntentService.class);
context.startService(intent1);
}
}
public class MyNewIntentService extends Service {
#Nullable
#Override
public IBinder onBind(Intent intent) {
return null;
}
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
super.onStartCommand(intent, flags, startId);
CommonUtil.showNotification(getApplicationContext());
return START_STICKY;
}
}
AndroidManifest.xml
<uses-permission android:name="android.permission.WAKE_LOCK"/>
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED"/>
<receiver
android:name=".MyReceiver"
android:enabled="true"
android:exported="false"
/>
<service
android:name=".MyNewIntentService"
android:exported="false"
/>
You can check here for working sample of Alarm with Broadcast receiver.
How to use Android AlarmManager in Fragment in Kotlin?
I'm a few days, the problem with Android service.
I wrote custom Class from service
I wrote custom class from thread.
I want my service to work after destroy program for send notification, everything is OK but custom class not working after destroy but in stop or pause app, my service work correct.
Please help me fix this problem.
ServiceNotification.class
import Threadcustom;
public class ServiceNotification extends Service {
#Override
public void onCreate() {
super.onCreate();
}
#Override
public int onStartCommand(final Intent intent, int flags, int startId) {
GlobalController.timerTaskService = new TimerTask() {
#Override
public void run() {
Threadcustom threadc = new Threadcustom();
threadc.setDetail("1");
threadc.start();
Threadcustom threadc1 = new Threadcustom();
threadc1.setDetail("2");
threadc1.start();
if (threadc.newMessage == 1) {
CustomNotification customNotification = new CustomNotification();
customNotification.notifiaction("my message");
}
}
};
GlobalController.timerService.schedule(GlobalController.timerTaskService, 0, 5000);
return Service.START_STICKY;
}
public void onTaskRemoved(Intent rootIntent) {
Intent restartService = new Intent(getApplicationContext(),
this.getClass());
restartService.setPackage(getPackageName());
PendingIntent restartServicePI = PendingIntent.getService(
getApplicationContext(), 1, restartService,
PendingIntent.FLAG_ONE_SHOT);
AlarmManager alarmService = (AlarmManager) getApplicationContext().getSystemService(Context.ALARM_SERVICE);
alarmService.set(AlarmManager.ELAPSED_REALTIME, SystemClock.elapsedRealtime() + 5000, restartServicePI);
}
#Override
public void onDestroy() {
super.onDestroy();
}
#Override
public IBinder onBind(Intent arg0) {
return null;
}
#Override
public void onRebind(Intent intent) {
super.onRebind(intent);
}
}
manifest.xml
<receiver
android:name=".services.ServiceBootCompleteReciver"
android:enabled="true" >
<intent-filter>
<action android:name="android.intent.action.BOOT_COMPLETED"/>
<category android:name="android.intent.category.DEFAULT"/>
</intent-filter>
</receiver>
<service
android:name=".services.ServiceNotification"
android:enabled="true"
android:exported="false"
/>
Threadcustom.class
public class ThreadSms extends Thread {
#Override
public void run() {
super.run();
define my url
define http url connection get data from url then insert data to sqlite database in my application.
}
my thread work correct my service work with thread and send notification,but after destroy app notification work but my custom thread not call, any program not crash only said warning
ClassLoader referenced unknown path: /data/app/app.myapp/lib/arm
ClassLoader referenced unknown path: /system/framework/tcmclient.jar
Read this SO Thread
you need a notification for your service if you don't want it being killed by OS
also you can use timer to run/check your service is running or not . you can read this SO Thread for implementing this method
I have a service that gives a notification if user has changed his location. I want this service to keep on running until user explicitly force stops my application in application manager. I have used following method:
Intent intent1 = new Intent(context, LocationService2.class);
PendingIntent contentIntent = PendingIntent.getService(context, 0, intent1, 0);
AlarmManager am = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE);
am.setRepeating(AlarmManager.ELAPSED_REALTIME_WAKEUP, SystemClock.elapsedRealtime(),2*60000, contentIntent);
Service class:
public class LocationService2 extends Service implements GoogleApiClient.ConnectionCallbacks,GoogleApiClient.OnConnectionFailedListener {
private GoogleApiClient mGoogleApiClient;
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
Log.v("TAG", "STARTLS");
mGoogleApiClient = new GoogleApiClient.Builder(this)
.addConnectionCallbacks(this)
.addOnConnectionFailedListener(this)
.addApi(LocationServices.API)
.build();
mGoogleApiClient.connect();
return START_STICKY;
}
#Override
public void onConnected(Bundle bundle) {
Log.i(TAG, "Location services connected.");
Location location = LocationServices.FusedLocationApi.getLastLocation(mGoogleApiClient);
// Use this location to give notification if required.
}
#Override
public void onConnectionSuspended(int i) {
Log.i(TAG, "Location services suspended. Please reconnect.");
}
#Override
public void onConnectionFailed(ConnectionResult connectionResult) {
}
#Nullable
#Override
public IBinder onBind(Intent intent) {
return null;
}
#Override
public void onDestroy() {
super.onDestroy();
mGoogleApiClient.disconnect();
}
}
This method does not work on all phones.
Is AlarmManager the best way to do this. If yes, then how can I improve this code to work on all phones?
You should make your service a Foreground Service. You can find a tutorial here.
Manifest Entry
<receiver android:name="YourPackagename.RestartReceiver">
<intent-filter>
<action android:name="android.intent.action.BOOT_COMPLETED" />
</intent-filter>
</receiver>
<receiver android:name="YourPackagename.AlarmReceiver" >
</receiver>
On phone reboot need to reinitialize alarm manager
RestartReceiver.java
public class RestartReceiver extends BroadcastReceiver {
#Override
public void onReceive(Context context, Intent intent) {
if (intent.getAction().equals(Intent.ACTION_BOOT_COMPLETED)) {
AlarmManager alarmMgr = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE);
Intent intentReciever = new Intent(context, AlarmReceiver.class);
PendingIntent alarmIntent = PendingIntent.getBroadcast(context, 0, intentReciever, 0);
alarmMgr.setRepeating(AlarmManager.RTC_WAKEUP, (System.currentTimeMillis() + GlobalContext.PUSH_NOTIFICATION_INTERVAL),
GlobalContext.PUSH_NOTIFICATION_INTERVAL, alarmIntent);
}
}
}
AlarmReceiver.java
public class AlarmReceiver extends BroadcastReceiver{
#Override
public void onReceive(Context context, Intent intent) {
//you can put your logic over here
}
}
Put below code in your Splash Screen
private void initService() {
if(!app_preferences.getBoolean("isServiceRunning", false))
{
AlarmManager alarmMgr = (AlarmManager) getSystemService(Context.ALARM_SERVICE);
Intent intentReciever = new Intent(LoadingScreen.this, AlarmReceiver.class);
PendingIntent alarmIntent = PendingIntent.getBroadcast(LoadingScreen.this, 0, intentReciever, 0);
alarmMgr.setRepeating(AlarmManager.RTC_WAKEUP, (System.currentTimeMillis()+GlobalContext.PUSH_NOTIFICATION_INTERVAL),
GlobalContext.PUSH_NOTIFICATION_INTERVAL, alarmIntent);
app_preferences.edit().putBoolean("isServiceRunning", true).commit();
}
}
//Note: its not good way to check your Alerm service using shared preference is running or not.
The steps to make a never ending service are :
1.) Start service using alarmManager.
2.) Check in onResume if service is running & restart if not.
3.) Return START_STICKY from onStartCommand().
4.) In OnStartCommand() , create a thread and do the needful from that thread .All the logical stuff should be there in while(true).
This way your service will never be killed .
In given code i have put some good things like you can communicate with activity using binder service via listner. You can notify your activity that you lost internet connction by writing code in service...
Create service as sticky which will never end. if user will kill app it will again automatically restart.
When compare to alarm manager you may face duplication/multiple service get started. like we need to identify and prevent that if Alarm manager already i have created then don't start again as per my another answer written in same question.
Manifest.xml
<receiver android:name=".BootCompleteReceiver"><intent-filter><action android:name="android.intent.action.BOOT_COMPLETED"/></intent-filter></receiver>
<service android:name=".MyService" android:enabled="true" android:exported="false"/>
MyService.java
public class MyService extends Service {
CommunicationListner listener;
public class LocalBinder extends Binder {
public MyService getService() {
// Return this instance of LocalService so clients can call public methods
return MyService.this;
}
}
#Override
public IBinder onBind(Intent intent) {
return mBinder;
}
#Override
public void onCreate() {
super.onCreate();
}
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
try {
unregisterReceiver(internetConnectionReceiver);
} catch (Exception e) {
}
registerReceiver(internetConnectionReceiver, new IntentFilter(ConnectivityManager.CONNECTIVITY_ACTION));
return START_STICKY;
}
#Override
public void onDestroy() {
super.onDestroy();
}
//communication with activity
public void registerChatReceivedListener(CommunicationListner listener) {
this.listener = listener;
}
public void removeChatReceivedListener() {
chatListener = null;
}
private BroadcastReceiver internetConnectionReceiver = new BroadcastReceiver() {
#Override
public void onReceive(Context context, Intent intent) {
}
};
public MyService() {
}
}
To restart your service on restart phone
BootCompleteReceiver.Java
public class BootCompleteReceiver extends BroadcastReceiver {
#Override
public void onReceive(Context context, Intent intent) {
if (intent.getAction().equals(Intent.ACTION_BOOT_COMPLETED)) {
context.startService(new Intent(context, MyService.class));
}
}
}
Put code in you splash screen to start myservice if its already started then also no need to worry.
startService(new Intent(getApplicationContext(), MyService.class));
Start the service anytime it got killed.
#Override
public void onDestroy() {
super.onDestroy();
mGoogleApiClient.disconnect();
startService(new Intent(this, LocationService2.class));
}
The solutions in android 5 and higher is using AlarmManger and Broadcast Receiver
I am trying to create a service that will run on bootup, however when trying it in my emulator the log is not showing my message through log tag, so clearly something is wrong.
Here is my code.
service.java
public class service extends Service {
private static final String TAG = "myapp.mycomp";
public service() {
}
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
Log.i(TAG, "Service started");
Runnable r = new Runnable() {
#Override
public void run() {
/** something to do **/
}
};
Thread service = new Thread(r);
service.start();
return Service.START_STICKY;
}
#Override
public void onDestroy() {
Log.i(TAG, "Service stopped");
}
#Override
public IBinder onBind(Intent intent) {
return null;
}
MyReceiver.java
public class MyReceiver extends BroadcastReceiver {
#Override
public void onReceive(Context context, Intent intent) {
Intent myIntent = new Intent(context, service.class);
context.startService(myIntent);
}
}
XML manifest intent
<receiver android:name=".MyReceiver" >
<intent-filter>
<action android:name="android.intent.action.BOOT_COMPLETED" />
</intent-filter>
</receiver>
XML manifest permission
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />
I want to close the service when user removes the app from current running app list. Here, what I'm doing, when user starts the app, service gets started and remain in progress. But when user removes the app via swipe, new service is being created. I want to close the service. Below is my code.
// Start service using AlarmManager
Calendar cal = Calendar.getInstance();
cal.add(Calendar.SECOND, 10);
Intent intent = new Intent(this, MyService.class);
PendingIntent pintent = PendingIntent.getService(this, 0, intent, 0);
AlarmManager alarm = (AlarmManager) getSystemService(Context.ALARM_SERVICE);
alarm.setRepeating(AlarmManager.RTC_WAKEUP, cal.getTimeInMillis(),
5000, pintent);
startService(new Intent(getBaseContext(), MyService.class));
MyService.java
import android.app.Service;
import android.content.Intent;
import android.os.IBinder;
import android.widget.Toast;
public class MyService extends Service {
int count = 0;
public MyService() {
}
#Override
public IBinder onBind(Intent intent) {
// TODO: Return the communication channel to the service.
throw new UnsupportedOperationException("Not yet implemented");
}
#Override
public void onCreate() {
Toast.makeText(this, "The new Service was Created", Toast.LENGTH_LONG).show();
}
#Override
public void onStart(Intent intent, int startId) {
// For time consuming an long tasks you can launch a new thread here...
count++;
Toast.makeText(this, " Service Started" + " " + count, Toast.LENGTH_LONG).show();
}
#Override
public void onDestroy() {
Toast.makeText(this, "Service Destroyed", Toast.LENGTH_LONG).show();
}
}
According with google's employee Dianne Hackborn explains in a comment on one of her Google+ posts, you have to implemente the onTaskremoved on your service.
[W]hat specifically happens when you swipe away a recent task is it:
(1) kills any background or empty processes of the application (see
http://developer.android.com/guide/topics/fundamentals/processes-and-threads.html#Lifecycle
for what this means), and (2) uses the new
http://developer.android.com/reference/android/app/Service.html#onTaskRemoved(android.content.Intent)
API to tell any services of the application about the task being
removed so it can do whatever it thinks is appropriate.
So I think you can do it this way: In that callback you have to stop the service, and tell the alarm manager to stop starting it again. For that, first of all, you need to pass to the service the pending intent that you use with the AlarmManger, so the service can use the intent to cancel the schedule.
At least, you need all this:
In your service
public class MyService extends Service {
private DefaultBinder mBinder;
private AlarmManager alarmManager ;
private PendingIntent alarmIntent;
private void setAlarmIntent(PendingIntent alarmIntent){
this.alarmIntent=alarmIntent;
}
public void onCreate() {
alarmManager = (AlarmManager) getSystemService(Context.ALARM_SERVICE);
mBinder = new DefaultBinder(this);
}
#Override
public IBinder onBind(Intent intent) {
return mBinder;
}
public void onTaskRemoved (Intent rootIntent){
alarmManager.cancel(alarmIntent);
this.stopSelf();
}
}
Then in other file, you create DefaultBinder Class
public class DefaultBinder extends Binder {
MyService s;
public DefaultBinder( MyService s) {
this.s = s;
}
public MyService getService() {
return s;
}
}
in your activity
MyService service;
protected ServiceConnection mConnection = new ServiceConnection() {
public void onServiceConnected(ComponentName className, IBinder binder) {
service = ((DefaultBinder) binder).getService();
service.setAlarmIntent(pIntent);
}
public void onServiceDisconnected(ComponentName className) {
service = null;
}
};
protected void onResume() {
super.onResume();
bindService(new Intent(this, MainService.class), mConnection,
Context.BIND_AUTO_CREATE);
}
#Override
protected void onStop() {
super.onStop();
if (mConnection != null) {
try {
unbindService(mConnection);
} catch (Exception e) {}
}
}