service息屏保活 和 service的相关使用简介

1.各种点击情况

前提:

mainactivity.java

   private ServiceConnection connection = new ServiceConnection() { 

 

       @Override 

       public void onServiceDisconnected(ComponentName name) { 

       } 

 

       @Override 

       public void onServiceConnected(ComponentName name, IBinder service){ 

           myBinder = (MyService.MyBinder) service; 

           myBinder.startDownload(); 

       } 

   };

 

bindService(bindIntent, connection, BIND_AUTO_CREATE);  

 

 

0.1start stop

start : onCreate()  onStartCommand()

stop: onDestroy

 

0.2bind unbind

bind: 服务的 onCreate()     客户端的onServiceConnected()

unbind: onDestroy

 

1.点击两次start

第一次onCreate()  onStartCommand()

第二次onStartCommand()

 

1.1点击两次bind

bind: 服务的 onCreate()     客户端的onServiceConnected()

第二次, 无效

 

2.点击一次start一次bind

点start : onCreate()  onStartCommand()

点bind: 调用onServiceConnected, 返回服务端的binder

 

3.点一次bind,再点start

bind: 服务的 onCreate()     客户端的onServiceConnected()

start: 服务的onStartCommand()

 

4.start unbind(unbind只有在已经bind的情况下, 仅仅调用一次)

start: onCreate() onStartCommand()

unbind:崩溃

 

5.bind stop

bind: 服务的 onCreate()   客户端的onServiceConnected()

stop: 无反应

 

6. start bind stop

start : onCreate()  onStartCommand()

bind: 调用onServiceConnected, 返回服务端的binder

stop: 无反应

 

7. start bind unbind/stop

start : onCreate()  onStartCommand()

bind: 调用onServiceConnected, 返回服务端的binder

unbind/stop: 无反应

 

8. start bind unbind stop/ startbind stop unbind

start : onCreate()  onStartCommand()

bind: 调用onServiceConnected, 返回服务端的binder

stop unbind/ unbindstop: onDestroy

 

 

额,既然在Service里也要创建一个子线程,那为什么不直接在Activity里创建呢?

(1)    这是因为Activity很难对Thread进行控制,当Activity被销毁之后,就没有任何其它的办法可以再重新获取到之前创建的子线程的实例。

(2)    而且在一个Activity中创建的子线程,另一个Activity无法对其进行操作。

(3)    但是Service就不同了,所有的Activity都可以与Service进行关联,然后可以很方便地操作其中的方法,即使Activity被销毁了,之后只要重新与Service建立关联,就又能够获取到原有的Service中Binder的实例。

因此,使用Service来处理后台任务,Activity就可以放心地finish,完全不需要担心无法对后台任务进行控制的情况。

 

android7.0以前, 可以用两个相同的service分别设置为startForeground前台服务, 然后另一个取消前台服务, 他俩用同一个notification. 那么一个取消了之后, 另一个依然是前台进程, 但是他的notification已经没了. 隐藏起来了.

https://blog.csdn.net/wxx614817/article/details/50669420

这篇文章, 讲解的不错.

 

真正的service bind了一个助手service,然后当

    private class AssistServiceConnectionimplements ServiceConnection { 

        @Override 

        public voidonServiceDisconnected(ComponentName name) { 

            Log.d(TAG, "MyService:onServiceDisconnected"); 

        } 

 

        @Override 

        public voidonServiceConnected(ComponentName name, IBinder binder) { 

            Log.d(TAG, "MyService:onServiceConnected"); 

 

            // sdk >=18 

            // 的,会在通知栏显示service正在运行,这里不要让用户感知,所以这里的实现方式是利用2个同进程的service,利用相同的notificationID, 

            // 2个service分别startForeground,然后只在1个service里stopForeground,这样即可去掉通知栏的显示 

            Service assistService =((AssistService.LocalBinder) binder) 

                    .getService(); 

//相同的notification ID, 用的都是当前进程的PID

            MyService.this.startForeground(PID,getNotification()); 

           assistService.startForeground(PID, getNotification()); 

           assistService.stopForeground(true); 

 

            MyService.this.unbindService(mConnection); 

            mConnection = null; 

        } 

    } 

 

    private Notification getNotification(){ 

        // 定义一个notification 

        Notification notification = newNotification(); 

        Intent notificationIntent = newIntent(this, MainActivity.class); 

        PendingIntent pendingIntent =PendingIntent.getActivity(this, 0, 

                notificationIntent, 0); 

        notification.setLatestEventInfo(this,"My title", "My content", 

                pendingIntent); 

        return notification; 

2. Android:退出程序后保持Serivce开启不关闭  

Android中,service的开启,默认是绑定activity的,是activity级的。

如果要实现当退出程序后,保持Service的运行,那么需要把service设置成为system级的,设置方法:

在AndroidManifest.xml中注册service时,加上属性android:process,如:

<service

     android:name="com.jansun.pushnotification.PushNotificationService"

     android:enabled="true"

     android:process="system"

     />

     

另外,还要在启动service时,加入FLAG_ACTIVITY_NEW_TASK标签,如:

public static void actionStart(Context ctx) {

//System.out.println("----Notification service started!");

Intent i = new Intent(ctx,  PushNotificationService .class);

i.setAction(ACTION_START);

i.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);

ctx.startService(i);

}

 

至此,当你退出程序后,service还在系统后台正常运行,目标达成。

 

3.bindService与startService的区别

bindService启动服务的特点

相比于用startService启动的Service,bindService启动的服务具有如下特点: 
1. bindService启动的服务在调用者和服务之间是典型的client-server的接口,即调用者是客户端,service是服务端,service就一个,但是连接绑定到service上面的客户端client可以是一个或多个。这里特别要说明的是,这里所提到的client指的是组件,比如某个Activity。 
2. 客户端client(即调用bindService的一方,比如某个Activity)可以通过IBinder接口获取Service的实例,从而可以实现在client端直接调用Service中的方法以实现灵活的交互,并且可借助IBinder实现跨进程的client-server的交互,这在纯startService启动的Service中是无法实现的。 
3. 不同于startService启动的服务默认无限期执行(可以通过Context的stopService或Service的stopSelf方法停止运行),bindService启动的服务的生命周期与其绑定的client息息相关。当client销毁的时候,client会自动与Service解除绑定,当然client也可以通过明确调用Context的unbindService方法与Service解除绑定。当没有任何client与Service绑定的时候,Service会自行销毁(通过startService启动的除外)。 
4. startService和bindService二者执行的回调方法不同:startService启动的服务会涉及Service的的onStartCommand回调方法,而通过bindService启动的服务会涉及Service的onBind、onUnbind等回调方法。

4.总结service包活的方法.

 

(1)经测试,当打开当前activity的时候, 按息屏按钮, 该activity所属的进程不会被杀掉.

(2)经测试,打开当前activity. 按下桌面按钮, service不会被杀. 再按息屏. 该activity所属进程被干掉

(3)所以有这么个service息屏包活的想法.

(3-1)用前台进程,保证service是活的. 在切换到别的程序的时候, 该service也是活的.

(3-2)在service里注册开关屏的广播.

mScreenStatusReceiver= new ScreenStatusReceiver();   

 IntentFilter screenStatus =newIntentFilter(Intent.ACTION_SCREEN_UP);   

 screenStatus.addAction(Intent.ACTION_SCREEN_OFF);   

 registerReceiver(mScreenStatusReceiver,screenStatus);  

在广播里这么写

if(action.equals(Intent.ACTION_SCREEN_OFF)){

            // 当屏幕关闭时,启动一个像素的Activity

           Intent activity = new Intent(context,OnePxActivity.class);

           activity.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);

           context.startActivity(activity);

} else if(action.equals(Intent.ACTION_SCREEN_ON)){

           // 用户解锁,关闭Activity

           // 这里发个广播是什么鬼,其实看下面OnePxAcitivity里面的代码就知道了,发这个广播就是为了finish掉OnePxActivity

           Intent broadcast = new Intent("FinishActivity");

           // broadcast.setFlags(32);Intent.FLAG_INCLUDE_STOPPED_PACKAGES

           context.sendBroadcast(broadcast);//发送对应的广播

}

 (3-3)当接受到关屏广播时, 开启一个1像素的activity, 那么该service所属进程有一个activity在显示, 所以该service不会被杀死.

1像素的activity

public class OnePxActivity extends Activity {

    protectedBroadcastReceiver receiver = new BroadcastReceiver() {

        @Override

        public voidonReceive(Context context, Intent intent) {

            // 收到广播

           OnePxActivity.this.finish();

        }

    };

 

    @Override

    protected voidonCreate(Bundle savedInstanceState) {

        super.onCreate(savedInstanceState);

 

        Windowwindow = getWindow();

        // 设置窗口位置在左上角

       window.setGravity(Gravity.LEFT | Gravity.TOP);

       WindowManager.LayoutParams params = window.getAttributes();

        params.x= 0;

        params.y= 0;

       params.width = 1;

       params.height = 1;

        window.setAttributes(params);

 

        // 动态注册广播,这个广播是在屏幕亮的时候,发送广播,来关闭当前的Activity

       registerReceiver(receiver, new IntentFilter("FinishActivity"));

 

    }

 

    @Override

    protected voidonDestroy() {

       unregisterReceiver(receiver);

        Log.e(TAG, TAG + "onDestory");

        super.onDestroy();

    }

 

}

配置文件

<activity

            android:name=".activity.OnePxActivity"            android:configChanges="keyboardHidden|orientation|screenSize|navigation|keyboard"

            android:excludeFromRecents="true"

            android:exported="false"

            android:finishOnTaskLaunch="false"

            android:launchMode="singleInstance"

            android:process=":process"

            android:theme="@style/undeadActivityStyle"

            >

        </activity>

主题

<style name="undeadActivityStyle">

        <!-- 背景设置为透明 -->

        <item name="android:windowBackground">@android:color/transparent</item>

        <!-- 是否有边框 -->

        <item name="android:windowFrame">@null</item>

        <item name="android:windowNoTitle">true</item>

        <!-- 是否浮动在界面上 -->

       <item name="android:windowIsFloating">true</item>

        <!-- 是否透明 -->

        <item name="android:windowIsTranslucent">true</item>

        <!-- 窗体上面是否有遮盖 -->

        <item name="android:windowContentOverlay">@null</item>

        <!-- 背景是否变暗 -->

        <item name="android:backgroundDimEnabled">false</item>

        <!-- 设置背景透明 -->

        <item name="android:windowIsTranslucent">true</item>

        <!-- 为窗体的Enter和Exit设置动画 -->

        <item name="android:windowAnimationStyle">@null</item>

        <!-- 是否禁止窗体显示前显示的View -->

        <item name="android:windowDisablePreview">true</item>

        <item name="android:windowNoDisplay">false</item>

    </style>

 

(4)当收到开屏广播的时候, 这个开启的1像素activity自动关闭了. service仍然是活的.

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值