稳定的闹钟服务定时循环请求网络接口(可做类似即时通讯或者推送功能)


为了保证我们进程运行的安全,并且为了保证我们的循环请求不会因为屏幕变暗,手机睡眠等状态而导致循环停止,推荐大家使用AlarmManager定时唤醒启动服务,执行循环。 
好了,具体看代码。 
一,MainActivity中的主要方法。

package com.mlxing.timerhttp;

import android.content.Intent;
import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;

public class MainActivity extends AppCompatActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        //启动Android定时器,并且启动服务
        TimerService.getConnet(this);
    }

    @Override
    protected void onDestroy() {
        //停止由AlarmManager启动的循环
        TimerService.stop(this);
        //停止由服务启动的循环
        Intent intent = new Intent(this, TimerService.class);
        stopService(intent);
        super.onDestroy();
    }
}
 
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26

上面没什么好讲的,主要还是让我们来看看TimerService。

package com.mlxing.timerhttp;

import android.app.AlarmManager;
import android.app.PendingIntent;
import android.app.Service;
import android.content.Context;
import android.content.Intent;
import android.os.IBinder;
import android.util.Log;

import com.zhy.http.okhttp.OkHttpUtils;
import com.zhy.http.okhttp.callback.StringCallback;

import okhttp3.Call;

public class TimerService extends Service {
    private boolean pushthread = false;
    public TimerService() {
    }

    @Override
    public IBinder onBind(Intent intent) {
        Log.d("TimerService", "onBind");
        throw new UnsupportedOperationException("Not yet implemented");
    }

    @Override
    public int onStartCommand(Intent intent, int flags, int startId) {
        Log.d("TimerService", "onStartCommand");
        if (intent.getStringExtra("flags").equals("3")) {
            //判断当系统版本大于20,即超过Android5.0时,我们采用线程循环的方式请求。
            //当小于5.0时的系统则采用定时唤醒服务的方式执行循环
            int currentapiVersion = android.os.Build.VERSION.SDK_INT;
            if (currentapiVersion > 20) {
                getPushThread();
            } else {
                getHttp();
            }
        }
        return super.onStartCommand(intent, flags, startId);
    }

    //循环请求的线程
    public void getPushThread() {
        pushthread = true;
        new Thread(new Runnable() {
            @Override
            public void run() {
                while (pushthread) {
                    try {
                        Thread.sleep(3000);
                        getHttp();
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
            }
        }).start();
    }

    //请求网络获取数据
    private void getHttp() {
        String url = "http://sns.maimaicha.com/api?apikey=b4f4ee31a8b9acc866ef2afb754c33e6&format=json&method=news.getNewsContent&id=1";
        OkHttpUtils.get().url(url).build().execute(new StringCallback() {
            @Override
            public void onError(Call call, Exception e, int id) {
                Log.d("TimerService", "TimerService" + e.toString());
            }
            @Override
            public void onResponse(String response, int id) {
                Log.d("TimerService", "response==" + response);
            }
        });
    }

    @Override
    public void onDestroy() {
        pushthread = false;
        Log.d("TimerService", "onDestroy");
        super.onDestroy();
    }

    //启动服务和定时器
    public static void getConnet(Context mContext) {
        try {
            Intent intent = new Intent(mContext, TimerService.class);
            intent.putExtra("flags", "3");
            int currentapiVersion = android.os.Build.VERSION.SDK_INT;
            if (currentapiVersion > 20) {
                //一般的启动服务的方式
                mContext.startService(intent);
            } else {
                //定时唤醒服务的启动方式
                PendingIntent pIntent = PendingIntent.getService(mContext, 0,
                        intent, PendingIntent.FLAG_UPDATE_CURRENT);
                AlarmManager alarmManager = (AlarmManager) mContext
                        .getSystemService(Context.ALARM_SERVICE);
                alarmManager.setRepeating(AlarmManager.RTC_WAKEUP,
                        System.currentTimeMillis(), 3000, pIntent);
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }


    //停止由AlarmManager启动的循环
    public static void stop(Context mContext) {
        Intent intent = new Intent(mContext, TimerService.class);
        PendingIntent pIntent = PendingIntent.getService(mContext, 0,
                intent, PendingIntent.FLAG_UPDATE_CURRENT);
        AlarmManager alarmManager = (AlarmManager) mContext
                .getSystemService(Context.ALARM_SERVICE);
        alarmManager.cancel(pIntent);
    }
}
 
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77
  • 78
  • 79
  • 80
  • 81
  • 82
  • 83
  • 84
  • 85
  • 86
  • 87
  • 88
  • 89
  • 90
  • 91
  • 92
  • 93
  • 94
  • 95
  • 96
  • 97
  • 98
  • 99
  • 100
  • 101
  • 102
  • 103
  • 104
  • 105
  • 106
  • 107
  • 108
  • 109
  • 110
  • 111
  • 112
  • 113
  • 114
  • 115
  • 116

运行之后结果如下: 
Android4.4
好了,这里就需要重点说明一下,虽然代码里的注释已经写的很清楚了。首先就是系统版本的问题,在Android5.0之后,Android系统对于省电功能这一块做了很大的改善,所以在手机进入睡眠,黑屏等状态时,系统会停止应用的一些不必要的进程。导致一些普通的线程在没有经过保护的情况下自己停止运作了。所以在这里我们在低于5.0版本的时候使用定时唤醒服务AlarmManager 的方式来执行循环,具体的AlarmManager 使用方法和功能网上有很多讲解的地方,在这里我就不细说了。 
不信请看图说话,本人手机亲测小米Note Android6.0系统的效果 
Android6.0
请看圈起来的时间,我在代码中设置的3秒请求一次,然而实际上却是60秒之后,而且手机不同时间还不一样。

还有我这里的网络请求为了节约时间用的是张鸿洋大神的封装的OkHttpUtils。具体链接如下: 
http://blog.csdn.net/lmj623565791/article/details/47911083 
不吹不黑,对于新手来说真的超级方便。今天就说这里吧,别忘了在建项目的时候配置清单文件

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.mlxing.timerhttp">

    <uses-permission android:name="android.permission.INTERNET" />
    <application
        android:allowBackup="true"
        android:icon="@mipmap/ic_launcher"
        android:label="@string/app_name"
        android:supportsRtl="true"
        android:theme="@style/AppTheme">
        <activity android:name=".MainActivity">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />

                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>

        <service
            android:name=".TimerService"
            android:enabled="true"
            android:exported="true"></service>
    </application>

</manifest>


注意:

getConnet 下的flags 。 可能获取的时候会出现获取不到的情况,程序会直接崩溃了,

这里对获取的地方onStartCommand进行空判处理,提升逻辑严谨性:

 @Override
    public int onStartCommand(Intent intent, int flags, int startId) {
        Log.e(TAG, "-----------------------onStartCommand----------------------");
        if (intent != null){
            String flags1 = intent.getStringExtra("flags");
            if (!TextUtils.isEmpty(flags1)){
                //判断当系统版本大于20,即超过Android5.0时,我们采用线程循环的方式请求。
                //当小于5.0时的系统则采用定时唤醒服务的方式执行循环
                int currentapiVersion = android.os.Build.VERSION.SDK_INT;
                if (currentapiVersion > 20) {
                    Log.e(TAG, "-----------------------currentapiVersion > 20----------------------");
                    getPushThread();
                } else {
                    Log.e(TAG, "-----------------------currentapiVersion < 20----------------------");
                    getHttp();
                }
            }
        }

        return super.onStartCommand(intent, flags, startId);
    }





参考自:http://blog.csdn.net/hkq463/article/details/51969753




评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值