Android 后台运行那些事

这里我告诉大家一些最快最实用的解决方法,这些都是放在我项目中成功实现的。

Service 保活

服务相互保活是一个很流氓的方式 而且随着sdk升级 这种方式已经不能在高版本使用了;
解决方式:
1*一种比较文明的方式,这也是大多数注重用户体验app使用的*
下面这张是我常用的app,因为常常把它放在后台记录行程,所以有一天突然app跳出提示说被意外杀死,要我怎么做怎么做. 其实说的很明白了。根据不同的手机对后台运行app的容忍度不同。一般都会在3-5分钟左右杀死。这个时候即使你依然在运行但是收不到任何通知网络也会被断掉,也就是常说的休眠。 这种机制很好的保护了你的电池续航。
这里写图片描述

2 提升服务到前台,starService并bindService

//onStartCommand只会调用一次  
//START_STICKY类似的一共有3个  
//想了解的可以去查一下 这个意思是当服务被杀死后开启后不走onCreate直接启动;
@Override
    public int onStartCommand(Intent intent, int flags, int startId) {
        play();
        return START_STICKY;
    }

    //这个就是将服务提到前台的代码
    private void play() {
        if (!isPlay) {
            isPlay = true;
            //和上一笔记中创建通知的步骤一样,只是不需要通过通知管理器进行触发,而是用startForeground(ID,notify)来处理
            //步骤1:和上一笔记一样,通过Notification.Builder( )来创建通知
            //FakePlayer就是两个大button的activity,也即服务的界面,见最左图
            Intent i = new Intent(this, MainActivity.class);
            //注意Intent的flag设置:FLAG_ACTIVITY_CLEAR_TOP: 如果activity已在当前任务中运行,在它前端的activity都会被关闭,它就成了最前端的activity。FLAG_ACTIVITY_SINGLE_TOP: 如果activity已经在最前端运行,则不需要再加载。设置这两个flag,就是让一个且唯一的一个activity(服务界面)运行在最前端。
            i.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP | Intent.FLAG_ACTIVITY_SINGLE_TOP);
            PendingIntent pi = PendingIntent.getActivity(this, 0, i, 0);
            Notification myNotify = new Notification.Builder(this)
                    .setSmallIcon(R.drawable.logo)
                    .setContentTitle("共享代驾")
                    .setContentText("共享代驾正在工作中")
                    .setContentIntent(null)
                    .getNotification();
            //设置notification的flag,表明在点击通知后,通知并不会消失,也在最右图上仍在通知栏显示图标。这是确保在activity中退出后,状态栏仍有图标可提下拉、点击,再次进入activity。
            myNotify.flags |= Notification.FLAG_NO_CLEAR;
            // 步骤 2:startForeground( int, Notification)将服务设置为foreground状态,使系统知道该服务是用户关注,低内存情况下不会killed,并提供通知向用户表明处于foreground状态。
            startForeground(968, myNotify);
        }
    }
    private void stop() {
        if (isPlay) {
            isPlay = false;
            //将服务从forefround状态中移走,使得系统可以在低内存的情况下清除它。
            stopForeground(true);
        }
    }

starService并bindService
先开启在绑定服务 这样做即使所有绑定服务的Activity走了onDestory了 服务依然可以在后台运行
还有一种方式在Manifest中给Service配置 android:priority =1000;

Service于Activity通讯

描述问题 : 当你切出去到桌面的时候 如何在回到当前界面而不都是数据 常常会发现页面上的数据不见了甚至崩溃的情况
解决方法:
1*使用movebackTask结合HomeWatcherReceiver使用 *
这种方式只是让桌面挡住了当前的Activity而没有正真的走onDestory方法;
监听到home键被按下就执行该方法 点击app图标会很快回到当前界面而且数据不会丢失

public class HomeWatcherReceiver extends BroadcastReceiver {
    private static final String LOG_TAG = "HomeReceiver";
    private static final String SYSTEM_DIALOG_REASON_KEY = "reason";
    private static final String SYSTEM_DIALOG_REASON_HOME_KEY = "homekey";

    @Override
    public void onReceive(Context context, Intent intent) {
        String action = intent.getAction();
        Log.i(LOG_TAG, "onReceive: action: " + action);
        if (action.equals(Intent.ACTION_CLOSE_SYSTEM_DIALOGS)) {
            String reason = intent.getStringExtra(SYSTEM_DIALOG_REASON_KEY);
            if (SYSTEM_DIALOG_REASON_HOME_KEY.equals(reason)) {
                ((LocationActivity) context).moveTaskToBack(true);
            }
        }
    }

2*当我们点击通知的到Activity界面数据消失问题*
解决方法:
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_SINGLE_TOP);
这个flags的意思是如果该Activity存在于栈中就将他置顶否则重新创建;
一般你切换到后的时候不应该销毁这个Activity的 但是事实是过不了30秒他就会被销毁
结合上面的HomeWatcherReceiver 使用就可以防止这个数据丢失的问题;

/**
     * 创建通知
     */
    private void setUpNotification() {
        if (currentTencentLocation != null) {
            int id = new Random(System.nanoTime()).nextInt();
            // 放置在"正在运行"栏目中
            Intent intent = new Intent(this, MovingActivity.class);
            intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_SINGLE_TOP);
            PendingIntent contentIntent = PendingIntent.getActivity(this, UUID.randomUUID().hashCode(), intent, PendingIntent.FLAG_UPDATE_CURRENT);
            //intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK);
            //intent.putExtra(MovingActivity.IntentResult, getIntentResult(currentTencentLocation));
            Notification mNotification = new Notification.Builder(ServingPassengerDownloadService.this)
                    .setAutoCancel(true)
                    .setContentTitle("车辆行驶中")
                    .setSmallIcon(R.drawable.logo)
                    .setContentIntent(contentIntent)
                    .setWhen(System.currentTimeMillis()).getNotification();
            mNotification.flags = Notification.FLAG_ONGOING_EVENT;
            mNotificationManager.notify(id, mNotification);
        }
    }

有一种情况 当你开着app不使用半个小时间1个小时后会怎样?

大多数不会去考虑这个问题,是怎样就怎样吧~,但是烦人的客户不买账怎么办?
以上的三种方式可以就做到app在后台长期运行 但是app在长时间后台将会进入休眠(在上面就有说过)。
解决方法:

//当请求中断后  注意是你框架中的回调突然走了Error的时候,这个时候你应该去判断并排除网络断开的原因
//你发现原来是代码依然在运行,可就是不走onNext方法,发个通知他也收不到··,这就是上面说到的休眠状态。
//以下是做一个闹钟唤醒app这种方式还挺好用的。但是现在手机品牌很多 我测试的小米note1只能唤醒一次,再次
//唤醒将无效。。。。无效。。。
 boolean b = !cheNetWork();
                    Log.i("cheNetWork", "===========cheNetWork=============" + b);
                    if (b) return;
                    AlarmManager aManager = (AlarmManager) getSystemService(ALARM_SERVICE);
                    Intent intent = new Intent();
                    intent.setData(Uri.parse("Start://Now"));
                    PendingIntent pi = PendingIntent.getActivity(MainActivity.this, 0, intent, 0);
                    intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS);
                    aManager.set(AlarmManager.RTC_WAKEUP, Calendar.getInstance().getTimeInMillis(), pi);

其他

1 屏幕常亮
android:keepScreenOn=”true”
2 在Activity的oncreate中加入以下代码 结合上面的闹钟 可以唤醒屏幕
**getWindow().addFlags(
WindowManager.LayoutParams.FLAG_DISMISS_KEYGUARD |
WindowManager.LayoutParams.FLAG_TURN_SCREEN_ON |
WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);**
3 有的朋友会问:那APP就是被杀死了呢?怎么办?
好吧 推荐大家使用一款数据库

//之所以推荐这个是因为他可以动态更新,网上对它评价褒贬不一,请自行选择
public class RealmHelper {
    public static final String DB_NAME = "drive.realm";
    private Realm mRealm;
    private static RealmHelper instance;
    private int maxSize;

    private RealmHelper() {
        maxSize = 10;
    }

    public static RealmHelper getInstance() {
        if (instance == null) {
            synchronized (RealmHelper.class) {
                if (instance == null)
                    instance = new RealmHelper();
            }
        }
        return instance;
    }

    public Realm getRealm() {
        if (mRealm == null || mRealm.isClosed())
            mRealm = Realm.getDefaultInstance();
        return mRealm;
    }
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值