精华内容
下载资源
问答
  • 其实我们开发者并不想让自己做的应用变成流氓软件,但是没办法, 你的老板需要,你要不想让你的应用常驻,那咱就常驻不了了。。。所以说,言归正传。。。  第一篇准备使用系统的服务保活。如果想看提高app的进程...

           其实我们开发者并不想让自己做的应用变成流氓软件,但是没办法, 你的老板需要,你要不想让你的应用常驻,那咱就常驻不了了。。。所以说,言归正传。。。

          第一篇准备使用系统的服务保活。如果想看提高app的进程等级来实现应用保活,可以直接进行点击Android进程守护,让APP在系统内存中常驻(二)跳转。

           一:系统拉活service进程

               1.首先新建一个service,在服务中重写onStartCommand方法,注意要返回的值。

    public class StickService extends Service {
        public StickService() {
        }
    
        @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) {
            return START_STICKY;
        }
    }
    

             2.写完服务直接在活动中启动服务即可,这就是第一种系统拉活service进程。

    public class MainActivity extends AppCompatActivity {
    
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_main);
    
            //1.系统拉活service进程
            startService(new Intent(this,StickService.class));
        }
    }
    

         二:通过jobScheduler拉活

             1.新建立一个服务,不过是继承JobSerive的。

    package zj.it.bhne.androidprocess;
    
    import android.app.job.JobParameters;
    import android.app.job.JobService;
    import android.os.Build;
    import android.support.annotation.RequiresApi;
    import android.widget.Toast;
    
    @RequiresApi(api = Build.VERSION_CODES.LOLLIPOP)
    public class JobSchedulerService extends JobService {
        public JobSchedulerService() {
        }
    
    
        @Override
        public boolean onStartJob(JobParameters params) {
            Toast.makeText(this, "梁锎你好帅!!!", Toast.LENGTH_SHORT).show();
            return false;
        }
    
        @Override
        public boolean onStopJob(JobParameters params) {
            return false;
        }
    }
    

            2.在活动中需要创建JobScheduler,这个需要构建一下,全都写在下面了。

    public class MainActivity extends AppCompatActivity {
    
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_main);
    
            //1.系统拉活service进程
            //startService(new Intent(this,StickService.class));
    
            //2.通过jobScheduler拉活
            startJob();
    
        }
    
        /**
         * 通过jobScheduler拉活
         */
        private void startJob() {
    
            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP){
                JobScheduler jobScheduler = (JobScheduler) getSystemService(JOB_SCHEDULER_SERVICE);
                if (jobScheduler != null){
                    JobInfo.Builder builder = new JobInfo.Builder(1,new ComponentName(getPackageName(),JobSchedulerService.class.getName()));
                    builder.setRequiredNetworkType(JobInfo.NETWORK_TYPE_ANY);
                    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N){
                        builder.setMinimumLatency(1000);
                    }else {
                        builder.setPeriodic(3000);
                    }
                    jobScheduler.schedule(builder.build());
                }
            }
    
        }
    }
    

             3.需要在AndroidManifest中声明下权限。

    <service
                android:name=".JobSchedulerService"
                android:enabled="true"
                android:exported="true"
                android:permission="android.permission.BIND_JOB_SERVICE"/>

      

        三:通过bindService,通过ServiceConnection来拉活

              1.首先还是新建一个服务。

    public class LiveService extends Service {
        public LiveService() {
        }
    
        @Override
        public IBinder onBind(Intent intent) {
            return new LocalBinder();
        }
    
        public static class LocalBinder extends Binder{
    
        }
    
    }
    

           2.在活动中调用。

     @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_main);
    
            //1.系统拉活service进程
            //startService(new Intent(this,StickService.class));
    
            //2.通过jobScheduler拉活
            //startJob();
    
            //3.通过bindService,通过ServiceConnection来拉活
            bindService();
        }
    
        private void bindService() {
            bindService(new Intent(this,LiveService.class),connection, Context.BIND_AUTO_CREATE);
        }
    
        private ServiceConnection connection = new ServiceConnection() {
            @Override
            public void onServiceConnected(ComponentName name, IBinder service) {
    
            }
    
            @Override
            public void onServiceDisconnected(ComponentName name) {
    
            }
        };

          好了。今天先写这三种,这三种属于系统直接拉活的方法。明天再写一篇吧,明天的有两种,都是用来提升app的进程等级的。有很多地方写的不完善,希望各位大佬指点。

    展开全文
  • 冰箱和绿色守护可以杀死常驻内存的流氓软件,原理是什么?
  • 随着AlarmManager唤醒、native进程拉起等方式的失效,APP常驻内存的时代将不复存在,尤其是当APP进程被杀死后,基本很难将其拉起。从用户的角度来讲,这是一种很好的发展,而这一切应该归功于谷歌和各大厂商不断追求...

    探讨Android6.0及以上系统APP常驻内存(保活)实现-复活篇

    (转载请声明出处:http://blog.csdn.net/andrexpert/article/details/75174586)

    APP保活系列(最高支持到Android 7.0)
    (1) 探讨一种新型的双进程守护应用保活方法
    (2) 探讨Android6.0及以上系统APP常驻内存(保活)实现-争宠篇
    (3) 探讨Android6.0及以上系统APP常驻内存(保活)实现-复活篇


          APP常驻内存(保活),又旧事重提,距离上一次的研究亦有半年有余。最近,用户反馈说多进程守护方案在华为Mate8(7.0)保活效果不是很好,有时候还是不能及时收到消息,于是,又带着怀疑的眼光,重新找回原来的代码进行测试,顺便分析了市场上主流运动类APP保活方法(微信、手Q就算了,富人家的孩子,不具代表性),同时也对系统对内存中APP的管理规则进行了进一步探索。本文便是对最近一周的探索、学习、测试的总结之一,以备将来不时之需。

    一、APP复活核心思想归纳
         随着AlarmManager唤醒、native进程拉起等方式的失效,APP常驻内存的时代将不复存在,尤其是当APP进程被杀死后,基本很难将其拉起。从用户的角度来讲,这是一种很好的发展,而这一切应该归功于谷歌和各大厂商不断追求良好的用户体验;从开发者的角度来说,尤其是即时通信类应用,这将是毁灭性打击。如果用户使用你的聊天软件,但在使用过程中总是不能及时收到对方的消息,那将是一种什么样的体验,因此,厂商"白名单"便应运而生了。正是因为如此,本文探讨的相关方案不可能保证在任何时候,或者任何机型能够唤醒,一切都是相对存在的。
        接下来,我们先了解下哪些情况下进程会被杀死:
       1. LowMemoryKiller:这种情况是触发了系统进程管理机制,通过系统会参照当前系统资源情况和oom_adj值来回收进程,oom_adj越大,越容易被杀死;
       2. 第三方清理软件:杀死oom_adj值大于4的进程,如果拥有root权限,理论可杀死所有进程;
       3. 厂商杀进程:可杀所有进程
       4. Force-stop:可杀所有非系统进程
    二、APP复活方案探讨
    1. 使用JobScheduler

         JobScheduler是谷歌在Android 5.0引入的一个能够执行某项任务的API,它允许APP在将来达到一定条件时执行指定的任务。通常情况下,即使APP被强制停止,预定的任务仍然会被执行。JobScheduler工作原理:
         首先在一个实现了JobService的子类的onStartJob方法中执行这项任务,使用JobInfo的Builder方法来设定条件并和实现了JobService的子类的组件名绑定,然后调用系统服务JobScheduler的schedule方法。这样,即便在执行任务之前应用程序进程被杀,也不会导致任务不会执行,因为系统服务JobScheduler会使用bindServiceAsUser的方法把实现了JobService的子类服务启动起来,并执行它的onStartJob方法
    (1) AliveJobService.java

    /**JobService,支持5.0以上forcestop依然有效
     *
     * Created by jianddongguo on 2017/7/10.
     */
    @TargetApi(21)
    public class AliveJobService extends JobService {
        private final static String TAG = "KeepAliveService";
        // 告知编译器,这个变量不能被优化
        private volatile static Service mKeepAliveService = null;
    
        public static boolean isJobServiceAlive(){
            return mKeepAliveService != null;
        }
    
        private static final int MESSAGE_ID_TASK = 0x01;
    
        private Handler mHandler = new Handler(new Handler.Callback() {
            @Override
            public boolean handleMessage(Message msg) {
                // 具体任务逻辑
                if(SystemUtils.isAPPALive(getApplicationContext(), Contants.PACKAGE_NAME)){
                    Toast.makeText(getApplicationContext(), "APP活着的", Toast.LENGTH_SHORT)
                            .show();
                }else{
                    Intent intent = new Intent(getApplicationContext(), SportsActivity.class);
                    intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
                    startActivity(intent);
                    Toast.makeText(getApplicationContext(), "APP被杀死,重启...", Toast.LENGTH_SHORT)
                            .show();
                }
                // 通知系统任务执行结束
                jobFinished( (JobParameters) msg.obj, false );
                return true;
            }
        });
    
        @Override
        public boolean onStartJob(JobParameters params) {
            if(Contants.DEBUG)
                Log.d(TAG,"KeepAliveService----->JobService服务被启动...");
            mKeepAliveService = this;
            // 返回false,系统假设这个方法返回时任务已经执行完毕;
            // 返回true,系统假定这个任务正要被执行
            Message msg = Message.obtain(mHandler, MESSAGE_ID_TASK, params);
            mHandler.sendMessage(msg);
            return true;
        }
    
    
        @Override
        public boolean onStopJob(JobParameters params) {
            mHandler.removeMessages(MESSAGE_ID_TASK);
            if(Contants.DEBUG)
                Log.d(TAG,"KeepAliveService----->JobService服务被关闭");
            return false;
        }
    }
    
    

    (2) JobSchedulerManager.java

    /**JobScheduler管理类,单例模式
     * 执行系统任务
     *
     * Created by jianddongguo on 2017/7/10.
     * http://blog.csdn.net/andrexpert
     */
    public class JobSchedulerManager {
        private static final int JOB_ID = 1;
        private static JobSchedulerManager mJobManager;
        private JobScheduler mJobScheduler;
        private static Context mContext;
    
        private JobSchedulerManager(Context ctxt){
            this.mContext = ctxt;
            mJobScheduler = (JobScheduler)ctxt.getSystemService(Context.JOB_SCHEDULER_SERVICE);
        }
        public final static JobSchedulerManager getJobSchedulerInstance(Context ctxt){
            if(mJobManager == null){
                mJobManager = new JobSchedulerManager(ctxt);
            }
            return mJobManager;
        }
        @TargetApi(21)
        public void startJobScheduler(){
            // 如果JobService已经启动或API<21,返回
            if(AliveJobService.isJobServiceAlive() || isBelowLOLLIPOP()){
                return;
            }
            // 构建JobInfo对象,传递给JobSchedulerService
            JobInfo.Builder builder = new JobInfo.Builder(JOB_ID,new ComponentName(mContext, AliveJobService.class));
            // 设置每3秒执行一下任务
            builder.setPeriodic(3000);
            // 设置设备重启时,执行该任务
            builder.setPersisted(true);
            // 当插入充电器,执行该任务
            builder.setRequiresCharging(true);
            JobInfo info = builder.build();
            //开始定时执行该系统任务
            mJobScheduler.schedule(info);
        }
        @TargetApi(21)
        public void stopJobScheduler(){
            if(isBelowLOLLIPOP())
                return;
            mJobScheduler.cancelAll();
        }
        private boolean isBelowLOLLIPOP(){
            // API< 21
            return Build.VERSION.SDK_INT < Build.VERSION_CODES.LOLLIPOP;
        }
    }

    (3) AndroidManifest.xml
    <--! AliveJobService需要BIND_JOB_SERVICE权限-->
     <service
             android:name=".service.AliveJobService"
              android:permission="android.permission.BIND_JOB_SERVICE"/>
    Doze模式讲解:
         Doze,即休眠、打盹之意,是谷歌在Android M(6.0)提出为了延长电池使用寿命的一种节能方式,它的核心思想是在手机处于屏幕熄灭、不插电或静止不动一段时间后,手机会自动进入Doze模式,处于Doze模式的手机将停止所有非系统应用的WalkLocks、网络访问、闹钟、GPS/WIFI扫描、JobSheduler活动。当进入Doze模式的手机屏幕被点亮、移动或充电时,会立即从Doze模式恢复到正常,系统继续执行被Doze模式"冷冻"的各项活着。换而言之,Doze模式不会杀死进程,只是停止了进程相关的耗电活动,使其进入"休眠"状态。至Android N(7.0)后,谷歌进一步对Doze休眠机制进行了优化,休眠机制的应用场景和使用规则进行了扩展。Doze在Android 6.0中需要将手机平行放置一段时间才能开启,在7.0中则可随时开启。
          因此,对于Android 5.0,JobSheduler的唤醒是非常有效的;对于Android 6.0,虽然谷歌引入了Doze模式,但通常很难真正进入Doze模式,所以JobSheduler的唤醒依然有效;对于Android 7.0,JobSheduler的唤醒会有一定的影响,我们可以在电池管理中给APP开绿色通道,防止手机Doze模式后阻止APP使用JobSheduler功能。注:如果遇到深度定制机型,这就要看运气了...
    (4) 测试结果
         三星C9(6.0):一键清理和强制停止(force stop)都能够唤醒APP;
         三星Note4(5.0):一键清理和强制停止(force stop)都能够唤醒APP;
        华为荣耀4X(6.0):一键清理和强制停止(force stop)都能够唤醒APP;
        华为Mate8(7.0):失效(可能被华为屏蔽了);

        

    2. 华为推送SDK
          与个推、小米、极光推送类似,华为Push也是为开发者提供的一个消息推送平台,它建立了从云端到手机端的消息推送通道,支持上报标签、LBS信息、通知推送。换句话来说,就算我们的APP没有自己的服务器,也可以通过这些第三方推送平台,把最新消息及时地通知用户。
    华为推送保活原理:华为推送服务以后台Service方式运行在一个独立进程里,主程序不需要常驻内存。当该后台Service接收到push消息后会以广播的方式通知主进程,触发相关回调接口。通常,被强制停止的APP无法接收到广播,但是华为push通道(即推送后台Service,它会常驻内存)能够强行将APP拉起来,这是因为其在发广播时利用了Intent.FLAG_INCLUDE_STOPPED_PACKAGES标记实现的。
    (1) MyHwPushReceiver.java

    /** 华为接收器子类,用于接收推送消息
     *
     * Created by jianddongguo on 2017/7/10.
     * http://blog.csdn.net/andrexpert
     *
     */
    
    
    public class MyHwPushReceiver extends PushEventReceiver{
        private final static String TAG = "MyHwPushReceiver";
    
    
        /**
         * pushToken申请成功后,会自动回调该方法
         * 应用通过该方法获取token(必须实现)
         * */
        @Override
        public void onToken(Context context, String token, Bundle bundle) {
            Log.i(TAG,"连接到华为推送服务器,token="+token);
        }
    
    
        /**
         *  推送消息下来时会自动回调onPushMsg方法
         *  用于接收透传消息(必须实现)
         * */
        @Override
        public boolean onPushMsg(Context context, byte[] msgBytes, Bundle bundle) {
            if(Contants.DEBUG){
                try {
                    Log.i(TAG,"接收透传消息:"+new String(msgBytes,"UTF-8"));
                } catch (UnsupportedEncodingException e) {
                    e.printStackTrace();
                }
            }
            // 启动应用
    
    
            return false;
        }
    
    
        /**
         * 连接状态的回调方法
         * */
        @Override
        public void onPushState(Context context, boolean connectState) {
            Log.i(TAG,"是否连接到华为推送服务器:"+(connectState?"connected":"disconnected"));
        }
    
    
        /**
         * 该方法会在设置标签、LBS信息之后,点击打开通知栏消息
         * 点击通知栏上的按钮之后被调用,由业务决定是否调用该函数。
         * Event类型:
         * NOTIFICATION_OPEMED,通知栏中的通知被点击打开
         * NOTIFICATION_CLICK_BTN,通知栏中通知上的按钮被点击
         * PLUGINRSP,标签上报回应
         * */
        @Override
        public void onEvent(Context context, Event event, Bundle bundle) {
            super.onEvent(context, event, bundle);
        }
    }
    讲解一下:
        MyHwPushReceiver是华为接收器(com.huawei.android.pushagent.api.PushEventReceive)的子类,用于接收服务器传递过来的token,获取服务器连接状态,接收服务器推送过来的通知、透传等消息。需要注意的是,onToken方法、onPushMsg方法必须要实现,并且尽量不要在MyHwPushReceiver类中开启线程、处理Handler等。
    (2) HwPushManager.java
    /**华为推送控制类
     *
     * Created by jianddongguo on 2017/7/15.
     * http://blog.csdn.net/andrexpert
     */
    
    
    public class HwPushManager {
        private static HwPushManager mPushManager;
        private Context mContext;
    
    
        private HwPushManager(Context mContext){
            this.mContext = mContext;
        }
    
    
        public static  HwPushManager getInstance(Context mContext){
            if(mPushManager == null){
                mPushManager = new HwPushManager(mContext);
            }
            return mPushManager;
        }
    
    
        /**向服务器请求Token
         * 前提是已经在华为开发者联盟注册本应用,并申请、审核通过Push权益
         * */
        public void startRequestToken(){
            PushManager.requestToken(mContext);
        }
    
    
        /**
         * 是否接收服务器传递过来的透传消息
         * */
        public void isEnableReceiveNormalMsg(boolean isEnable){
            PushManager.enableReceiveNormalMsg(mContext,isEnable);
        }
    
    
        /**
         * 是否接收自呈现消息
         * */
        public  void isEnableReceiverNotifyMsg(boolean isEnable){
            PushManager.enableReceiveNotifyMsg(mContext,isEnable);
        }
    
    
    }
    讲解一下:
    a. 透传消息,即对于信息传输通道来说不会去关心透传消息的消息体格式及内容,它只是负责消息的传递,不对消息做任何处理,当客户端接收到透传消息后,由客户端自己来决定如何处理消息,比如默默在后台处理消息、以通知的方式向用户展示消息等,因此它弥补了通知栏消息客户端无法捕获到相关动作的不足。
    b. 通知栏消息,即被推送的通知发送后会在客户端系统通知栏收到展现,同时响铃或振动提醒用户,但客户端无法捕捉到通知栏消息的相关动作,来做进一步的处理。
    c. 富媒体消息,即随着信息技术的升级发展,在互联网上传播的信息,不仅只有文字或图片,同时还可以包括动画、视频、互动、音乐或语音效果等。
    (3) AndroidManifest.xml
      <!-- 必需的权限 -->
        <uses-permission android:name="android.permission.INTERNET" />
        <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
        <uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
        <uses-permission android:name="android.permission.READ_PHONE_STATE" />
        <uses-permission android:name="android.permission.WAKE_LOCK" />
      <!-- 第三方相关 :接收Push消息(注册、Push消息、Push连接状态、标签,LBS上报结果)广播 -->
            <receiver android:name=".receiver.MyHwPushReceiver" >
                <intent-filter>
                    <!-- 必须,用于接收token-->
                    <action android:name="com.huawei.android.push.intent.REGISTRATION" />
                    <!-- 必须,用于接收消息-->
                    <action android:name="com.huawei.android.push.intent.RECEIVE" />
                    <!-- 可选,用于点击通知栏或通知栏上的按钮后触发onEvent回调-->
                    <action android:name="com.huawei.android.push.intent.CLICK" />
                    <!-- 可选,查看push通道是否连接,不查看则不需要-->
                    <action android:name="com.huawei.intent.action.PUSH_STATE" />
                    <!-- 可选,标签、地理位置上报回应,不上报则不需要 -->
                    <action android:name="com.huawei.android.push.plugin.RESPONSE" />
                </intent-filter>
                <meta-data android:name="CS_cloud_ablitity" android:value="@string/hwpush_ability_value"/>
            </receiver>
    
    
            <!-- 备注:Push相关的android组件需要添加到业务的AndroidManifest.xml,
            	 Push相关android组件运行在另外一个进程是为了防止Push服务异常而影响主业务 -->
            <!-- PushSDK:PushSDK接收外部请求事件入口 -->
            <receiver
                android:name="com.huawei.android.pushagent.PushEventReceiver"
                android:process=":pushservice" >
                <intent-filter>
                 <action android:name="com.huawei.android.push.intent.REFRESH_PUSH_CHANNEL" />
                    <action android:name="com.huawei.intent.action.PUSH" />
                    <action android:name="com.huawei.intent.action.PUSH_ON" />
                    <action android:name="com.huawei.android.push.PLUGIN" />
                </intent-filter>
                <intent-filter>
                    <action android:name="android.intent.action.PACKAGE_ADDED" />
                    <action android:name="android.intent.action.PACKAGE_REMOVED" />
    
    
                    <data android:scheme="package" />
                </intent-filter>
            </receiver>
            <receiver
                android:name="com.huawei.android.pushagent.PushBootReceiver"
                android:process=":pushservice" >
                <intent-filter>
                    <action android:name="com.huawei.android.push.intent.REGISTER" />
                    <action android:name="android.net.conn.CONNECTIVITY_CHANGE" />
                </intent-filter>
                <meta-data
                    android:name="CS_cloud_version"
                    android:value="\u0032\u0037\u0030\u0035" />
            </receiver>
    
    
            <!-- PushSDK:Push服务 -->
            <service
                android:name="com.huawei.android.pushagent.PushService"
                android:process=":pushservice" >
            </service>
    
    
            <!-- PushSDK:富媒体呈现页面,用于呈现服务器下发的富媒体消息 -->
            <!-- locale|layoutDirection 切换语言后不重新创建activity -->
            <activity
                android:name="com.huawei.android.pushselfshow.richpush.RichPushActivity"
                android:process=":pushservice"
                android:theme="@style/hwpush_NoActionBar"
                android:configChanges="orientation|screenSize|locale|layoutDirection"
                android:screenOrientation="portrait">
                <meta-data android:name="hwc-theme"
                    android:value="androidhwext:style/Theme.Emui"/>
                <intent-filter>
                    <action android:name="com.huawei.android.push.intent.RICHPUSH" />
    
    
                    <category android:name="android.intent.category.DEFAULT" />
                </intent-filter>
            </activity>
            <activity
               android:name="com.huawei.android.pushselfshow.permission.RequestPermissionsActivity"
                android:theme="@android:style/Theme.DeviceDefault.Light.Dialog.NoActionBar"
                android:launchMode="singleTop"
                android:screenOrientation="portrait"
                android:configChanges="orientation|screenSize|locale|layoutDirection"
                android:exported="false">
            </activity>
    讲解一下:
         这里除了MyHwPushReceiver类,其他直接从华为推送官方Demo拷贝即可。在测试过程中,需要连接到网络,然后我这里是通过华为开发者联盟网页中给KeepAppAlive发送透传消息的,用来测试华为推送保活的可行性。一般来说,我们都是在自己的服务器开一个定时器,定时推送透传消息到客户端。注:部分华为手机可能还需要开启自启动权限;如何集成华为推送SDK,直接看官方文档即可;非华为手机需要安装"华为手机服务.apk"才能使用华为推送,这个有点坑。
    (4) 接收日志

    (5) 效果演示

    3. 第三方应用互相唤醒
          “探讨一种新型的双进程守护应用保活方法”就是利用第三方应用相互唤醒实现的,只是唤醒的方式比较 "坦率"。不会像腾讯、阿里全家桶那样 "委婉":当你启动其中的一个APP,该APP可能就会通过广播的方式偷偷唤醒它们这一个派系的其他APP,可谓是神不知鬼不觉。


    Github项目地址:https://github.com/jiangdongguo/KeepingAppAlive


    参考资料:
    (1) Android之JobScheduler运行机制源码分析
    (2) 安卓推送技术手册——使用透传消息的正确姿势
    (3) 华为推送服务官网
    (4) 流媒体、富媒体、多媒体到底有什么区别?
    (5) 史上最全解析Android消息推送解决方案
    (6) 华为推送接口文档
    (7) Android集成华为推送的问题总结
    (8) android接入华为推送注意点

    展开全文
  • 软件简介同行业最小体积、最快速度、最全数据、目前唯一一款非常驻内存的来电归属地显示软件。包含中国移动、联通、电信所有共25个号段以及全国所有固话区号信息。总数据量超过25万组,采用优秀的数据库结构顶尖的...

    软件简介
    同行业最小体积、最快速度、最全数据、目前唯一一款非常驻内存的来电归属地显示软件。包含中国移
    动、联通、电信所有共25个号段以及全国所有固话区号信息。

    总数据量超过25万组,采用优秀的数据库结构顶尖的压缩技术使得体积只有同行业软件体积的一半。采用系统级服务技术,保证不会偷偷的在后台运行(这点非常重要,目前所有的来电通软件都是在后台运行,殊不知后台运行也是占用内存资源、占用CPU资源,您的电源就这样一点点的被耗费完了,这也是装的软件越多待机时间越来越短的主要原因),更重要的是能够为您的爱机节省宝贵的电源

    转载于:https://www.cnblogs.com/private250/archive/2010/08/09/1795808.html

    展开全文
  • 我们知道,在Android4.4之后的版本中,Android在硬件中支持内置计步传感器,例如微信运动等软件都是调用了Android中的Sensor.TYPE_STEP_COUNTER传感器服务,从而获取到每日的步数。 由于当时用户手机版本普遍偏低,...

    前言

    遥想当年,博主铭记在心的一件事,就是曾做过让我加快秃顶的功能——健步活动。我们知道,在Android4.4之后的版本中,Android在硬件中支持内置计步传感器,例如微信运动等软件都是调用了Android中的Sensor.TYPE_STEP_COUNTER传感器服务,从而获取到每日的步数。

    由于当时用户手机版本普遍偏低,因此需要手写记步。当时好在机智如我,参考了微信摇一摇的原理,通过加速度传感器SENSOR_TYPE_LINEAR_ACCELERATION获取到在某个时间段的加速度值,最后通过一顿计算公式得出步数。但是不同机型的加速度值并不相同,而且超级耗电。而最难的问题,就是应用特别容易被杀死,因为内存和电量耗损大,当应用在后台运行会优先被系统回收,而且用户手动一键清理时杀死进程,导致无法记步。

     

    一、常见的应用保活方法 

    1、  监听广播方式

    通过监听全局的静态广播,如开机广播、解锁屏广播、网络状态广播等,来启动应用的后台服务。目前,在高版本的Android系统中已经失效,因为Android系统规定应用必须在系统开机后运行一次才能监听这些系统广播,一般应用进程被杀死,广播也接收不到。

    2、 提高Service的优先级

    提高Service优先级方法很多,比如onStartCommand返回START_STICKY使系统内存足够的时候Service能够自动启动、弹出通知、配置service的优先级等,这些方式只能在一定程度上缓解service被立马回收,但只要用户一键清理或者系统回收照样无效。

    3、 双service拉起

      经过测试,只要当前应用被杀,任何后台service都无法运行,也无法拉起。

    4、双进程拉起

    这种方式使用NDK在底层fork出一个子进程,来实现与父进程之间的互拉。在Android4.x还是非常有效的,但是高版本的Android系统的系统回收策略已经改成进程组的形式了,如果系统要回收一个应用,必然会杀死同属于一个进程组的所有进程导致双进程无法拉起。 

     5、Wake_Lock

    系统为了节省电量,CPU在没有任务忙的时候就会自动进入休眠,有任务需要唤醒CPU高效执行的时候,就会给CPU加Wake_Lock锁。

    Wake Lock是Android框架层提供的一套锁的机制,应用使用该机制可以达到控制系统无法进入休眠,cpu的保持运行。意思就是我的程序给CPU加了这个锁那系统就不会休眠了,这样做的目的是为了全力配合我们程序的运行。

    当手机灭屏状态下保持一段时间后,系统会进入休眠,一些后台运行的任务就可能得不到正常执行,比如网络下载中断,后台播放音乐暂停,再比如微信等及时通讯的心跳包会在熄屏不久后停止网络访问等问题。WakeLock正是为了解决这类问题,应用只要申请了WakeLock,那么在释放WakeLock之前,系统不会进入休眠,即使在灭屏的状态下,应用要执行的任务依旧不会被系统打断。所以微信里面是有大量使用到了Wake_Lock锁。

    但是用wake唤醒CPU持续来工作是会造成耗电的,记得在合适的业务情况下释放Wake_Lock。

    二、多进程音频保活方案

    综上所述,上面的方法只是提高了APP后台运行存留能力,在用户不主动清理或强杀的情况下,测试APP的保活效果还是非常不错的。但是,"咕咚"在点击一键清理时奇妙的活了下来,原因是在后台循环播放一段无声音乐。如下图:

    代码如下:

    public class PlayerMusicService extends Service {
        private final static String TAG = "PlayerMusicService";
        private MediaPlayer mMediaPlayer;
        @Nullable
        @Override
        public IBinder onBind(Intent intent) {
            return null;
        }
        @Override
        public void onCreate() {
            super.onCreate();
            mMediaPlayer = MediaPlayer.create(getApplicationContext(), R.raw.silent);
            mMediaPlayer.setLooping(true);
        }
        @Override
        public int onStartCommand(Intent intent, int flags, int startId) {
            new Thread(new Runnable() {
                @Override
                public void run() {
                    startPlayMusic();
                }
            }).start();
            return START_STICKY;//注释1
        }
        private void startPlayMusic(){
            if(mMediaPlayer != null){
                mMediaPlayer.start();
            }
        }
        private void stopPlayMusic(){
            if(mMediaPlayer != null){
                mMediaPlayer.stop();
            }
        }
        @Override
        public void onDestroy() {
            super.onDestroy();
            stopPlayMusic();
            // 注释2
            Intent intent = new Intent(getApplicationContext(),PlayerMusicService.class);
            startService(intent);
        }
    }
    

    AndroidManifest.xml

    <service android:name=".service.PlayerMusicService"
              android:enabled="true"
              android:exported="true"
              android:process=":music_service"/>//多进程
    

    注释1:在onStartCommand方法中返回START_STICKY,其作用是当Service进程被kill后,系统会尝试重新创建这个Service。

    注释2:在onDestory方法中重新启动自己,即Service被销毁时调用onDestory,就执行重新启动代码。

    开启后台播放音频服务,此方案在各机型测试情况如下:
    1、 华为Mate8(7.0) ,一键清理依然存活,在置于后台的黑屏模式下存活12小时以上;但是如果用户只选择清理此应用也会被杀死,这与"咕咚"保活效果一致。
    2、三星C9(6.0),一键清理最近应用,成功保活;
    3、华为4X(6.0):一键清理最近应用,成功保活;
    4、三星Note4(5.0):一键清理最近应用,成功保活;

     

    三、通过JobScheduler方案

    概述

    JobScheduler是谷歌在Android 5.0引入的一个能够执行特定任务的API,当条件满足时执行指定的任务。通常情况下,即使APP被强制停止,预定的任务仍然会被执行。

    原理

         在重写父类JobService的onStartJob的方法中执行任务,使用JobInfo的Builder方法来设定条件并和实现了JobService的子类的组件名绑定,然后调用系统服务JobScheduler的schedule方法。这样,即便在执行任务之前应用程序进程被杀,也不会导致任务不会执行,因为系统服务JobScheduler会使用bindServiceAsUser的方法把实现了JobService的子类服务启动起来,并执行它的onStartJob方法

    新建类:AliveJobService.java

    @TargetApi(21)
    public class AliveJobService extends JobService {
        private static final int MESSAGE_ID_TASK = 0x01;
        // 告知编译器,这个变量不能被优化
        private volatile static Service mKeepAliveService = null;
        public static boolean isJobServiceAlive(){
            return mKeepAliveService != null;
        }
        private Handler mHandler = new Handler(new Handler.Callback() {
            @Override
            public boolean handleMessage(Message msg) {
                if(SystemUtils.isAPPALive(getApplicationContext(), Contants.PACKAGE_NAME)){
                    //APP活着的
                }else{
                    Intent intent = new Intent(getApplicationContext(), SportsActivity.class);
                    intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
                    startActivity(intent);
                    //APP被杀死后重启
                }
                jobFinished( (JobParameters) msg.obj, false ); // 通知系统任务执行结束
                return true;
            }
        });
        @Override
        public boolean onStartJob(JobParameters params) {
            mKeepAliveService = this;
            Message msg = Message.obtain(mHandler, MESSAGE_ID_TASK, params);
            mHandler.sendMessage(msg);
            // 返回false,系统假设这个方法返回时任务已经执行完毕;
            // 返回true,系统假定这个任务正要被执行
            return true;
        }
        @Override
        public boolean onStopJob(JobParameters params) {
            mHandler.removeMessages(MESSAGE_ID_TASK);
            return false;
        }
    }
     

    JobScheduler管理类执行系统任务:JobSchedulerManager.java

    public class JobSchedulerManager {
        private static final int JOB_ID = 1;
        private static JobSchedulerManager mJobManager;
        private JobScheduler mJobScheduler;
        private static Context mContext;
     
        private JobSchedulerManager(Context ctxt){
            this.mContext = ctxt;
            mJobScheduler = (JobScheduler)ctxt.getSystemService(Context.JOB_SCHEDULER_SERVICE);
        }
        public final static JobSchedulerManager getJobSchedulerInstance(Context ctxt){
            if(mJobManager == null){
                mJobManager = new JobSchedulerManager(ctxt);
            }
            return mJobManager;
        }
        @TargetApi(21)
        public void startJobScheduler(){
            if(AliveJobService.isJobServiceAlive() || isBelowLOLLIPOP()){
                return;        // 如果JobService已经启动或API<21,返回
            }
            JobInfo.Builder builder = new JobInfo.Builder(JOB_ID,new ComponentName(mContext, AliveJobService.class));
            builder.setPeriodic(3000); // 设置每3秒执行一下任务
            builder.setPersisted(true);  // 设置设备重启时,执行该任务
            builder.setRequiresCharging(true); // 当插入充电器,执行该任务
            JobInfo info = builder.build();
            mJobScheduler.schedule(info);  
        }
        @TargetApi(21)
        public void stopJobScheduler(){
            if(isBelowLOLLIPOP())
                return;
            mJobScheduler.cancelAll();
        }
        private boolean isBelowLOLLIPOP(){
            return Build.VERSION.SDK_INT < Build.VERSION_CODES.LOLLIPOP; // API< 21
        }
    }

    记得添加权限: android:permission="android.permission.BIND_JOB_SERVICE"

    Doze休眠模式

    谷歌在Android M(6.0)提出为了延长电池使用寿命的一种节能方式,它的核心思想是在手机处于屏幕熄灭、不插电或静止不动一段时间后,手机会自动进入Doze模式,处于Doze模式的手机将停止所有非系统应用的WalkLocks、网络访问、闹钟、GPS/WIFI扫描,包括JobSheduler活动

    当进入Doze模式的手机屏幕被点亮、移动或充电时,会立即从Doze模式恢复到正常,系统继续执行被Doze模式"冷冻"的各项活着。换而言之,Doze模式不会杀死进程,只是停止了进程相关的耗电活动,使其进入"休眠"状态。至Android N(7.0)后,谷歌进一步对Doze休眠机制进行了优化,休眠机制的应用场景和使用规则进行了加强。Doze在Android 6.0中需要将手机平行放置一段时间才能开启,在7.0中则可随时开启。

    因此,对于Android 5.0,JobSheduler的唤醒是非常有效的;对于Android 6.0,虽然谷歌引入了Doze模式,但通常很难真正进入Doze模式,所以JobSheduler的唤醒依然有效;对于Android 7.0,JobSheduler的唤醒会有一定的影响,我们可以在电池管理中给APP开绿色通道,防止手机Doze模式后阻止APP使用JobSheduler功能。

    测试结果
        三星C9(6.0):一键清理和强制停止(force stop)都能够唤醒APP;
        三星Note4(5.0):一键清理和强制停止(force stop)都能够唤醒APP;
        华为荣耀4X(6.0):一键清理和强制停止(force stop)都能够唤醒APP;
        华为Mate8(7.0):失效(可能被华为屏蔽了);


    四、华为推送SDK

    Android市场推送,包括个推、小米、极光华为Push、360、魅族等。华为推送服务让一个后台运行的Service在一个独立进程里,主程序不需要常驻内存。当该后台Service接收到push消息后会以广播的方式通知主进程,触发相关回调接口。通常,被强制停止的APP无法接收到广播,但是华为push的后台Service,可以强行将APP拉起来,这是因为其在发广播时利用了Intent.FLAG_INCLUDE_STOPPED_PACKAGES标记实现的。

    MyHwPushReceiver.java

    该类继承了华为接收器(com.huawei.android.pushagent.api.PushEventReceive),用于接收服务器传递过来的token,获取服务器连接状态,接收服务器推送过来的通知、透传等消息。需要注意的是,onToken方法、onPushMsg方法必须要实现,并且尽量不要在MyHwPushReceiver类中开启线程、处理Handler等。

    public class MyHwPushReceiver extends PushEventReceiver{
        private final static String TAG = "MyHwPushReceiver";
        @Override
        public void onToken(Context context, String token, Bundle bundle) {
            Log.i(TAG,"连接到华为推送服务器,token="+token);
        }
        @Override
        public boolean onPushMsg(Context context, byte[] msgBytes, Bundle bundle) {
            Log.i(TAG,"接收透传消息:"+new String(msgBytes,"UTF-8"));
            // 启动应用
            return false;
        }
        @Override
        public void onPushState(Context context, boolean connectState) {
            Log.i(TAG,"是否连接到华为推送服务器:"+(connectState?"connected":"disconnected"));
        }
    
        @Override
        public void onEvent(Context context, Event event, Bundle bundle) { 
            //点击打开通知栏
            super.onEvent(context, event, bundle);
        }
    }
    

    HwPushManager.java

     public class HwPushManager {
        private static HwPushManager mPushManager;
        private Context mContext; 
        private HwPushManager(Context mContext){
            this.mContext = mContext;
        }
        public static  HwPushManager getInstance(Context mContext){
            if(mPushManager == null){
                mPushManager = new HwPushManager(mContext);
            }
            return mPushManager;
        }
        public void startRequestToken(){
            //向服务器请求Token
            PushManager.requestToken(mContext);
        }
            //是否接收服务器传递过来的透传消息
        public void isEnableReceiveNormalMsg(boolean isEnable){
            PushManager.enableReceiveNormalMsg(mContext,isEnable);
        }
            //是否接收自呈现消息
        public  void isEnableReceiverNotifyMsg(boolean isEnable){
            PushManager.enableReceiveNotifyMsg(mContext,isEnable);
        }
    }

    穿透消息,即对于信息传输通道来说不会去关心透传消息的消息体格式及内容,它只是负责消息的传递,不对消息做任何处理,当客户端接收到透传消息后,由客户端自己来决定如何处理消息,比如默默在后台处理消息、以通知的方式向用户展示消息等,因此它弥补了通知栏消息客户端无法捕获到相关动作的不足。

     AndroidManifest.xml

    除了自定义的MyHwPushReceiver类,其他直接从华为推送官方Demo拷贝即可。通过华为开发者联盟网页中给KeepAppAlive发送透传消息的,测试华为推送保活的可行性。一般来说,我们都是在自己的服务器开一个定时器,定时推送透传消息到客户端。

    注:部分华为手机可能还需要开启自启动权限;如何集成华为推送SDK,直接看官方文档即可;非华为手机需要安装"华为手机服务.apk"才能使用华为推送(有点坑)。

        <uses-permission android:name="android.permission.INTERNET" />
        <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
        <uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
        <uses-permission android:name="android.permission.READ_PHONE_STATE" />
        <uses-permission android:name="android.permission.WAKE_LOCK" />
      <!-- 第三方相关 :接收Push消息(注册、Push消息、Push连接状态、标签,LBS上报结果)广播 -->
            <receiver android:name=".receiver.MyHwPushReceiver" >
                <intent-filter>
                    <action android:name="com.huawei.android.push.intent.REGISTRATION" />
                    <action android:name="com.huawei.android.push.intent.RECEIVE" />
                    <action android:name="com.huawei.android.push.intent.CLICK" />
                    <action android:name="com.huawei.intent.action.PUSH_STATE" />
                    <action android:name="com.huawei.android.push.plugin.RESPONSE" />
                </intent-filter>
                <meta-data android:name="CS_cloud_ablitity" android:value="@string/hwpush_ability_value"/>
            </receiver>
            <!-- PushSDK:PushSDK接收外部请求事件入口 -->
            <receiver
                android:name="com.huawei.android.pushagent.PushEventReceiver"
                android:process=":pushservice" >
                <intent-filter>
                 <action android:name="com.huawei.android.push.intent.REFRESH_PUSH_CHANNEL" />
                    <action android:name="com.huawei.intent.action.PUSH" />
                    <action android:name="com.huawei.intent.action.PUSH_ON" />
                    <action android:name="com.huawei.android.push.PLUGIN" />
                </intent-filter>
                <intent-filter>
                    <action android:name="android.intent.action.PACKAGE_ADDED" />
                    <action android:name="android.intent.action.PACKAGE_REMOVED" />
                    <data android:scheme="package" />
                </intent-filter>
            </receiver>
            <receiver
                android:name="com.huawei.android.pushagent.PushBootReceiver"
                android:process=":pushservice" >
                <intent-filter>
                    <action android:name="com.huawei.android.push.intent.REGISTER" />
                    <action android:name="android.net.conn.CONNECTIVITY_CHANGE" />
                </intent-filter>
                <meta-data
                    android:name="CS_cloud_version"
                    android:value="\u0032\u0037\u0030\u0035" />
            </receiver>
            <!-- PushSDK:Push服务 -->
            <service
                android:name="com.huawei.android.pushagent.PushService"
                android:process=":pushservice" >
            </service>
            <!-- locale|layoutDirection 切换语言后不重新创建activity -->
            <activity
                android:name="com.huawei.android.pushselfshow.richpush.RichPushActivity"
                android:process=":pushservice"
                android:theme="@style/hwpush_NoActionBar"
                android:configChanges="orientation|screenSize|locale|layoutDirection"
                android:screenOrientation="portrait">
                <meta-data android:name="hwc-theme"
                    android:value="androidhwext:style/Theme.Emui"/>
                <intent-filter>
                    <action android:name="com.huawei.android.push.intent.RICHPUSH" />
                    <category android:name="android.intent.category.DEFAULT" />
                </intent-filter>
            </activity>
            <activity
           android:name="com.huawei.android.pushselfshow.permission.RequestPermissionsActivity"
                android:theme="@android:style/Theme.DeviceDefault.Light.Dialog.NoActionBar"
                android:launchMode="singleTop"
                android:screenOrientation="portrait"
                android:configChanges="orientation|screenSize|locale|layoutDirection"
                android:exported="false">
            </activity>
    

    测试结果

     


    参考链接:

    https://blog.csdn.net/andrexpert/article/details/75174586

    https://blog.csdn.net/andrexpert/article/details/75045678


    推荐阅读:

    原创 Android性能优化(一)闪退治理、卡顿优化、耗电优化、APK瘦身

    展开全文
  • )默认如图,它将每根内存的最低位64Mb设置为排除,是因为有些驱动程序和常驻系统的软件会占用这部分内存,为了避免引起冲突采取的措施。如果大家有兴趣的话,还可以把虚拟盘设置到任意一根内存条上,比如第一或是...
  • 近期被一些朋友问到关于进程保活这块的知识点,想必是很多开发者研究的重点,虽然我不支持做成这类【流氓软件】,因为大家都这么干的话,Android系统的内存永远不够用,电量消耗的贼快,流畅度肯定就大大的降低了;...
  • Android 常驻进程保活自启动方案总结

    千次阅读 2017-06-01 22:36:29
    Android常驻进程就是进程一直存在,即使被系统外者其他软件人为杀死也能够自启,这种需求一般就是用来常驻接受推送消息时,如何保证进程不被杀死,实时收到推送的消息,与后台保持着链接。那如何保持进程常驻呢,...
  • Android_常驻进程(杀不死的进程)

    万次阅读 2016-08-05 14:38:23
    Android常驻进程,就是要让进程在内存中永远存在,让进程保活,不被杀死。可能这时都会喷,这不是流氓软件吗?刚接触android的时候,我也是认为这是很流氓的做法,可是慢慢发现很多场景(应用),要为用户服务,就...
  • 内存概念、术语

    2019-11-27 11:36:11
    常驻内存 当前处于主存中的内存。 虚拟内存 一个抽象的主存概念,它几乎是无限的和非竞争性的。虚拟内存不是真实的内存。他向每个进程和内核提供巨大的、线性的而且私有的地址空间。它简化了软件开发,把物理内存的...
  • 在大型的软件开发项目中,常会遇到较大的常驻内存内存泄露、内存破坏等问题,这些问题往往都是致命的。于是我们就借助于一些内存检测工具、API或者是某种技术手段,来动态地跟踪内存分配,查看内存使用细节,方法...
  • 异常、用户或安全管理软件清理、系统。 要让进程或服务常驻,异常不考虑。 剩下就是两种情况,防止被系统杀死,防止被清理。 一、背景 (1) service是进程内的组件,所以推测其生命周期应该收进程影响吧。 (2...
  • 可以创建指定容量的虚拟内存盘,分区格式可选择为NTFS或者FAT32,也可以从已有的磁盘镜像文件创建内存盘,支持开机自动加载指定盘符的内存盘,关机时保存内存盘数据(此功能需要常驻系统)。内存盘的大小是有限制的,...
  • 软件介绍: 魔方内存盘能够将系统多余的内存划分为一个虚拟磁盘,众所周之内存的读写速度远远高于硬盘,所以将临时文件或者IE缓存文件放到虚拟的内存盘中,...支持开机自动加载及关机时保存内存盘数据(需要常驻系统)
  • 除了内存占用小,界面简洁美观之外,最重要的是该软件常驻通知栏,一来腾出一个软件图标的宝贵位置,二来需要开启闪光灯时能够快速的从通知栏里找到,节省了宝贵时间。欢迎试用并给出宝贵意见,后续版本正在紧张...
  • 6:感染电脑的病毒程序常驻内存中,导致CMOS参数中关于内存的相关参数值被修改,导致内存值与内存条实际内存大小不符,这将会导致电脑在使用时出现速度变慢或是系统死机等现象。 7:电脑进行内存扩充选择了与主板...
  • 2,此软件和Windows的底层挂接,运行后将会常驻内存(占用70K左右),只有重新启动一下操作系统才能退出或删除。 3,就算退出了程序(或结束进程MemorySaviour.exe),核心部分仍然驻留,所以优化效果依然有效。 4,...
  • 今天在看工程源码的时候看到了SoftReference这个类。 用来缓存我们软件的一些图片...首相SoftReference的用处是增强一个引用常驻内存的能力。也就是说一个引用比如A a=new A(); 此时如果你把a=null;那么在不久之
  • 原标题:再次确认苹果的1G运存相当于安卓的4G运行内存苹果手机和安卓手机之间的系统架构和运行机制是有所区别的,运行内存速度快,但是容量比较有限,是用来存储系统和常驻软件的临时存储器,可以大大加速手机存储...
  • 关键词:软件优化,软件加速,...我们可以把软件分成前台和后台部分(服务或者deamon程序),在软件启动前,后台部分已经常驻内存,这样软件启动时,加载的代码和数据可以明显减少,软件启动的速度就提高了。 So动态库
  • 利用Empty.exe降低AutoHotkey占用的内存

    千次阅读 2010-10-18 21:54:00
    但是如果你的AutoHotkey(或编译后的.exe程序)常驻内存,大部分时间只是在后台等待热键或者等待其它任务,还是有办法减少它的内存占用的。我试用了Empty.exe这个小工具,效果很好。 Empty.exe是一个来自于微软的...
  • Mac 下禁用开机自启软件

    千次阅读 2018-09-13 15:53:49
    有部分软件的开机启动项放在 /...深信服的 EasyConnect 有一个进程叫做 EasyMonitor 可以说是非常流氓了,开机自启 + 常驻内存 + 内存泄露,时间长了以后会占用 1g 以上的内存。 它的 plist 位于 /Library/Laun...
  • 何小墨桌面画笔软件是...1. 首次运行后,软件常驻内存(占用内存大小约2M),下次直接按Ctrl F1即可直接使用。 2. 若要关闭程序,调出任务管理器关闭“Pointer.exe”进程。 3. 软件不会跟随电脑自启,所以电脑重启后
  • 软件测试常见面试题

    2019-10-24 20:47:34
    内存:空闲状态下,中等规格状态下,满规格状态下的应用内存消耗,应用内存峰值,应用内存泄露,应用是否常驻内存,压力测试后的内存使用 CPU 流量:应用首次启动流量提示,应用后台连续运行2小时的流量值,应用高负荷运行的...
  • 与其他的软件不同是:你运行BetterAndBetter软件不会调出主页面,而是常驻于状态栏,并且会实时的监控内存占用率和网速,点击它才能打开软件的主页面。另外软件功能强大,占用内存小,对于输入法的实际操作也可以...

空空如也

空空如也

1 2 3 4 5 ... 9
收藏数 179
精华内容 71
关键字:

内存常驻软件