android service 面试

android service 面试

service 生命周期

android service 面试_第1张图片

StartService步骤

1、定义一个类继承于Service

2、在Manifest.xml文件中配置该Service

3、使用Context的startService(Intent)方法启动该Service

4、不再使用时使用stopService(Intent)方法停止该服务

BindService步骤

1、定义一个类继承Service,创建一个继承与Binder的实例对象,并提供公共方法供客户端调用。

2、实现onBind()方法,返回Binder实例

3、在Manifest.xml文件中配置该Service

4、在客户端中,实现ServiceConnection实例,从onServiceConnected()回调方法接收Binder,并使用bindService绑定服务。注:onServiceDiscounnection方法是在服务崩溃或者服务杀死导致的连接中断时调用

源码分析IntentService: https://blog.csdn.net/gyh790005156/article/details/62887407

Service是否在main thread中执行, service里面是否能执行耗时的操作?

Service不是独立的进程,也不是独立的线程,它是依赖于应用程序的主线程的,也就是说,在更多时候不建议在Service中编写耗时的逻辑和操作(比如:网络请求,拷贝数据库,大文件),否则会引起ANR。
如果想在服务中执行耗时的任务。有以下解决方案:
1) 在service中开启一个子线程
new Thread(){}.start();

2) 可以使用IntentService异步管理服务
参考文章IntentService的使用:
http://blog.csdn.net/mwq384807683/article/details/72549222
Service 和 Activity 在同一个线程,对于同一 app 来说默认情况下是在同一个线程中的 main Thread (UI Thread)

Service不死之身

一: 在onStartCommand方法中将flag设置为START_STICKY;

return Service.START_STICKY;

二:在xml中设置了android:priority


 
 

三:在onStartCommand方法中设置为前台进程

@Override
public int onStartCommand(Intent intent, int flags, int startId) {
  Notification notification = new Notification(R.mipmap.ic_launcher, "服务正在运行",System.currentTimeMillis());
   Intent notificationIntent = new Intent(this, MainActivity.class);
    PendingIntent pendingIntent = PendingIntent.getActivity(this, 0,notificationIntent,0);
    RemoteViews remoteView = new RemoteViews(this.getPackageName(),R.layout.notification);
    remoteView.setImageViewResource(R.id.image, R.mipmap.ic_launcher);
    remoteView.setTextViewText(R.id.text , "Hello,this message is in a custom expanded view");
    notification.contentView = remoteView;
    notification.contentIntent = pendingIntent;
    startForeground(1, notification);
    return Service.START_STICKY;
}

四:在onDestroy方法中重启service

@Override
public void onDestroy() {
    super.onDestroy();
    startService(new Intent(this, MyService.class));
}

五:用AlarmManager.setRepeating(…)方法循环发送闹钟广播,接收的时候调用service的onstart方法

	Intent intent = new Intent(MainActivity.this,MyAlarmReciver.class);
    PendingIntent sender = PendingIntent.getBroadcast( MainActivity.this, 0, intent, 0);

    // We want the alarm to go off 10 seconds from now.
    Calendar calendar = Calendar.getInstance();
    calendar.setTimeInMillis(System.currentTimeMillis());
    calendar.add(Calendar.SECOND, 1);
    AlarmManager am = (AlarmManager) getSystemService(ALARM_SERVICE);
    //重复闹钟
    /**
     *  @param type
     * @param triggerAtMillis t 闹钟的第一次执行时间,以毫秒为单位
     * go off, using the appropriate clock (depending on the alarm type).
     * @param intervalMillis 表示两次闹钟执行的间隔时间,也是以毫秒为单位
     * of the alarm.
     * @param operation 绑定了闹钟的执行动作,比如发送一个广播、给出提示等等
     */
    am.setRepeating(AlarmManager.RTC_WAKEUP, calendar.getTimeInMillis(), 2 * 1000, sender);

六:目前市场面的很多三方的消息推送SDK唤醒APP,例如Jpush

总结

这纯粹是面试的时候忽悠一下面试官,不代表着你的Service就永生不死了,只能说是提高了进程的优先级。迄今为止我没有发现能够通过常规方法达到流氓需求(通过长按home键清除都清除不掉)的方法,目前所有方法都是指通过Android的内存回收机制和普通的第三方内存清除等手段后仍然保持运行的方法,有些手机厂商把这些知名的app放入了自己的白名单中,保证了进程不死来提高用户体验(如微信、QQ、陌陌都在小米的白名单中)。如果从白名单中移除,他们终究还是和普通app一样躲避不了被杀的命运。

Service 是否在 main thread 中执行, service 里面是否 能执行耗时的操作?

默认情况,如果没有显示的指 service 所运行的进程, Service 和 activity 是运 行在当前 app 所在进程的 main thread(UI 主线程)里面。
service 里面不能执行耗时的操作(网络请求,拷贝数据库,大文件 )
特殊情况 ,可以在清单文件配置 service 执行所在的进程 ,让 service 在另 外的进程中执行



如何提高service的优先级

1、在AndroidManifest.xml文件中对于intent-filter可以通过android:priority = “1000”这个属性设置最高优先级,1000是最高值,如果数字越小则优先级越低,同时实用于广播。

2、在onStartCommand里面调用 startForeground()方法把Service提升为前台进程级别,然后再onDestroy里面要记得调用stopForeground ()方法。

3、onStartCommand方法,手动返回START_STICKY。

4、 在onDestroy方法里发广播重启service。
service +broadcast 方式,就是当service走ondestory的时候,发送一个自定义的广播,当收到广播的时候,重新启动service。(第三方应用或是在setting里-应用-强制停止时,APP进程就直接被干掉了,onDestroy方法都进不来,所以无法保证会执行)

5、监听系统广播判断Service状态。
通过系统的一些广播,比如:手机重启、界面唤醒、应用状态改变等等监听并捕获到,然后判断我们的Service是否还存活。

6、Application加上Persistent属性。

Service 的 onStartCommand 方法有几种返回值?各代表什么意思?

有四种返回值,不同值代表的意思如下:

  • START_STICKY:如果 service 进程被 kill 掉,保留 service 的状态为开始状态,但不保留递送的 intent 对象。随 后系统会尝试重新创建 service,由于服务状态为开始状态,所以创建服务后一定会调用 onStartCommand(Intent,int,int)方法。如果在此期间没有任何启动命令被传递到 service,那么参数 Intent 将为 null。

  • START_NOT_STICKY:“非粘性的”。使用这个返回值时,如果在执行完 onStartCommand 后,服务被异常 kill 掉,系统不会自动重启该服务。

  • START_REDELIVER_INTENT:重传 Intent。使用这个返回值时,如果在执行完 onStartCommand 后,服务被异 常 kill 掉,系统会自动重启该服务,并将 Intent 的值传入。

  • START_STICKY_COMPATIBILITY: START_STICKY 的兼容版本,但不保证服务被 kill 后一定能重启。

Service 的 onRebind(Intent)方法在什么情况下会执行?

如果在 onUnbind()方法返回 true 的情况下会执行,否则不执行。

Service里面可以弹Toast么?

  • 面试经验:
    面试官问这个问题就是看看你对Service是否深入理解,Service不仅可以弹Toast还能弹出对话框,把Service看成Activity就行,所有的界面都是展示到Window窗体上面的,大家可以回顾下小卫士里面来点归属地不就是在服务里面进行监听归属地进行展示的吗。

  • 答案解析:
    可以的。弹吐司有个条件就是得有一个Context上下文,而Service本身就是Context的子类,因此在Service里面弹Toast是完全可以的。比如我们在Service中完成下载任务后可以弹一个Toast通知用户。

你一般在什么情况下会使用Service?

  • 经验总结:
    Service其实就是背地搞事情,又不想让别人知道,举一个生活当中的例子,你想知道一件事情不需要直接去问,你可以通过侧面了解。这就是Service设计的初衷

  • Service为什么被设计出来?
    根据Service的定义,我们可以知道需要长期在后台进行的工作我们需要将其放在Service中去做。说得再通熟易懂一点,就是不能放在Activity中来执行的工作就必须得放到Service中去做。如:音乐播放、下载、上传大文件、定时关闭应用等功能。这些功能如果放到Activity中做的话,那Activity退出被销毁了的话,那这些功能也就停止了,这显然是不符合我们的设计要求的,所以要将他们放在Service中去执行。

你可能感兴趣的:(android,学习,面试,android,移动端开发)