Android–基於PUSH服務的位置共享軟件app的實現

原文地址:http://blog.ygeekcome.com/archives/186


開發軟件的目的很單純:如果想知道Ta的位置,你不用主動詢問,打開手機軟件,即可查看到對方的實時位置。

軟件的早期版本沒有使用PUSH服務,而是通過動態算法輪詢的方式進行位置數據提交,比較耗費電量和流量。
軟件最新版本下載地址:

在新版的軟件中加入了PUSH服務,在手機開機完成後會自動啓動一個後臺的PUSH服務,建立與PUSH服務器的長連接,以便收取到推送的消息。
PUSH服務使用的是JPUSH提供的免費服務。
在Android工程中添加JPUSH支持:

1、導入 SDK 開發包到你自己的應用程序項目

  • 解壓縮 jpush-sdk_v1.x.y.zip 集成壓縮包
  • 複製 libs/jpush-sdk-release1.x.y.jar 到工程 libs/ 目錄下
  • 複製 libs/armeabi/libjpush.so 到工程 libs/armeabi 目錄下

    如果您的項目有 libs/armeabi-v7a 這個目錄,請把 libjpush.so 也複製一份到這個目錄。

2、配置 AndroidManifest.xml

根據 SDK 壓縮包裏的 AndroidManifest.xml 樣例文件,來配置應用程序項目的 AndroidManifest.xml 。

主要步驟爲:

  1. 複製備註爲 “Required” 的部分
  2. 將備註爲替換包名的部分,替換爲當前應用程序的包名

將AppKey替換爲在Portal上註冊該應用的的Key,例如(9fed5bcb7b9b87413678c407)

01<?xml version="1.0"encoding="utf-8"?>
02<manifest xmlns:android="http://schemas.android.com/apk/res/android"
03    package="Your Package"
04    android:versionCode="100"
05    android:versionName="1.0.0"
06    >
07 
08    <!-- Required -->
09    <permission android:name="Your Package.permission.JPUSH_MESSAGE" android:protectionLevel="signature" />
10 
11    <!-- Required -->
12    <uses-permission android:name="You Package.permission.JPUSH_MESSAGE" />
13    <uses-permission android:name="android.permission.RECEIVE_USER_PRESENT" />
14    <uses-permission android:name="android.permission.INTERNET" />
15    <uses-permission android:name="android.permission.WAKE_LOCK" />
16    <uses-permission android:name="android.permission.READ_PHONE_STATE" />
17    <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
18    <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
19    <uses-permission android:name="android.permission.VIBRATE" />
20    <uses-permission android:name="android.permission.MOUNT_UNMOUNT_FILESYSTEMS"/>
21    <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
22 
23    <!-- Optional. Required for location feature -->
24    <uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
25    <uses-permission android:name="android.permission.ACCESS_COARSE_UPDATES" />
26    <uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
27    <uses-permission android:name="android.permission.CHANGE_WIFI_STATE" />
28    <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
29    <uses-permission android:name="android.permission.ACCESS_LOCATION_EXTRA_COMMANDS" />
30    <uses-permission android:name="android.permission.CHANGE_NETWORK_STATE" />
31 
32    <application
33        android:icon="@drawable/ic_launcher"
34        android:label="@string/app_name"
35        android:name="Your Application">
36 
37        <!-- Required -->
38        <service
39            android:name="cn.jpush.android.service.PushService"
40            android:enabled="true"
41            android:exported="false" >
42            <intent-filter>
43                <action android:name="cn.jpush.android.intent.REGISTER" />
44                <action android:name="cn.jpush.android.intent.REPORT" />
45                <action android:name="cn.jpush.android.intent.PushService" />
46                <action android:name="cn.jpush.android.intent.PUSH_TIME" />
47            </intent-filter>
48        </service>
49 
50        <!-- Required -->
51        <receiver
52            android:name="cn.jpush.android.service.PushReceiver"
53            android:enabled="true" >
54          <intent-filter android:priority="1000"<!--since 1.3.5 -->
55                <action android:name="cn.jpush.android.intent.NOTIFICATION_RECEIVED_PROXY" /> <!--since 1.3.5 -->
56                <category android:name="Your Package" /> <!--since 1.3.5 -->
57            </intent-filter<!--since 1.3.5 -->
58            <intent-filter>
59                <action android:name="android.intent.action.USER_PRESENT" />
60                <action android:name="android.net.conn.CONNECTIVITY_CHANGE" />
61            </intent-filter>
62            <intent-filter>
63                <action android:name="android.intent.action.PACKAGE_ADDED" />
64                <action android:name="android.intent.action.PACKAGE_REMOVED" />
65                <data android:scheme="package" />
66            </intent-filter>
67        </receiver>
68     <!-- Required SDK核心功能-->
69        <activity
70            android:name="cn.jpush.android.ui.PushActivity"
71            android:theme="@android:style/Theme.Translucent.NoTitleBar"
72            android:configChanges="orientation|keyboardHidden" >
73            <intent-filter>
74                <action android:name="cn.jpush.android.ui.PushActivity" />
75                <category android:name="android.intent.category.DEFAULT" />
76                <category android:name="Your Package" />
77            </intent-filter>
78        </activity>
79        <!-- Required SDK核心功能-->
80        <service
81            android:name="cn.jpush.android.service.DownloadService"
82            android:enabled="true"
83            android:exported="false" >
84        </service>
85        <!-- Required SDK核心功能-->
86        <receiver android:name="cn.jpush.android.service.AlarmReceiver" />
87 
88        <!-- Required. For publish channel feature -->
89        <!-- JPUSH_CHANNEL 是爲了方便開發者統計APK分發渠道。-->
90        <!-- 例如: -->
91        <!-- 發到 Google Play 的APK可以設置爲 google-play; -->
92        <!-- 發到其他市場的 APK 可以設置爲 xxx-market。 -->
93        <!-- 目前這個渠道統計功能的報表還未開放。-->
94        <meta-data android:name="JPUSH_CHANNEL" android:value="developer-default"/>
95        <!-- Required. AppKey copied from Portal -->
96        <meta-data android:name="JPUSH_APPKEY" android:value="Your AppKey"/>
97    </application>
98</manifest>

然後在Android工程中添加BroadcastReciever類,用來接收系統的廣播,在系統期待完成後發送一個啓動完成的廣播,在收到這個廣播消息後啓動PUSH服務,然後對用戶名進行MD5加密後設在alias,用於對該用戶的唯一標識:

01Log.d(TAG,"Starting Push Service");
02JPushInterface.init(context);
03Log.d(TAG,"Push Service Started");
04 
05String email = sharedPreferences.getString("EMAIL"null);
06Log.d(TAG,"Set your device Alias to :"+email);
07 
08//如果沒有記錄到用戶的用戶名則不設置
09if(email != null)
10JPushInterface.setAliasAndTags(context, Utils.MD5(email), null);
這樣就建立了與PUSH服務器的長連接,由於使用MD5算法進行字符串加密,保證了別名的唯一性。

當用於需要查看對方的位置信息的時候,打開本軟件後會通過ASYNC任務向軟件服務器發送一個Web Service請求:

01public class ChangeTaStateTask extends AsyncTask<String, Void, Boolean> {
02    @Override
03    protected Boolean doInBackground(String... params) {
04 
05        SoapObject changestate_soap =  new SoapObject(NAMESPACE, CHANGE_TA_STATE_AND_RETURN);
06 
07        /*
08         * params[0] is the email
09         *
10         * params[1] is the state:
11         * 0:not be focused
12         * 1:be focused
13        */
14        changestate_soap.addProperty("arg0",params[0]);
15        changestate_soap.addProperty("arg1",params[1]);
16 
17        Log.d(TAG, "Send a request to your friend to open position service");
18 
19        //鐢熸垚璋冪敤Web service鏂規硶鐨凷OAP璇鋒眰淇℃伅
20        SoapSerializationEnvelope envelope = new SoapSerializationEnvelope(SoapEnvelope.VER11);
21        envelope.bodyOut = changestate_soap;
22        envelope.dotNet = false;
23 
24        HttpTransportSE ht = new HttpTransportSE(URL);
25 
26        try {
27            ht.call(NAMESPACE + CHANGE_TA_STATE_AND_RETURN, envelope);
28        catch (IOException e) {
29            // TODO Auto-generated catch block
30            e.printStackTrace();
31        catch (XmlPullParserException e) {
32            // TODO Auto-generated catch block
33            e.printStackTrace();
34        }
35 
36        return true;
37    }
38}

 

 

服務器端添加對JPUSH的支持:

點擊下載:jpush-api-v2.zip

在你的項目裏引入 jpush-java-libraryV2.jar 以及lib文件夾裏的第三方依賴包(gson.jar)。

服務器接收到該請求會向對方通過唯一標識的別名發送一個PUSH消息:

01if(email == null || on_off == null)
02    return "ER";
03 
04jpush = getJpushClient();
05 
06MessageResult msgResult = jpush.sendCustomMessageWithAlias(getRandomSendNo(),Utils.MD5(ta_email), email, on_off);
07 
08if (null != msgResult) {
09    logger.info("JPUSH return data: " + msgResult.toString());
10    if (msgResult.getErrcode() == ErrorCodeEnum.NOERROR.value()) {
11        logger.info(String.format("send message successfully錛?sendNo= %s,messageId= %s",msgResult.getSendno(),msgResult.getMsg_id()));
12        return "OK";
13    else {
14        logger.error("send message failed錛?error code=" + msgResult.getErrcode() + ", error message=" + msgResult.getErrmsg());
15        return "ER";
16    }
17else {
18    logger.error("鏃犳硶鑾峯彇鏁版嵁");
19    return "ER";
20}

 

當另一方收到該自定義消息會進行消息的解析,然後通過消息的內容進行判斷是開啓還是關閉位置上傳服。
當你退出或將軟件運行轉到後臺後,也同時會向服務器發送PUSH服務,請求關閉對方的位置上傳服務。
由於有PUSH服務的支持,所以可以實現位置的按需上傳。只要對方開機,默認開啓數據連接,就能時刻查看對方的位置。

=-=-=-=-=
Powered by Blogilo


發佈了383 篇原創文章 · 獲贊 774 · 訪問量 271萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章