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

自从做了第一个项目之后,也有很多朋友问到项目中即时通讯的实现方法,然而是事实上我之前做的项目并非真正意义上的即时通讯,但也达到了需要的效果并且使得项目的包小,运行正常。在此,我今天就讲一下这个写法,顺便写了下面这个小例子,其实也并没有什么难度的东西,只是在一些小细节上需要注意。如果有朋友觉得有什么不妥的地方,欢迎批评指教!
在这里,为了保证我们进程运行的安全,并且为了保证我们的循环请求不会因为屏幕变暗,手机睡眠等状态而导致循环停止,推荐大家使用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();
    }
}

上面没什么好讲的,主要还是让我们来看看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);
    }
}

运行之后结果如下:
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
不吹不黑,对于新手来说真的超级方便。今天就说这里吧,别忘了在建项目的时候配置清单文件


<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>

你可能感兴趣的:(个人笔记)