From a22583da81e40e4b967c7495d1d5030756d63124 Mon Sep 17 00:00:00 2001 From: Administrator <981964879@qq.com> Date: Fri, 27 Mar 2020 18:46:43 +0800 Subject: [PATCH] =?UTF-8?q?update:2019.03.27=20fix:=E6=9B=B4=E6=96=B0?= =?UTF-8?q?=E6=9E=81=E5=85=89=E6=8E=A8=E9=80=81=E6=A1=86=E6=9E=B6=E5=88=B0?= =?UTF-8?q?=E6=9C=80=E6=96=B0=E7=89=88=E6=9C=AC=20add:?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/build.gradle | 12 +- app/libs/armeabi-v7a/libjpush220.so | Bin 99756 -> 0 bytes app/src/main/AndroidManifest.xml | 269 +++++++++----- .../com/mjsheng/myappstore/MyApplication.java | 157 ++++++++ .../myappstore/activity/MainActivity.java | 301 +++++++++------- .../mjsheng/myappstore/jpush/ExampleUtil.java | 132 +++++++ .../jpush/Invalid/ExampleApplication.java | 25 ++ .../jpush/Invalid/MainActivity.java | 163 +++++++++ .../jpush/Invalid/PushSetActivity.java | 265 ++++++++++++++ .../jpush/Invalid/SettingActivity.java | 177 +++++++++ .../jpush/Invalid/TestActivity.java | 32 ++ .../jpush/LocalBroadcastManager.java | 263 ++++++++++++++ .../com/mjsheng/myappstore/jpush/Logger.java | 40 ++ .../jpush/MyJPushMessageReceiver.java | 46 +++ .../mjsheng/myappstore/jpush/MyReceiver.java | 129 +++++++ .../mjsheng/myappstore/jpush/PushService.java | 7 + .../jpush/TagAliasOperatorHelper.java | 341 ++++++++++++++++++ .../myappstore/network/HTTPInterface.java | 64 ++++ .../myappstore/receiver/MyJPushReceiver.java | 1 + .../myappstore/server/InitJpushServer.java | 122 +++---- .../mjsheng/myappstore/utils/ApkUtils.java | 6 +- .../mjsheng/myappstore/utils/Configure.java | 10 +- 22 files changed, 2261 insertions(+), 301 deletions(-) delete mode 100644 app/libs/armeabi-v7a/libjpush220.so create mode 100644 app/src/main/java/com/mjsheng/myappstore/jpush/ExampleUtil.java create mode 100644 app/src/main/java/com/mjsheng/myappstore/jpush/Invalid/ExampleApplication.java create mode 100644 app/src/main/java/com/mjsheng/myappstore/jpush/Invalid/MainActivity.java create mode 100644 app/src/main/java/com/mjsheng/myappstore/jpush/Invalid/PushSetActivity.java create mode 100644 app/src/main/java/com/mjsheng/myappstore/jpush/Invalid/SettingActivity.java create mode 100644 app/src/main/java/com/mjsheng/myappstore/jpush/Invalid/TestActivity.java create mode 100644 app/src/main/java/com/mjsheng/myappstore/jpush/LocalBroadcastManager.java create mode 100644 app/src/main/java/com/mjsheng/myappstore/jpush/Logger.java create mode 100644 app/src/main/java/com/mjsheng/myappstore/jpush/MyJPushMessageReceiver.java create mode 100644 app/src/main/java/com/mjsheng/myappstore/jpush/MyReceiver.java create mode 100644 app/src/main/java/com/mjsheng/myappstore/jpush/PushService.java create mode 100644 app/src/main/java/com/mjsheng/myappstore/jpush/TagAliasOperatorHelper.java diff --git a/app/build.gradle b/app/build.gradle index 5cf353c..8b2e426 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -16,8 +16,9 @@ android { targetSdkVersion 26 // versionCode 85 // versionName "2.0.4.6"//正式jiaoguanyi.com - versionCode 107 - versionName "2.6.9"//测试jiaoguanyi.cn + versionCode 113 + versionName "2.7.5"//测试jiaoguanyi.cn + multiDexEnabled true testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner" packagingOptions { @@ -36,6 +37,9 @@ android { lintOptions { checkReleaseBuilds false } + dexOptions { + jumboMode true + } //签名 signingConfigs { debug { @@ -139,7 +143,9 @@ dependencies { implementation 'io.reactivex.rxjava2:rxandroid:2.0.1' implementation 'com.google.code.gson:gson:2.2.4' - implementation 'cn.jiguang:jpush:2.2.0' +// implementation 'cn.jiguang:jpush:2.2.0' + implementation 'cn.jiguang.sdk:jpush:3.5.6' // 此处以JPush 3.5.6 版本为例。 + implementation 'cn.jiguang.sdk:jcore:2.2.8' // 此处以JCore 2.2.8 版本为例。 implementation "com.github.yjfnypeu:UpdatePlugin:3.0.1" diff --git a/app/libs/armeabi-v7a/libjpush220.so b/app/libs/armeabi-v7a/libjpush220.so deleted file mode 100644 index b7e43a8cca3d8a9ad952926040a6a1275d7b7ea4..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 99756 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 diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index 9876aeb..da820b5 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -1,28 +1,34 @@ - - + + + + + + + android:protectionLevel="signature" /> + + + - - + + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + android:exported="true"> + + + + + + + + + + + + @@ -137,7 +102,8 @@ - + + @@ -149,35 +115,160 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + android:value="20f70bbeb78bad23eddd08d0" /> + - - - - - - - - - - - - - - - - - diff --git a/app/src/main/java/com/mjsheng/myappstore/MyApplication.java b/app/src/main/java/com/mjsheng/myappstore/MyApplication.java index 7a94f72..425f646 100644 --- a/app/src/main/java/com/mjsheng/myappstore/MyApplication.java +++ b/app/src/main/java/com/mjsheng/myappstore/MyApplication.java @@ -4,6 +4,8 @@ import android.app.Activity; import android.content.Context; import android.content.Intent; import android.content.res.Configuration; +import android.os.Handler; +import android.os.Message; import android.support.multidex.MultiDexApplication; import android.util.Log; @@ -21,6 +23,8 @@ import com.mjsheng.myappstore.Statistics.StatisticsInfo; import com.mjsheng.myappstore.activity.MainActivity; import com.mjsheng.myappstore.bean.FileData; import com.mjsheng.myappstore.comm.CommonDatas; +import com.mjsheng.myappstore.jpush.TagAliasOperatorHelper; +import com.mjsheng.myappstore.network.HTTPInterface; import com.mjsheng.myappstore.utils.ApkUtils; import com.mjsheng.myappstore.utils.Configure; import com.mjsheng.myappstore.utils.MySQLData; @@ -43,11 +47,15 @@ import java.util.HashMap; import java.util.LinkedList; import java.util.List; import java.util.Map; +import java.util.concurrent.TimeUnit; import java.util.logging.Level; import cn.jpush.android.api.JPushInterface; +import cn.jpush.android.api.JPushMessage; import okhttp3.Call; import okhttp3.Response; +import rx.Observable; +import rx.functions.Action1; import uk.co.chrisjenx.calligraphy.CalligraphyConfig; /** @@ -81,6 +89,7 @@ public class MyApplication extends MultiDexApplication implements Thread.Uncaugh return instance; } + @Override public void onCreate() { super.onCreate(); @@ -125,6 +134,154 @@ public class MyApplication extends MultiDexApplication implements Thread.Uncaugh } + + public void onTagOperatorResult(JPushMessage jPushMessage) { + if (jPushMessage == null) { + return; + } + String s = "tags:\t"; + int errorCode = jPushMessage.getErrorCode(); + switch (errorCode) { + case 0: + Log.e("jiguangInterface", s + "Tag绑定成功"); + break; + case 6001: + Log.e("jiguangInterface", s + "无效的设置"); + break; + case 6005: + Log.e("jiguangInterface", s + "某一个 tag 字符串不合法"); + ToastUtil.show("设备标签不合法,联系管理员修改\t" + "code:6005"); + break; + case 6006: + Log.e("jiguangInterface", s + "某一个 tag 超长"); + ToastUtil.show("设备标签过长,联系管理员修改\t" + "code:6006"); + break; + case 6007: + Log.e("jiguangInterface", s + "tags 数量超出限制"); + ToastUtil.show("设备标签数量超出限制,联系管理员修改\t" + "code:6007"); + break; + case 6008: + Log.e("jiguangInterface", s + "tag 超出总长度限制"); + ToastUtil.show("设备标签超出总长度限制,联系管理员修改\t" + "code:6008"); + break; + case 6011: + Log.e("jiguangInterface", s + "短时间内操作过于频繁"); + break; + case 6013: + Log.e("jiguangInterface", s + "用户设备时间轴异常"); + ToastUtil.show("用户设备时间轴异常,修改后重新登陆\t" + "code:6013"); + break; + case 6018: + Log.e("jiguangInterface", s + "Tags 过多"); + ToastUtil.show("设备标签数量超出限制,联系管理员修改\t" + "code:6018"); + break; + case 6021: + Log.e("jiguangInterface", s + "tags 操作正在进行中"); + break; + + //需要重新设置 + case 6002: + Log.e("jiguangInterface", s + "设置超时,请重试"); + setJpushTags(); + break; + case 6014: + Log.e("jiguangInterface", s + "服务器繁忙,建议重试"); + setJpushTags(); + break; + case 6020: + Log.e("jiguangInterface", s + "建议过一段时间再设置"); + setJpushTags(); + break; + case 6024: + Log.e("jiguangInterface", s + "服务器内部错误"); + setJpushTags(); + break; + } + } + + public static void setJpushTags() { + Log.e("jiguangInterface", "30s后重新设置tags"); + Observable.timer(30000, TimeUnit.MILLISECONDS) + .observeOn(rx.android.schedulers.AndroidSchedulers.mainThread()) + .subscribe(new Action1() { + @Override + public void call(Long aLong) { + HTTPInterface.setJpushTags(context); + } + }); + } + + + public void onAliasOperatorResult(JPushMessage jPushMessage) { + if (jPushMessage == null) { + return; + } + String s = "alias:\t"; + int errorCode = jPushMessage.getErrorCode(); + switch (errorCode) { + case 0: + Log.e("jiguangInterface", s + "Alias绑定成功"); + break; + case 6001: + Log.e("jiguangInterface", s + "无效的设置"); + break; + case 6011: + Log.e("jiguangInterface", s + "短时间内操作过于频繁"); + break; + case 6013: + Log.e("jiguangInterface", s + "用户设备时间轴异常"); + ToastUtil.show("用户设备时间轴异常,修改后重新登陆\t" + s + "code:6013"); + break; + case 6022: + Log.e("jiguangInterface", s + "alias 操作正在进行中"); + break; + + + //需要重新设置 + case 6002: + Log.e("jiguangInterface", s + "设置超时,请重试"); + setJpushAlias(); + break; + case 6014: + Log.e("jiguangInterface", s + "服务器繁忙,建议重试"); + setJpushAlias(); + break; + case 6020: + Log.e("jiguangInterface", s + "建议过一段时间再设置"); + setJpushAlias(); + break; + case 6024: + Log.e("jiguangInterface", s + "服务器内部错误"); + setJpushAlias(); + break; + + case 6017: + case 6027: + Log.e("jiguangInterface", s + "别名绑定的设备数超过限制"); + clean(); + setJpushAlias(); + break; + } + } + + public static void setJpushAlias() { + Log.e("jiguangInterface", "30s后重新设置alias"); + Observable.timer(30000, TimeUnit.MILLISECONDS) + .observeOn(rx.android.schedulers.AndroidSchedulers.mainThread()) + .subscribe(new Action1() { + @Override + public void call(Long aLong) { + JPushInterface.setAlias(context, TagAliasOperatorHelper.sequence++, Utils.getSerial()); + } + }); + } + + public void clean() { + //alias的绑定的设备超过10个,但是alias应该是一个设备对应一个,在重置设备后jpush的regid会变动,所以需要清除 + //https://docs.jiguang.cn/jpush/server/push/rest_api_v3_device/#_5 + HTTPInterface.cleanJpushAlias(Utils.getSerial()); + } + private boolean finished = false; public boolean isFinished() { diff --git a/app/src/main/java/com/mjsheng/myappstore/activity/MainActivity.java b/app/src/main/java/com/mjsheng/myappstore/activity/MainActivity.java index 6481ac3..e8a213c 100644 --- a/app/src/main/java/com/mjsheng/myappstore/activity/MainActivity.java +++ b/app/src/main/java/com/mjsheng/myappstore/activity/MainActivity.java @@ -56,6 +56,7 @@ import com.mjsheng.myappstore.bean.NetAndLaunchData; import com.mjsheng.myappstore.bean.UploadAppInfo; import com.mjsheng.myappstore.bean.UserInfo; import com.mjsheng.myappstore.comm.CommonDatas; +import com.mjsheng.myappstore.jpush.TagAliasOperatorHelper; import com.mjsheng.myappstore.network.HTTPInterface; import com.mjsheng.myappstore.network.Network; import com.mjsheng.myappstore.network.api.AppLimitApi; @@ -90,11 +91,15 @@ import java.io.IOException; import java.util.ArrayList; import java.util.HashSet; import java.util.List; +import java.util.Random; import java.util.Set; import java.util.concurrent.TimeUnit; +import cn.jpush.android.api.CustomMessage; import cn.jpush.android.api.JPushInterface; +import cn.jpush.android.api.JPushMessage; import cn.jpush.android.api.TagAliasCallback; +import cn.jpush.android.service.JPushMessageReceiver; import io.reactivex.Observer; import io.reactivex.android.schedulers.AndroidSchedulers; import io.reactivex.disposables.Disposable; @@ -105,6 +110,14 @@ import okhttp3.ResponseBody; import rx.Observable; import rx.functions.Action1; +import static com.mjsheng.myappstore.jpush.TagAliasOperatorHelper.ACTION_ADD; +import static com.mjsheng.myappstore.jpush.TagAliasOperatorHelper.ACTION_CHECK; +import static com.mjsheng.myappstore.jpush.TagAliasOperatorHelper.ACTION_CLEAN; +import static com.mjsheng.myappstore.jpush.TagAliasOperatorHelper.ACTION_DELETE; +import static com.mjsheng.myappstore.jpush.TagAliasOperatorHelper.ACTION_GET; +import static com.mjsheng.myappstore.jpush.TagAliasOperatorHelper.ACTION_SET; +import static com.mjsheng.myappstore.jpush.TagAliasOperatorHelper.TagAliasBean; +import static com.mjsheng.myappstore.jpush.TagAliasOperatorHelper.sequence; public class MainActivity extends AppCompatActivity implements NetStateChangeObserver { @@ -114,11 +127,132 @@ public class MainActivity extends AppCompatActivity implements NetStateChangeObs private final String ACTION_HrReceiver_JGY_DIS = "qch_jgy_network_disallow"; private final String ACTION_HrReceiver_JGY = "qch_jgy_network_allow"; private DownloadManager downloadManager; - public static boolean isForeground = false; private ImageView imageView; private TextView tv_devsn, tv_devmac, tv_version; private int DeviceInfo; + //jiguang + public static boolean isForeground = false; + //for receive customer msg from jpush server + private MessageReceiver mMessageReceiver; + public static final String MESSAGE_RECEIVED_ACTION = "com.jiaoguanyi.appstore.MESSAGE_RECEIVED_ACTION"; + public static final String KEY_TITLE = "title"; + public static final String KEY_MESSAGE = "message"; + public static final String KEY_EXTRAS = "extras"; + + public void registerMessageReceiver() { + mMessageReceiver = new MessageReceiver(); + IntentFilter filter = new IntentFilter(); + filter.setPriority(IntentFilter.SYSTEM_HIGH_PRIORITY); + filter.addAction(MESSAGE_RECEIVED_ACTION); + LocalBroadcastManager.getInstance(this).registerReceiver(mMessageReceiver, filter); + } + + public class MessageReceiver extends BroadcastReceiver { + @Override + public void onReceive(Context context, Intent intent) { + try { + if (MESSAGE_RECEIVED_ACTION.equals(intent.getAction())) { + String messge = intent.getStringExtra(KEY_MESSAGE); + String extras = intent.getStringExtra(KEY_EXTRAS); + StringBuilder showMsg = new StringBuilder(); + showMsg.append(KEY_MESSAGE + " : " + messge + "\n"); + if (!ExampleUtil.isEmpty(extras)) { + showMsg.append(KEY_EXTRAS + " : " + extras + "\n"); + } +// setCostomMsg(showMsg.toString()); + } + } catch (Exception e) { + } + } + } + + + public void onTagAliasAction(int i) { + Set tags = null; + String alias = null; + int action = -1; + boolean isAliasAction = false; + switch (i) { + //设置手机号码: + case 0: +// handleSetMobileNumber(); + return; + //增加tag + case 1: +// tags = getInPutTags(); + if (tags == null) { + return; + } + action = ACTION_ADD; + break; + //设置tag + case 2: +// tags = getInPutTags(); + if (tags == null) { + return; + } + action = ACTION_SET; + break; + //删除tag + case 3: +// tags = getInPutTags(); + if (tags == null) { + return; + } + action = ACTION_DELETE; + break; + //获取所有tag + case 4: + action = ACTION_GET; + break; + //清除所有tag + case 5: + action = ACTION_CLEAN; + break; + case 6: +// tags = getInPutTags(); + if (tags == null) { + return; + } + action = ACTION_CHECK; + break; + //设置alias + case 7: +// alias = getInPutAlias(); + alias = Utils.getSerial(); + if (TextUtils.isEmpty(alias)) { + return; + } + isAliasAction = true; + action = ACTION_SET; + break; + //获取alias + case 8: + isAliasAction = true; + action = ACTION_GET; + break; + //删除alias + case 9: + isAliasAction = true; + action = ACTION_DELETE; + break; + default: + return; + } + TagAliasBean tagAliasBean = new TagAliasBean(); + tagAliasBean.action = action; + sequence++; + if (isAliasAction) { + tagAliasBean.alias = alias; + } else { + tagAliasBean.tags = tags; + } + tagAliasBean.isAliasAction = isAliasAction; + TagAliasOperatorHelper.getInstance().handleAction(getApplicationContext(), sequence, tagAliasBean); + + } + @Override public void onConfigurationChanged(Configuration newConfig) { super.onConfigurationChanged(newConfig); @@ -131,9 +265,7 @@ public class MainActivity extends AppCompatActivity implements NetStateChangeObs // super.onSaveInstanceState(outState, outPersistentState); } - private class LocationReceiver extends BroadcastReceiver { - @Override public void onReceive(Context context, Intent intent) { // ToastTool.show("广播:::"+intent.getAction() + "--------" + intent.getStringExtra("package_name")); @@ -164,6 +296,7 @@ public class MainActivity extends AppCompatActivity implements NetStateChangeObs callback = new ToastCallback(this); initView(); + timerImitate(); initData(); downloadManager = DownloadService.getDownloadManager(); @@ -173,6 +306,7 @@ public class MainActivity extends AppCompatActivity implements NetStateChangeObs sendBroadcast(allIntent); } + //获取教管易版本号 synchronized private String getAPPVersionName() { PackageManager pm = getPackageManager(); @@ -229,9 +363,10 @@ public class MainActivity extends AppCompatActivity implements NetStateChangeObs Log.e("mjhsneg", "gagagag--------------------------" + Utils.getSerial()); getLockedState(); initJpush();//初始化极光推送 - setJpushTags(); + HTTPInterface.setJpushTags(this); // update();//接口更新app sendMACaddress(); + checkUpdate();//更新app Log.e("mac", com.blankj.utilcode.util.DeviceUtils.getMacAddress()); DeviceInfo = (int) SPUtils.get(this, "isLogined", 2); @@ -326,42 +461,6 @@ public class MainActivity extends AppCompatActivity implements NetStateChangeObs } - //for receive customer msg from jpush server - private MessageReceiver mMessageReceiver; - public static final String MESSAGE_RECEIVED_ACTION = "com.example.jpushdemo.MESSAGE_RECEIVED_ACTION"; - public static final String KEY_TITLE = "title"; - public static final String KEY_MESSAGE = "message"; - public static final String KEY_EXTRAS = "extras"; - - public void registerMessageReceiver() { - mMessageReceiver = new MessageReceiver(); - IntentFilter filter = new IntentFilter(); - filter.setPriority(IntentFilter.SYSTEM_HIGH_PRIORITY); - filter.addAction(MESSAGE_RECEIVED_ACTION); - LocalBroadcastManager.getInstance(this).registerReceiver(mMessageReceiver, filter); - } - - public class MessageReceiver extends BroadcastReceiver { - - @Override - public void onReceive(Context context, Intent intent) { - try { - if (MESSAGE_RECEIVED_ACTION.equals(intent.getAction())) { - String messge = intent.getStringExtra(KEY_MESSAGE); - String extras = intent.getStringExtra(KEY_EXTRAS); - StringBuilder showMsg = new StringBuilder(); - showMsg.append(KEY_MESSAGE + " : " + messge + "\n"); - if (!ExampleUtil.isEmpty(extras)) { - showMsg.append(KEY_EXTRAS + " : " + extras + "\n"); - } -// setCostomMsg(showMsg.toString()); - } - } catch (Exception e) { - } - } - } - - private boolean locked = false; public void getLockedState() { @@ -419,7 +518,6 @@ public class MainActivity extends AppCompatActivity implements NetStateChangeObs Aria.download(this).resumeAllTask(); // getForceDownload();//强制下载apk resetDevice();//恢复出厂设置 - checkUpdate();//更新app // fromNetToUpdate(); String registrationID = JPushInterface.getRegistrationID(MainActivity.this); Log.e("mjsheng", registrationID + "------------------------"); @@ -499,20 +597,23 @@ public class MainActivity extends AppCompatActivity implements NetStateChangeObs @Override protected void onStop() { - super.onStop(); } + @Override + protected void onPause() { + isForeground = false; + super.onPause(); + } @Override protected void onResume() { super.onResume(); + isForeground = true; Intent allIntent = new Intent(); allIntent.setAction(Utils.DOWNLOAD_ALLTASK_ACTION); sendBroadcast(allIntent); loadHeadImg(Configure.HTTP_TAG_HOME_PAGE_URL); - - lazyLoading(); } @@ -670,82 +771,41 @@ public class MainActivity extends AppCompatActivity implements NetStateChangeObs }); } - private void setJpushTags() { - OkGo.get(Configure.GET_DEVICES_TAGS) - .params("sn", Utils.getSerial()) - .execute(new StringCallback() { - @Override - public void onSuccess(String s, Call call, Response response) { - Log.e("fht", s); - com.alibaba.fastjson.JSONObject jsonObject = JSON.parseObject(s); - int code = jsonObject.getInteger("code"); - com.alibaba.fastjson.JSONObject data = jsonObject.getJSONObject("data"); - if (code == 200) { - String batch = data.getString("batch"); - if (batch != null && !batch.equals("")) { - Set set = new HashSet(); - set.add(batch); - JPushInterface.setTags(MainActivity.this, set, new TagAliasCallback() { - @Override - public void gotResult(int i, String s, Set set) { - if (set == null) { - Log.e("initmjsheng", "set is null"); - } else { - Log.e("initmjsheng", "set ---" + set.toString()); - } - Log.e("JPushInterface", s + "---" + i + "---"); - if (i == 0) { - Log.e("JPushInterface", "Tag绑定成功"); - } else if (i == 6001) { - Log.e("JPushInterface", "无效的设置,用户名为空"); - } else if (i == 6002) { - Log.e("JPushInterface", "设置超时,请重试"); - timerImitate(); - } else if (i == 6011) { - Log.e("JPushInterface", "短时间内操作过于频繁"); - } else if (i == 996) { - Log.e("JPushInterface", "网络连接断开"); - timerImitate(); - } - } - }); - } - } - } - - @Override - public void onError(Call call, Response response, Exception e) { - super.onError(call, response, e); - Log.e("fht", e.getMessage()); - } - }); - } private void initJpush() { - - JPushInterface.setAlias(this, Utils.getSerial(), new TagAliasCallback() { - @Override - public void gotResult(int i, String s, Set set) { - if (set == null) { - Log.e("mjhseng", "set is null"); - } else { - Log.e("mjhseng", "set ---" + set.toString()); - } - Log.e("JPushInterface", s + "---" + i + "---"); - if (i == 0) { - Log.e("JPushInterface", "JPush绑定成功"); - } else if (i == 6001) { - Log.e("JPushInterface", "无效的设置,用户名为空"); - } else if (i == 6002) { - Log.e("JPushInterface", "设置超时,请重试"); - timerImitate(); - } else if (i == 6011) { - Log.e("JPushInterface", "短时间内操作过于频繁"); - } else if (i == 996) { - Log.e("JPushInterface", "网络连接断开"); - } - } - }); + onTagAliasAction(7); + String rid = JPushInterface.getRegistrationID(getApplicationContext()); + if (!rid.isEmpty()) { +// ToastUtil.debugShow("RegId:" + rid); + Log.e("jiguang", "RegId:" + rid); + } else { +// ToastUtil.show("Get registration fail, JPush init failed!"); +// Toast.makeText(this, "Get registration fail, JPush init failed!", Toast.LENGTH_SHORT).show(); + } + JPushInterface.getAlias(this, new Random().nextInt(100)); +// JPushInterface.setAlias(this, Utils.getSerial(), new TagAliasCallback() { +// @Override +// public void gotResult(int i, String s, Set set) { +// if (set == null) { +// Log.e("mjhseng", "set is null"); +// } else { +// Log.e("mjhseng", "set ---" + set.toString()); +// } +// Log.e("JPushInterface", s + "---" + i + "---"); +// if (i == 0) { +// Log.e("JPushInterface", "JPush绑定成功"); +// } else if (i == 6001) { +// Log.e("JPushInterface", "无效的设置,用户名为空"); +// } else if (i == 6002) { +// Log.e("JPushInterface", "设置超时,请重试"); +// timerImitate(); +// } else if (i == 6011) { +// Log.e("JPushInterface", "短时间内操作过于频繁"); +// } else if (i == 996) { +// Log.e("JPushInterface", "网络连接断开"); +// } +// } +// }); } @@ -758,8 +818,7 @@ public class MainActivity extends AppCompatActivity implements NetStateChangeObs public void call(Long aLong) { Log.e("JPushInterface", "JPushInterface重新加载"); initJpush(); - setJpushTags(); - + HTTPInterface.setJpushTags(MainActivity.this); } }); } @@ -1104,7 +1163,7 @@ public class MainActivity extends AppCompatActivity implements NetStateChangeObs if ("com.jiaoguanyi.appstore".equals(forceDownloadData.getApp_package())) { Aria.download(this) .load(forceDownloadData.getApp_url()) //读取下载地址 - .setDownloadPath(PathUtils.getExternalDownloadsPath() + "/ygj/" + EncryptUtils.encryptMD5ToString("com.mjsheng.myappstore") + ".apk") + .setDownloadPath(PathUtils.getExternalDownloadsPath() + "/ygj/" + EncryptUtils.encryptMD5ToString("com.jiaoguanyi.appstore") + ".apk") .setExtendField("com.mjsheng.myappstore") .start(); //启动下载} diff --git a/app/src/main/java/com/mjsheng/myappstore/jpush/ExampleUtil.java b/app/src/main/java/com/mjsheng/myappstore/jpush/ExampleUtil.java new file mode 100644 index 0000000..9dd9c70 --- /dev/null +++ b/app/src/main/java/com/mjsheng/myappstore/jpush/ExampleUtil.java @@ -0,0 +1,132 @@ +package com.mjsheng.myappstore.jpush; + +import android.content.Context; +import android.content.pm.ApplicationInfo; +import android.content.pm.PackageInfo; +import android.content.pm.PackageManager; +import android.content.pm.PackageManager.NameNotFoundException; +import android.net.ConnectivityManager; +import android.net.NetworkInfo; +import android.os.Bundle; +import android.os.Looper; +import android.telephony.TelephonyManager; +import android.text.TextUtils; + +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +import cn.jpush.android.api.JPushInterface; + +public class ExampleUtil { + public static final String PREFS_NAME = "JPUSH_EXAMPLE"; + public static final String PREFS_DAYS = "JPUSH_EXAMPLE_DAYS"; + public static final String PREFS_START_TIME = "PREFS_START_TIME"; + public static final String PREFS_END_TIME = "PREFS_END_TIME"; + public static final String KEY_APP_KEY = "JPUSH_APPKEY"; + + public static boolean isEmpty(String s) { + if (null == s) + return true; + if (s.length() == 0) + return true; + if (s.trim().length() == 0) + return true; + return false; + } + /** + * 只能以 “+” 或者 数字开头;后面的内容只能包含 “-” 和 数字。 + * */ + private final static String MOBILE_NUMBER_CHARS = "^[+0-9][-0-9]{1,}$"; + public static boolean isValidMobileNumber(String s) { + if(TextUtils.isEmpty(s)) return true; + Pattern p = Pattern.compile(MOBILE_NUMBER_CHARS); + Matcher m = p.matcher(s); + return m.matches(); + } + // 校验Tag Alias 只能是数字,英文字母和中文 + public static boolean isValidTagAndAlias(String s) { + Pattern p = Pattern.compile("^[\u4E00-\u9FA50-9a-zA-Z_!@#$&*+=.|]+$"); + Matcher m = p.matcher(s); + return m.matches(); + } + + // 取得AppKey + public static String getAppKey(Context context) { + Bundle metaData = null; + String appKey = null; + try { + ApplicationInfo ai = context.getPackageManager().getApplicationInfo( + context.getPackageName(), PackageManager.GET_META_DATA); + if (null != ai) + metaData = ai.metaData; + if (null != metaData) { + appKey = metaData.getString(KEY_APP_KEY); + if ((null == appKey) || appKey.length() != 24) { + appKey = null; + } + } + } catch (NameNotFoundException e) { + + } + return appKey; + } + + // 取得版本号 + public static String GetVersion(Context context) { + try { + PackageInfo manager = context.getPackageManager().getPackageInfo( + context.getPackageName(), 0); + return manager.versionName; + } catch (NameNotFoundException e) { + return "Unknown"; + } + } + + public static void showToast(final String toast, final Context context) + { + new Thread(new Runnable() { + + @Override + public void run() { + Looper.prepare(); +// Toast.makeText(context, toast, Toast.LENGTH_SHORT).show(); + Looper.loop(); + } + }).start(); + } + + public static boolean isConnected(Context context) { + ConnectivityManager conn = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE); + NetworkInfo info = conn.getActiveNetworkInfo(); + return (info != null && info.isConnected()); + } + + public static String getImei(Context context, String imei) { + String ret = null; + try { + TelephonyManager telephonyManager = (TelephonyManager) context.getSystemService(Context.TELEPHONY_SERVICE); + ret = telephonyManager.getDeviceId(); + } catch (Exception e) { + Logger.e(ExampleUtil.class.getSimpleName(), e.getMessage()); + } + if (isReadableASCII(ret)){ + return ret; + } else { + return imei; + } + } + + private static boolean isReadableASCII(CharSequence string){ + if (TextUtils.isEmpty(string)) return false; + try { + Pattern p = Pattern.compile("[\\x20-\\x7E]+"); + return p.matcher(string).matches(); + } catch (Throwable e){ + return true; + } + } + + public static String getDeviceId(Context context) { + return JPushInterface.getUdid(context); + } +} diff --git a/app/src/main/java/com/mjsheng/myappstore/jpush/Invalid/ExampleApplication.java b/app/src/main/java/com/mjsheng/myappstore/jpush/Invalid/ExampleApplication.java new file mode 100644 index 0000000..a45b731 --- /dev/null +++ b/app/src/main/java/com/mjsheng/myappstore/jpush/Invalid/ExampleApplication.java @@ -0,0 +1,25 @@ +package com.mjsheng.myappstore.jpush.Invalid; + +import android.app.Application; + +import com.mjsheng.myappstore.jpush.Logger; + +import cn.jpush.android.api.JPushInterface; + +/** + * For developer startup JPush SDK + * + * 一般建议在自定义 Application 类里初始化。也可以在主 Activity 里。 + */ +public class ExampleApplication extends Application { + private static final String TAG = "JIGUANG-Example"; + + @Override + public void onCreate() { + Logger.d(TAG, "[ExampleApplication] onCreate"); + super.onCreate(); + + JPushInterface.setDebugMode(true); // 设置开启日志,发布时请关闭日志 + JPushInterface.init(this); // 初始化 JPush + } +} diff --git a/app/src/main/java/com/mjsheng/myappstore/jpush/Invalid/MainActivity.java b/app/src/main/java/com/mjsheng/myappstore/jpush/Invalid/MainActivity.java new file mode 100644 index 0000000..51fc316 --- /dev/null +++ b/app/src/main/java/com/mjsheng/myappstore/jpush/Invalid/MainActivity.java @@ -0,0 +1,163 @@ +package com.mjsheng.myappstore.jpush.Invalid; + + +//public class MainActivity extends InstrumentedActivity implements OnClickListener{ +// +// private Button mInit; +// private Button mSetting; +// private Button mStopPush; +// private Button mResumePush; +// private Button mGetRid; +// private TextView mRegId; +// private EditText msgText; +// +// public static boolean isForeground = false; +// @Override +// public void onCreate(Bundle savedInstanceState) { +// super.onCreate(savedInstanceState); +// setContentView(R.layout.main); +// initView(); +// registerMessageReceiver(); // used for receive msg +// } +// +// private void initView(){ +// TextView mImei = (TextView) findViewById(R.id.tv_imei); +// String udid = ExampleUtil.getImei(getApplicationContext(), ""); +// if (null != udid) mImei.setText("IMEI: " + udid); +// +// TextView mAppKey = (TextView) findViewById(R.id.tv_appkey); +// String appKey = ExampleUtil.getAppKey(getApplicationContext()); +// if (null == appKey) appKey = "AppKey异常"; +// mAppKey.setText("AppKey: " + appKey); +// +// mRegId = (TextView) findViewById(R.id.tv_regId); +// mRegId.setText("RegId:"); +// +// String packageName = getPackageName(); +// TextView mPackage = (TextView) findViewById(R.id.tv_package); +// mPackage.setText("PackageName: " + packageName); +// +// String deviceId = ExampleUtil.getDeviceId(getApplicationContext()); +// TextView mDeviceId = (TextView) findViewById(R.id.tv_device_id); +// mDeviceId.setText("deviceId:" + deviceId); +// +// String versionName = ExampleUtil.GetVersion(getApplicationContext()); +// TextView mVersion = (TextView) findViewById(R.id.tv_version); +// mVersion.setText("Version: " + versionName); +// +// mInit = (Button)findViewById(R.id.init); +// mInit.setOnClickListener(this); +// +// mStopPush = (Button)findViewById(R.id.stopPush); +// mStopPush.setOnClickListener(this); +// +// mResumePush = (Button)findViewById(R.id.resumePush); +// mResumePush.setOnClickListener(this); +// +// mGetRid = (Button) findViewById(R.id.getRegistrationId); +// mGetRid.setOnClickListener(this); +// +// mSetting = (Button)findViewById(R.id.setting); +// mSetting.setOnClickListener(this); +// +// msgText = (EditText)findViewById(R.id.msg_rec); +// } +// +// +// @Override +// public void onClick(View v) { +// switch (v.getId()) { +// case R.id.init: +// init(); +// break; +// case R.id.setting: +// Intent intent = new Intent(MainActivity.this, PushSetActivity.class); +// startActivity(intent); +// break; +// case R.id.stopPush: +// JPushInterface.stopPush(getApplicationContext()); +// break; +// case R.id.resumePush: +// JPushInterface.resumePush(getApplicationContext()); +// break; +// case R.id.getRegistrationId: +// String rid = JPushInterface.getRegistrationID(getApplicationContext()); +// if (!rid.isEmpty()) { +// mRegId.setText("RegId:" + rid); +// } else { +// Toast.makeText(this, "Get registration fail, JPush init failed!", Toast.LENGTH_SHORT).show(); +// } +// break; +// } +// } +// +// // 初始化 JPush。如果已经初始化,但没有登录成功,则执行重新登录。 +// private void init(){ +// JPushInterface.init(getApplicationContext()); +// } +// +// +// @Override +// protected void onResume() { +// isForeground = true; +// super.onResume(); +// } +// +// +// @Override +// protected void onPause() { +// isForeground = false; +// super.onPause(); +// } +// +// +// @Override +// protected void onDestroy() { +// LocalBroadcastManager.getInstance(this).unregisterReceiver(mMessageReceiver); +// super.onDestroy(); +// } +// +// +// //for receive customer msg from jpush server +// private MessageReceiver mMessageReceiver; +// public static final String MESSAGE_RECEIVED_ACTION = "com.example.jpushdemo.MESSAGE_RECEIVED_ACTION"; +// public static final String KEY_TITLE = "title"; +// public static final String KEY_MESSAGE = "message"; +// public static final String KEY_EXTRAS = "extras"; +// +// public void registerMessageReceiver() { +// mMessageReceiver = new MessageReceiver(); +// IntentFilter filter = new IntentFilter(); +// filter.setPriority(IntentFilter.SYSTEM_HIGH_PRIORITY); +// filter.addAction(MESSAGE_RECEIVED_ACTION); +// LocalBroadcastManager.getInstance(this).registerReceiver(mMessageReceiver, filter); +// } +// +// public class MessageReceiver extends BroadcastReceiver { +// +// @Override +// public void onReceive(Context context, Intent intent) { +// try { +// if (MESSAGE_RECEIVED_ACTION.equals(intent.getAction())) { +// String messge = intent.getStringExtra(KEY_MESSAGE); +// String extras = intent.getStringExtra(KEY_EXTRAS); +// StringBuilder showMsg = new StringBuilder(); +// showMsg.append(KEY_MESSAGE + " : " + messge + "\n"); +// if (!ExampleUtil.isEmpty(extras)) { +// showMsg.append(KEY_EXTRAS + " : " + extras + "\n"); +// } +// setCostomMsg(showMsg.toString()); +// } +// } catch (Exception e){ +// } +// } +// } +// +// private void setCostomMsg(String msg){ +// if (null != msgText) { +// msgText.setText(msg); +// msgText.setVisibility(View.VISIBLE); +// } +// } + +//} \ No newline at end of file diff --git a/app/src/main/java/com/mjsheng/myappstore/jpush/Invalid/PushSetActivity.java b/app/src/main/java/com/mjsheng/myappstore/jpush/Invalid/PushSetActivity.java new file mode 100644 index 0000000..c09653e --- /dev/null +++ b/app/src/main/java/com/mjsheng/myappstore/jpush/Invalid/PushSetActivity.java @@ -0,0 +1,265 @@ +package com.mjsheng.myappstore.jpush.Invalid; + +//public class PushSetActivity extends InstrumentedActivity implements OnClickListener { +// private static final String TAG = "JIGUANG-Example"; +// +// @Override +// public void onCreate(Bundle icicle) { +// super.onCreate(icicle); +// setContentView(R.layout.push_set_dialog); +// initListener(); +// } +// +// private void initListener() { +// //增加tag +// findViewById(R.id.bt_addtag).setOnClickListener(this); +// //设置tag +// findViewById(R.id.bt_settag).setOnClickListener(this); +// //删除tag +// findViewById(R.id.bt_deletetag).setOnClickListener(this); +// //获取所有tag +// findViewById(R.id.bt_getalltag).setOnClickListener(this); +// //清除所有tag +// findViewById(R.id.bt_cleantag).setOnClickListener(this); +// //查询tag绑定状态 +// findViewById(R.id.bt_checktag).setOnClickListener(this); +// +// //设置alias +// findViewById(R.id.bt_setalias).setOnClickListener(this); +// //获取alias +// findViewById(R.id.bt_getalias).setOnClickListener(this); +// //删除alias +// findViewById(R.id.bt_deletealias).setOnClickListener(this); +// //设置手机号码 +// findViewById(R.id.bt_setmobileNumber).setOnClickListener(this); +// //StyleAddActions +// findViewById(R.id.setStyle0).setOnClickListener(this); +// //StyleBasic +// findViewById(R.id.setStyle1).setOnClickListener(this); +// //StyleCustom +// findViewById(R.id.setStyle2).setOnClickListener(this); +// //SetPushTime +// findViewById(R.id.bu_setTime).setOnClickListener(this); +// } +// +// @Override +// public void onClick(View view) { +// switch (view.getId()) { +// case R.id.setStyle0: +// setAddActionsStyle(); +// break; +// case R.id.setStyle1: +// setStyleBasic(); +// break; +// case R.id.setStyle2: +// setStyleCustom(); +// break; +// case R.id.bu_setTime: +// Intent intent = new Intent(PushSetActivity.this, SettingActivity.class); +// startActivity(intent); +// break; +// default: +// onTagAliasAction(view); +// break; +// } +// } +// +// TagAliasCallback tagAlias = new TagAliasCallback() { +// @Override +// public void gotResult(int responseCode, String alias, Set tags) { +// Log.e(TAG,"responseCode:"+responseCode+",alias:"+alias+",tags:"+tags); +// } +// }; +// +// +// /** +// * 设置通知提示方式 - 基础属性 +// */ +// private void setStyleBasic() { +// BasicPushNotificationBuilder builder = new BasicPushNotificationBuilder(PushSetActivity.this); +// builder.statusBarDrawable = R.drawable.ic_launcher; +// builder.notificationFlags = Notification.FLAG_AUTO_CANCEL; //设置为点击后自动消失 +// builder.notificationDefaults = Notification.DEFAULT_SOUND; //设置为铃声( Notification.DEFAULT_SOUND)或者震动( Notification.DEFAULT_VIBRATE) +// JPushInterface.setPushNotificationBuilder(1, builder); +// Toast.makeText(PushSetActivity.this, "Basic Builder - 1", Toast.LENGTH_SHORT).show(); +// } +// +// +// /** +// * 设置通知栏样式 - 定义通知栏Layout +// */ +// private void setStyleCustom() { +// CustomPushNotificationBuilder builder = new CustomPushNotificationBuilder(PushSetActivity.this, R.layout.customer_notitfication_layout, R.id.icon, R.id.title, R.id.text); +// builder.layoutIconDrawable = R.drawable.ic_launcher; +// builder.developerArg0 = "developerArg2"; +// JPushInterface.setPushNotificationBuilder(2, builder); +// Toast.makeText(PushSetActivity.this, "Custom Builder - 2", Toast.LENGTH_SHORT).show(); +// } +// +// @Override +// public boolean onKeyDown(int keyCode, KeyEvent event) { +// if (keyCode == KeyEvent.KEYCODE_BACK) { +// finish(); +// } +// return super.onKeyDown(keyCode, event); +// } +// +// private void setAddActionsStyle() { +// MultiActionsNotificationBuilder builder = new MultiActionsNotificationBuilder(PushSetActivity.this); +// builder.addJPushAction(R.drawable.jpush_ic_richpush_actionbar_back, "first", "my_extra1"); +// builder.addJPushAction(R.drawable.jpush_ic_richpush_actionbar_back, "second", "my_extra2"); +// builder.addJPushAction(R.drawable.jpush_ic_richpush_actionbar_back, "third", "my_extra3"); +// JPushInterface.setPushNotificationBuilder(10, builder); +// +// Toast.makeText(PushSetActivity.this, "AddActions Builder - 10", Toast.LENGTH_SHORT).show(); +// } +// +// +// /**===========================================================================**/ +// /**=========================TAG/ALIAS 相关=====================================**/ +// /**===========================================================================**/ +// +// /** +// * 处理tag/alias相关操作的点击 +// * */ +// public void onTagAliasAction(View view) { +// Set tags = null; +// String alias = null; +// int action = -1; +// boolean isAliasAction = false; +// switch (view.getId()){ +// //设置手机号码: +// case R.id.bt_setmobileNumber: +// handleSetMobileNumber(); +// return; +// //增加tag +// case R.id.bt_addtag: +// tags = getInPutTags(); +// if(tags == null){ +// return; +// } +// action = ACTION_ADD; +// break; +// //设置tag +// case R.id.bt_settag: +// tags = getInPutTags(); +// if(tags == null){ +// return; +// } +// action = ACTION_SET; +// break; +// //删除tag +// case R.id.bt_deletetag: +// tags = getInPutTags(); +// if(tags == null){ +// return; +// } +// action = ACTION_DELETE; +// break; +// //获取所有tag +// case R.id.bt_getalltag: +// action = ACTION_GET; +// break; +// //清除所有tag +// case R.id.bt_cleantag: +// action = ACTION_CLEAN; +// break; +// case R.id.bt_checktag: +// tags = getInPutTags(); +// if(tags == null){ +// return; +// } +// action = ACTION_CHECK; +// break; +// //设置alias +// case R.id.bt_setalias: +// alias = getInPutAlias(); +// if(TextUtils.isEmpty(alias)){ +// return; +// } +// isAliasAction = true; +// action = ACTION_SET; +// break; +// //获取alias +// case R.id.bt_getalias: +// isAliasAction = true; +// action = ACTION_GET; +// break; +// //删除alias +// case R.id.bt_deletealias: +// isAliasAction = true; +// action = ACTION_DELETE; +// break; +// default: +// return; +// } +// TagAliasBean tagAliasBean = new TagAliasBean(); +// tagAliasBean.action = action; +// sequence++; +// if(isAliasAction){ +// tagAliasBean.alias = alias; +// }else{ +// tagAliasBean.tags = tags; +// } +// tagAliasBean.isAliasAction = isAliasAction; +// TagAliasOperatorHelper.getInstance().handleAction(getApplicationContext(),sequence,tagAliasBean); +// } +// +// private void handleSetMobileNumber(){ +// EditText mobileEdit = (EditText) findViewById(R.id.et_mobilenumber); +// String mobileNumber = mobileEdit.getText().toString().trim(); +// if (TextUtils.isEmpty(mobileNumber)) { +// Toast.makeText(getApplicationContext(), R.string.mobilenumber_empty_guide, Toast.LENGTH_SHORT).show(); +// } +// if (!ExampleUtil.isValidMobileNumber(mobileNumber)) { +// Toast.makeText(getApplicationContext(), R.string.error_tag_gs_empty, Toast.LENGTH_SHORT).show(); +// return; +// } +// sequence++; +// TagAliasOperatorHelper.getInstance().handleAction(getApplicationContext(),sequence,mobileNumber); +// } +// /** +// * 获取输入的alias +// * */ +// private String getInPutAlias(){ +// EditText aliasEdit = (EditText) findViewById(R.id.et_alias); +// String alias = aliasEdit.getText().toString().trim(); +// if (TextUtils.isEmpty(alias)) { +// Toast.makeText(getApplicationContext(), R.string.error_alias_empty, Toast.LENGTH_SHORT).show(); +// return null; +// } +// if (!ExampleUtil.isValidTagAndAlias(alias)) { +// Toast.makeText(getApplicationContext(), R.string.error_tag_gs_empty, Toast.LENGTH_SHORT).show(); +// return null; +// } +// return alias; +// } +// /** +// * 获取输入的tags +// * */ +// private Set getInPutTags(){ +// EditText tagEdit = (EditText) findViewById(R.id.et_tag); +// String tag = tagEdit.getText().toString().trim(); +// // 检查 tag 的有效性 +// if (TextUtils.isEmpty(tag)) { +// Toast.makeText(getApplicationContext(), R.string.error_tag_empty, Toast.LENGTH_SHORT).show(); +// return null; +// } +// +// // ","隔开的多个 转换成 Set +// String[] sArray = tag.split(","); +// Set tagSet = new LinkedHashSet(); +// for (String sTagItme : sArray) { +// if (!ExampleUtil.isValidTagAndAlias(sTagItme)) { +// Toast.makeText(getApplicationContext(), R.string.error_tag_gs_empty, Toast.LENGTH_SHORT).show(); +// return null; +// } +// tagSet.add(sTagItme); +// } +// if(tagSet.isEmpty()){ +// Toast.makeText(getApplicationContext(), R.string.error_tag_empty, Toast.LENGTH_SHORT).show(); +// return null; +// } +// return tagSet; +// } +//} \ No newline at end of file diff --git a/app/src/main/java/com/mjsheng/myappstore/jpush/Invalid/SettingActivity.java b/app/src/main/java/com/mjsheng/myappstore/jpush/Invalid/SettingActivity.java new file mode 100644 index 0000000..d4b52ff --- /dev/null +++ b/app/src/main/java/com/mjsheng/myappstore/jpush/Invalid/SettingActivity.java @@ -0,0 +1,177 @@ +package com.mjsheng.myappstore.jpush.Invalid; + +//public class SettingActivity extends InstrumentedActivity implements OnClickListener { +// TimePicker startTime; +// TimePicker endTime; +// CheckBox mMonday ; +// CheckBox mTuesday ; +// CheckBox mWednesday; +// CheckBox mThursday; +// CheckBox mFriday ; +// CheckBox mSaturday; +// CheckBox mSunday ; +// Button mSetTime; +// SharedPreferences mSettings; +// Editor mEditor; +// +// @Override +// public void onCreate(Bundle icicle) { +// super.onCreate(icicle); +// setContentView(R.layout.set_push_time); +// init(); +// initListener(); +// } +// +// @Override +// public void onStart() { +// super.onStart(); +// initData(); +// } +// +// private void init(){ +// startTime = (TimePicker) findViewById(R.id.start_time); +// endTime = (TimePicker) findViewById(R.id.end_time); +// startTime.setIs24HourView(DateFormat.is24HourFormat(this)); +// endTime.setIs24HourView(DateFormat.is24HourFormat(this)); +// mSetTime = (Button)findViewById(R.id.bu_setTime); +// mMonday = (CheckBox)findViewById(R.id.cb_monday); +// mTuesday = (CheckBox)findViewById(R.id.cb_tuesday); +// mWednesday = (CheckBox)findViewById(R.id.cb_wednesday); +// mThursday = (CheckBox)findViewById(R.id.cb_thursday); +// mFriday = (CheckBox)findViewById(R.id.cb_friday); +// mSaturday = (CheckBox)findViewById(R.id.cb_saturday); +// mSunday = (CheckBox)findViewById(R.id.cb_sunday); +// } +// +// private void initListener(){ +// mSetTime.setOnClickListener(this); +// } +// +// private void initData(){ +// mSettings = getSharedPreferences(ExampleUtil.PREFS_NAME, MODE_PRIVATE); +// String days = mSettings.getString(ExampleUtil.PREFS_DAYS, ""); +// if (!TextUtils.isEmpty(days)) { +// initAllWeek(false); +// String[] sArray = days.split(","); +// for (String day : sArray) { +// setWeek(day); +// } +// } else { +// initAllWeek(true); +// } +// +// int startTimeStr = mSettings.getInt(ExampleUtil.PREFS_START_TIME, 0); +// startTime.setCurrentHour(startTimeStr); +// int endTimeStr = mSettings.getInt(ExampleUtil.PREFS_END_TIME, 23); +// endTime.setCurrentHour(endTimeStr); +// } +// +// @Override +// public void onClick(View v) { +// switch (v.getId()) { +// case R.id.bu_setTime: +// v.requestFocus(); +// v.requestFocusFromTouch(); +// setPushTime(); +// break; +// } +// } +// +// /** +// *设置允许接收通知时间 +// */ +// private void setPushTime(){ +// int startime = startTime.getCurrentHour(); +// int endtime = endTime.getCurrentHour(); +// if (startime > endtime) { +// Toast.makeText(SettingActivity.this, "开始时间不能大于结束时间", Toast.LENGTH_SHORT).show(); +// return; +// } +// StringBuffer daysSB = new StringBuffer(); +// Set days = new HashSet(); +// if (mSunday.isChecked()) { +// days.add(0); +// daysSB.append("0,"); +// } +// if (mMonday.isChecked()) { +// days.add(1); +// daysSB.append("1,"); +// } +// if (mTuesday.isChecked()) { +// days.add(2); +// daysSB.append("2,"); +// } +// if (mWednesday.isChecked()) { +// days.add(3); +// daysSB.append("3,"); +// } +// if (mThursday.isChecked()) { +// days.add(4); +// daysSB.append("4,"); +// } +// if (mFriday.isChecked()) { +// days.add(5); +// daysSB.append("5,"); +// } +// if (mSaturday.isChecked()) { +// days.add(6); +// daysSB.append("6,"); +// } +// +// +// //调用JPush api设置Push时间 +// JPushInterface.setPushTime(getApplicationContext(), days, startime, endtime); +// +// mEditor = mSettings.edit(); +// mEditor.putString(ExampleUtil.PREFS_DAYS, daysSB.toString()); +// mEditor.putInt(ExampleUtil.PREFS_START_TIME, startime); +// mEditor.putInt(ExampleUtil.PREFS_END_TIME, endtime); +// mEditor.commit(); +// Toast.makeText(SettingActivity.this, R.string.setting_su, Toast.LENGTH_SHORT).show(); +// } +// +// @Override +// public boolean onKeyDown(int keyCode, KeyEvent event) { +// if (keyCode == KeyEvent.KEYCODE_BACK){ +// finish(); +// } +// return super.onKeyDown(keyCode, event); +// } +// +// private void setWeek(String day){ +// int dayId = Integer.valueOf(day); +// switch (dayId) { +// case 0: +// mSunday.setChecked(true); +// break; +// case 1: +// mMonday.setChecked(true); +// break; +// case 2: +// mTuesday.setChecked(true); +// break; +// case 3: +// mWednesday.setChecked(true); +// break; +// case 4: +// mThursday.setChecked(true); +// break; +// case 5: +// mFriday.setChecked(true); +// break; +// case 6: +// mSaturday.setChecked(true); +// break; +// } +// } +// +// private void initAllWeek(boolean isChecked) { +// mSunday.setChecked(isChecked); +// mMonday.setChecked(isChecked); +// mTuesday.setChecked(isChecked); +// mWednesday.setChecked(isChecked); +// mThursday.setChecked(isChecked); +// mFriday.setChecked(isChecked); +// mSaturday.setChecked(isChecked); +// } +//} \ No newline at end of file diff --git a/app/src/main/java/com/mjsheng/myappstore/jpush/Invalid/TestActivity.java b/app/src/main/java/com/mjsheng/myappstore/jpush/Invalid/TestActivity.java new file mode 100644 index 0000000..4fea427 --- /dev/null +++ b/app/src/main/java/com/mjsheng/myappstore/jpush/Invalid/TestActivity.java @@ -0,0 +1,32 @@ +package com.mjsheng.myappstore.jpush.Invalid; + +import android.app.Activity; +import android.content.Intent; +import android.os.Bundle; +import android.view.ViewGroup.LayoutParams; +import android.widget.TextView; + +import cn.jpush.android.api.JPushInterface; + +public class TestActivity extends Activity { + + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + TextView tv = new TextView(this); + tv.setText("用户自定义打开的Activity"); + Intent intent = getIntent(); + if (null != intent) { + Bundle bundle = getIntent().getExtras(); + String title = null; + String content = null; + if(bundle!=null){ + title = bundle.getString(JPushInterface.EXTRA_NOTIFICATION_TITLE); + content = bundle.getString(JPushInterface.EXTRA_ALERT); + } + tv.setText("Title : " + title + " " + "Content : " + content); + } + addContentView(tv, new LayoutParams(LayoutParams.FILL_PARENT, LayoutParams.FILL_PARENT)); + } + +} diff --git a/app/src/main/java/com/mjsheng/myappstore/jpush/LocalBroadcastManager.java b/app/src/main/java/com/mjsheng/myappstore/jpush/LocalBroadcastManager.java new file mode 100644 index 0000000..5465f66 --- /dev/null +++ b/app/src/main/java/com/mjsheng/myappstore/jpush/LocalBroadcastManager.java @@ -0,0 +1,263 @@ +package com.mjsheng.myappstore.jpush; + +import android.content.BroadcastReceiver; +import android.content.Context; +import android.content.Intent; +import android.content.IntentFilter; +import android.net.Uri; +import android.os.Handler; +import android.os.Message; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.Set; + +/** + * Created by efan on 2017/4/14. + */ + +public final class LocalBroadcastManager { + private static final String TAG = "JIGUANG-Example"; + private static final boolean DEBUG = false; + private final Context mAppContext; + private final HashMap> mReceivers = new HashMap>(); + private final HashMap> mActions = new HashMap>(); + private final ArrayList mPendingBroadcasts = new ArrayList(); + static final int MSG_EXEC_PENDING_BROADCASTS = 1; + private final Handler mHandler; + private static final Object mLock = new Object(); + private static LocalBroadcastManager mInstance; + + public static LocalBroadcastManager getInstance(Context context) { + Object var1 = mLock; + synchronized (mLock) { + if (mInstance == null) { + mInstance = new LocalBroadcastManager(context.getApplicationContext()); + } + + return mInstance; + } + } + + private LocalBroadcastManager(Context context) { + this.mAppContext = context; + this.mHandler = new Handler(context.getMainLooper()) { + public void handleMessage(Message msg) { + switch (msg.what) { + case 1: + LocalBroadcastManager.this.executePendingBroadcasts(); + break; + default: + super.handleMessage(msg); + } + + } + }; + } + + public void registerReceiver(BroadcastReceiver receiver, IntentFilter filter) { + HashMap var3 = this.mReceivers; + synchronized (this.mReceivers) { + ReceiverRecord entry = new ReceiverRecord(filter, receiver); + ArrayList filters = (ArrayList) this.mReceivers.get(receiver); + if (filters == null) { + filters = new ArrayList(1); + this.mReceivers.put(receiver, filters); + } + + filters.add(filter); + + for (int i = 0; i < filter.countActions(); ++i) { + String action = filter.getAction(i); + ArrayList entries = (ArrayList) this.mActions.get(action); + if (entries == null) { + entries = new ArrayList(1); + this.mActions.put(action, entries); + } + + entries.add(entry); + } + + } + } + + public void unregisterReceiver(BroadcastReceiver receiver) { + HashMap var2 = this.mReceivers; + synchronized (this.mReceivers) { + ArrayList filters = (ArrayList) this.mReceivers.remove(receiver); + if (filters != null) { + for (int i = 0; i < filters.size(); ++i) { + IntentFilter filter = (IntentFilter) filters.get(i); + + for (int j = 0; j < filter.countActions(); ++j) { + String action = filter.getAction(j); + ArrayList receivers = (ArrayList) this.mActions.get(action); + if (receivers != null) { + for (int k = 0; k < receivers.size(); ++k) { + if (((ReceiverRecord) receivers.get(k)).receiver == receiver) { + receivers.remove(k); + --k; + } + } + + if (receivers.size() <= 0) { + this.mActions.remove(action); + } + } + } + } + + } + } + } + + public boolean sendBroadcast(Intent intent) { + HashMap var2 = this.mReceivers; + synchronized (this.mReceivers) { + String action = intent.getAction(); + String type = intent.resolveTypeIfNeeded(this.mAppContext.getContentResolver()); + Uri data = intent.getData(); + String scheme = intent.getScheme(); + Set categories = intent.getCategories(); + boolean debug = (intent.getFlags() & 8) != 0; + if (debug) { + Logger.v("LocalBroadcastManager", "Resolving type " + type + " scheme " + scheme + " of intent " + intent); + } + + ArrayList entries = (ArrayList) this.mActions.get(intent.getAction()); + if (entries != null) { + if (debug) { + Logger.v("LocalBroadcastManager", "Action list: " + entries); + } + + ArrayList receivers = null; + + int i; + for (i = 0; i < entries.size(); ++i) { + ReceiverRecord receiver = (ReceiverRecord) entries.get(i); + if (debug) { + Logger.v("LocalBroadcastManager", "Matching against filter " + receiver.filter); + } + + if (receiver.broadcasting) { + if (debug) { + Logger.v("LocalBroadcastManager", " Filter\'s target already added"); + } + } else { + int match = receiver.filter.match(action, type, scheme, data, categories, "LocalBroadcastManager"); + if (match >= 0) { + if (debug) { + Logger.v("LocalBroadcastManager", " Filter matched! match=0x" + Integer.toHexString(match)); + } + + if (receivers == null) { + receivers = new ArrayList(); + } + + receivers.add(receiver); + receiver.broadcasting = true; + } else if (debug) { + String reason; + switch (match) { + case -4: + reason = "category"; + break; + case -3: + reason = "action"; + break; + case -2: + reason = "data"; + break; + case -1: + reason = "type"; + break; + default: + reason = "unknown reason"; + } + + Logger.v("LocalBroadcastManager", " Filter did not match: " + reason); + } + } + } + + if (receivers != null) { + for (i = 0; i < receivers.size(); ++i) { + ((ReceiverRecord) receivers.get(i)).broadcasting = false; + } + + this.mPendingBroadcasts.add(new BroadcastRecord(intent, receivers)); + if (!this.mHandler.hasMessages(1)) { + this.mHandler.sendEmptyMessage(1); + } + + return true; + } + } + + return false; + } + } + + public void sendBroadcastSync(Intent intent) { + if (this.sendBroadcast(intent)) { + this.executePendingBroadcasts(); + } + + } + + private void executePendingBroadcasts() { + while (true) { + BroadcastRecord[] brs = null; + HashMap i = this.mReceivers; + synchronized (this.mReceivers) { + int br = this.mPendingBroadcasts.size(); + if (br <= 0) { + return; + } + + brs = new BroadcastRecord[br]; + this.mPendingBroadcasts.toArray(brs); + this.mPendingBroadcasts.clear(); + } + + for (int var6 = 0; var6 < brs.length; ++var6) { + BroadcastRecord var7 = brs[var6]; + + for (int j = 0; j < var7.receivers.size(); ++j) { + ((ReceiverRecord) var7.receivers.get(j)).receiver.onReceive(this.mAppContext, var7.intent); + } + } + } + } + + private static class BroadcastRecord { + final Intent intent; + final ArrayList receivers; + + BroadcastRecord(Intent _intent, ArrayList _receivers) { + this.intent = _intent; + this.receivers = _receivers; + } + } + + private static class ReceiverRecord { + final IntentFilter filter; + final BroadcastReceiver receiver; + boolean broadcasting; + + ReceiverRecord(IntentFilter _filter, BroadcastReceiver _receiver) { + this.filter = _filter; + this.receiver = _receiver; + } + + public String toString() { + StringBuilder builder = new StringBuilder(128); + builder.append("Receiver{"); + builder.append(this.receiver); + builder.append(" filter="); + builder.append(this.filter); + builder.append("}"); + return builder.toString(); + } + } +} \ No newline at end of file diff --git a/app/src/main/java/com/mjsheng/myappstore/jpush/Logger.java b/app/src/main/java/com/mjsheng/myappstore/jpush/Logger.java new file mode 100644 index 0000000..010114d --- /dev/null +++ b/app/src/main/java/com/mjsheng/myappstore/jpush/Logger.java @@ -0,0 +1,40 @@ +package com.mjsheng.myappstore.jpush; + +import android.util.Log; + +/** + * Created by efan on 2017/4/13. + */ + +public class Logger { + + //设为false关闭日志 + private static final boolean LOG_ENABLE = true; + + public static void i(String tag, String msg){ + if (LOG_ENABLE){ + Log.i(tag, msg); + } + } + public static void v(String tag, String msg){ + if (LOG_ENABLE){ + Log.v(tag, msg); + } + } + public static void d(String tag, String msg){ + if (LOG_ENABLE){ + Log.d(tag, msg); + } + } + public static void w(String tag, String msg){ + if (LOG_ENABLE){ + Log.w(tag, msg); + } + } + public static void e(String tag, String msg){ + if (LOG_ENABLE){ + Log.e(tag, msg); + } + } + +} diff --git a/app/src/main/java/com/mjsheng/myappstore/jpush/MyJPushMessageReceiver.java b/app/src/main/java/com/mjsheng/myappstore/jpush/MyJPushMessageReceiver.java new file mode 100644 index 0000000..aabb4a3 --- /dev/null +++ b/app/src/main/java/com/mjsheng/myappstore/jpush/MyJPushMessageReceiver.java @@ -0,0 +1,46 @@ +package com.mjsheng.myappstore.jpush; + +import android.content.Context; + +import com.mjsheng.myappstore.MyApplication; + +import cn.jpush.android.api.CustomMessage; +import cn.jpush.android.api.JPushMessage; +import cn.jpush.android.service.JPushMessageReceiver; + +/** + * 自定义JPush message 接收器,包括操作tag/alias的结果返回(仅仅包含tag/alias新接口部分) + * */ +public class MyJPushMessageReceiver extends JPushMessageReceiver { + + @Override + public void onTagOperatorResult(Context context, JPushMessage jPushMessage) { + TagAliasOperatorHelper.getInstance().onTagOperatorResult(context,jPushMessage); + super.onTagOperatorResult(context, jPushMessage); + MyApplication.getInstance().onTagOperatorResult(jPushMessage); + } + @Override + public void onCheckTagOperatorResult(Context context, JPushMessage jPushMessage){ + TagAliasOperatorHelper.getInstance().onCheckTagOperatorResult(context,jPushMessage); + super.onCheckTagOperatorResult(context, jPushMessage); + } + @Override + public void onAliasOperatorResult(Context context, JPushMessage jPushMessage) { + TagAliasOperatorHelper.getInstance().onAliasOperatorResult(context,jPushMessage); + super.onAliasOperatorResult(context, jPushMessage); + MyApplication.getInstance().onAliasOperatorResult(jPushMessage); + } + + @Override + public void onMobileNumberOperatorResult(Context context, JPushMessage jPushMessage) { + TagAliasOperatorHelper.getInstance().onMobileNumberOperatorResult(context,jPushMessage); + super.onMobileNumberOperatorResult(context, jPushMessage); + } + + @Override + public void onMessage(Context context, CustomMessage customMessage) { + super.onMessage(context, customMessage); + } + + +} diff --git a/app/src/main/java/com/mjsheng/myappstore/jpush/MyReceiver.java b/app/src/main/java/com/mjsheng/myappstore/jpush/MyReceiver.java new file mode 100644 index 0000000..7db837e --- /dev/null +++ b/app/src/main/java/com/mjsheng/myappstore/jpush/MyReceiver.java @@ -0,0 +1,129 @@ +package com.mjsheng.myappstore.jpush; + +import android.content.BroadcastReceiver; +import android.content.Context; +import android.content.Intent; +import android.os.Bundle; +import android.text.TextUtils; + +import com.mjsheng.myappstore.activity.MainActivity; + +import org.json.JSONException; +import org.json.JSONObject; + +import java.util.Iterator; + +import cn.jpush.android.api.JPushInterface; + +/** + * 自定义接收器 + * + * 如果不定义这个 Receiver,则: + * 1) 默认用户会打开主界面 + * 2) 接收不到自定义消息 + */ +public class MyReceiver extends BroadcastReceiver { + private static final String TAG = "JIGUANG-Example"; + + @Override + public void onReceive(Context context, Intent intent) { + try { + Bundle bundle = intent.getExtras(); + Logger.d(TAG, "[MyReceiver] onReceive - " + intent.getAction() + ", extras: " + printBundle(bundle)); + + if (JPushInterface.ACTION_REGISTRATION_ID.equals(intent.getAction())) { + String regId = bundle.getString(JPushInterface.EXTRA_REGISTRATION_ID); + Logger.d(TAG, "[MyReceiver] 接收Registration Id : " + regId); + //send the Registration Id to your server... + + } else if (JPushInterface.ACTION_MESSAGE_RECEIVED.equals(intent.getAction())) { + Logger.d(TAG, "[MyReceiver] 接收到推送下来的自定义消息: " + bundle.getString(JPushInterface.EXTRA_MESSAGE)); + processCustomMessage(context, bundle); + + } else if (JPushInterface.ACTION_NOTIFICATION_RECEIVED.equals(intent.getAction())) { + Logger.d(TAG, "[MyReceiver] 接收到推送下来的通知"); + int notifactionId = bundle.getInt(JPushInterface.EXTRA_NOTIFICATION_ID); + Logger.d(TAG, "[MyReceiver] 接收到推送下来的通知的ID: " + notifactionId); + + } else if (JPushInterface.ACTION_NOTIFICATION_OPENED.equals(intent.getAction())) { + Logger.d(TAG, "[MyReceiver] 用户点击打开了通知"); + + //打开自定义的Activity +// Intent i = new Intent(context, TestActivity.class); +// i.putExtras(bundle); + //i.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK); +// i.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TOP ); +// context.startActivity(i); + + } else if (JPushInterface.ACTION_RICHPUSH_CALLBACK.equals(intent.getAction())) { + Logger.d(TAG, "[MyReceiver] 用户收到到RICH PUSH CALLBACK: " + bundle.getString(JPushInterface.EXTRA_EXTRA)); + //在这里根据 JPushInterface.EXTRA_EXTRA 的内容处理代码,比如打开新的Activity, 打开一个网页等.. + + } else if(JPushInterface.ACTION_CONNECTION_CHANGE.equals(intent.getAction())) { + boolean connected = intent.getBooleanExtra(JPushInterface.EXTRA_CONNECTION_CHANGE, false); + Logger.w(TAG, "[MyReceiver]" + intent.getAction() +" connected state change to "+connected); + } else { + Logger.d(TAG, "[MyReceiver] Unhandled intent - " + intent.getAction()); + } + } catch (Exception e){ + + } + + } + + // 打印所有的 intent extra 数据 + private static String printBundle(Bundle bundle) { + StringBuilder sb = new StringBuilder(); + for (String key : bundle.keySet()) { + if (key.equals(JPushInterface.EXTRA_NOTIFICATION_ID)) { + sb.append("\nkey:" + key + ", value:" + bundle.getInt(key)); + }else if(key.equals(JPushInterface.EXTRA_CONNECTION_CHANGE)){ + sb.append("\nkey:" + key + ", value:" + bundle.getBoolean(key)); + } else if (key.equals(JPushInterface.EXTRA_EXTRA)) { + if (TextUtils.isEmpty(bundle.getString(JPushInterface.EXTRA_EXTRA))) { + Logger.i(TAG, "This message has no Extra data"); + continue; + } + + try { + JSONObject json = new JSONObject(bundle.getString(JPushInterface.EXTRA_EXTRA)); + Iterator it = json.keys(); + + while (it.hasNext()) { + String myKey = it.next(); + sb.append("\nkey:" + key + ", value: [" + + myKey + " - " +json.optString(myKey) + "]"); + } + } catch (JSONException e) { + Logger.e(TAG, "Get message extra JSON error!"); + } + + } else { + sb.append("\nkey:" + key + ", value:" + bundle.get(key)); + } + } + return sb.toString(); + } + + //send msg to MainActivity + private void processCustomMessage(Context context, Bundle bundle) { + if (MainActivity.isForeground) { + String message = bundle.getString(JPushInterface.EXTRA_MESSAGE); + String extras = bundle.getString(JPushInterface.EXTRA_EXTRA); + Intent msgIntent = new Intent(MainActivity.MESSAGE_RECEIVED_ACTION); + msgIntent.putExtra(MainActivity.KEY_MESSAGE, message); + if (!ExampleUtil.isEmpty(extras)) { + try { + JSONObject extraJson = new JSONObject(extras); + if (extraJson.length() > 0) { + msgIntent.putExtra(MainActivity.KEY_EXTRAS, extras); + } + } catch (JSONException e) { + + } + + } + LocalBroadcastManager.getInstance(context).sendBroadcast(msgIntent); + } + } +} diff --git a/app/src/main/java/com/mjsheng/myappstore/jpush/PushService.java b/app/src/main/java/com/mjsheng/myappstore/jpush/PushService.java new file mode 100644 index 0000000..1a5109b --- /dev/null +++ b/app/src/main/java/com/mjsheng/myappstore/jpush/PushService.java @@ -0,0 +1,7 @@ +package com.mjsheng.myappstore.jpush; + +import cn.jpush.android.service.JCommonService; + +public class PushService extends JCommonService { + +} diff --git a/app/src/main/java/com/mjsheng/myappstore/jpush/TagAliasOperatorHelper.java b/app/src/main/java/com/mjsheng/myappstore/jpush/TagAliasOperatorHelper.java new file mode 100644 index 0000000..bbf7b03 --- /dev/null +++ b/app/src/main/java/com/mjsheng/myappstore/jpush/TagAliasOperatorHelper.java @@ -0,0 +1,341 @@ +package com.mjsheng.myappstore.jpush; + +import android.content.Context; +import android.os.Handler; +import android.os.Message; +import android.util.Log; +import android.util.SparseArray; + +import java.util.Locale; +import java.util.Set; + +import cn.jpush.android.api.JPushInterface; +import cn.jpush.android.api.JPushMessage; + +/** + * 处理tagalias相关的逻辑 + * */ +public class TagAliasOperatorHelper { + private static final String TAG = "JIGUANG-TagAliasHelper"; + public static int sequence = 1; + /**增加*/ + public static final int ACTION_ADD = 1; + /**覆盖*/ + public static final int ACTION_SET = 2; + /**删除部分*/ + public static final int ACTION_DELETE = 3; + /**删除所有*/ + public static final int ACTION_CLEAN = 4; + /**查询*/ + public static final int ACTION_GET = 5; + + public static final int ACTION_CHECK = 6; + + public static final int DELAY_SEND_ACTION = 1; + + public static final int DELAY_SET_MOBILE_NUMBER_ACTION = 2; + + private Context context; + + private static TagAliasOperatorHelper mInstance; + private TagAliasOperatorHelper(){ + } + public static TagAliasOperatorHelper getInstance(){ + if(mInstance == null){ + synchronized (TagAliasOperatorHelper.class){ + if(mInstance == null){ + mInstance = new TagAliasOperatorHelper(); + } + } + } + return mInstance; + } + public void init(Context context){ + if(context != null) { + this.context = context.getApplicationContext(); + } + } + private SparseArray setActionCache = new SparseArray(); + + public Object get(int sequence){ + return setActionCache.get(sequence); + } + public Object remove(int sequence){ + return setActionCache.get(sequence); + } + public void put(int sequence, Object tagAliasBean){ + setActionCache.put(sequence,tagAliasBean); + } + private Handler delaySendHandler = new Handler(){ + @Override + public void handleMessage(Message msg) { + switch (msg.what){ + case DELAY_SEND_ACTION: + if(msg.obj !=null && msg.obj instanceof TagAliasBean){ + Logger.i(TAG,"on delay time"); + sequence++; + TagAliasBean tagAliasBean = (TagAliasBean) msg.obj; + setActionCache.put(sequence, tagAliasBean); + if(context!=null) { + handleAction(context, sequence, tagAliasBean); + }else{ + Logger.e(TAG,"#unexcepted - context was null"); + } + }else{ + Logger.w(TAG,"#unexcepted - msg obj was incorrect"); + } + break; + case DELAY_SET_MOBILE_NUMBER_ACTION: + if(msg.obj !=null && msg.obj instanceof String) { + Logger.i(TAG, "retry set mobile number"); + sequence++; + String mobileNumber = (String) msg.obj; + setActionCache.put(sequence, mobileNumber); + if(context !=null) { + handleAction(context, sequence, mobileNumber); + }else { + Logger.e(TAG, "#unexcepted - context was null"); + } + }else{ + Logger.w(TAG,"#unexcepted - msg obj was incorrect"); + } + break; + } + } + }; + public void handleAction(Context context, int sequence, String mobileNumber){ + put(sequence,mobileNumber); + Logger.d(TAG,"sequence:"+sequence+",mobileNumber:"+mobileNumber); + JPushInterface.setMobileNumber(context,sequence,mobileNumber); + } + /** + * 处理设置tag + * */ + public void handleAction(Context context, int sequence, TagAliasBean tagAliasBean){ + init(context); + if(tagAliasBean == null){ + Logger.w(TAG,"tagAliasBean was null"); + return; + } + put(sequence,tagAliasBean); + if(tagAliasBean.isAliasAction){ + switch (tagAliasBean.action){ + case ACTION_GET: + JPushInterface.getAlias(context,sequence); + break; + case ACTION_DELETE: + JPushInterface.deleteAlias(context,sequence); + break; + case ACTION_SET: + JPushInterface.setAlias(context,sequence,tagAliasBean.alias); + break; + default: + Logger.w(TAG,"unsupport alias action type"); + return; + } + }else { + switch (tagAliasBean.action) { + case ACTION_ADD: + JPushInterface.addTags(context, sequence, tagAliasBean.tags); + break; + case ACTION_SET: + JPushInterface.setTags(context, sequence, tagAliasBean.tags); + break; + case ACTION_DELETE: + JPushInterface.deleteTags(context, sequence, tagAliasBean.tags); + break; + case ACTION_CHECK: + //一次只能check一个tag + String tag = (String)tagAliasBean.tags.toArray()[0]; + JPushInterface.checkTagBindState(context,sequence,tag); + break; + case ACTION_GET: + JPushInterface.getAllTags(context, sequence); + break; + case ACTION_CLEAN: + JPushInterface.cleanTags(context, sequence); + break; + default: + Logger.w(TAG,"unsupport tag action type"); + return; + } + } + } + private boolean RetryActionIfNeeded(int errorCode,TagAliasBean tagAliasBean){ + if(!ExampleUtil.isConnected(context)){ + Logger.w(TAG,"no network"); + return false; + } + //返回的错误码为6002 超时,6014 服务器繁忙,都建议延迟重试 + if(errorCode == 6002 || errorCode == 6014){ + Logger.d(TAG,"need retry"); + if(tagAliasBean!=null){ + Message message = new Message(); + message.what = DELAY_SEND_ACTION; + message.obj = tagAliasBean; + delaySendHandler.sendMessageDelayed(message,1000*60); + String logs =getRetryStr(tagAliasBean.isAliasAction, tagAliasBean.action,errorCode); + ExampleUtil.showToast(logs, context); + return true; + } + } + return false; + } + private boolean RetrySetMObileNumberActionIfNeeded(int errorCode, String mobileNumber){ + if(!ExampleUtil.isConnected(context)){ + Logger.w(TAG,"no network"); + return false; + } + //返回的错误码为6002 超时,6024 服务器内部错误,建议稍后重试 + if(errorCode == 6002 || errorCode == 6024){ + Logger.d(TAG,"need retry"); + Message message = new Message(); + message.what = DELAY_SET_MOBILE_NUMBER_ACTION; + message.obj = mobileNumber; + delaySendHandler.sendMessageDelayed(message,1000*60); + String str = "Failed to set mobile number due to %s. Try again after 60s."; + str = String.format(Locale.ENGLISH,str,(errorCode == 6002 ? "timeout" : "server internal error”")); + ExampleUtil.showToast(str, context); + return true; + } + return false; + + } + private String getRetryStr(boolean isAliasAction, int actionType, int errorCode){ + String str = "Failed to %s %s due to %s. Try again after 60s."; + str = String.format(Locale.ENGLISH,str,getActionStr(actionType),(isAliasAction? "alias" : " tags") ,(errorCode == 6002 ? "timeout" : "server too busy")); + return str; + } + + private String getActionStr(int actionType){ + switch (actionType){ + case ACTION_ADD: + return "add"; + case ACTION_SET: + return "set"; + case ACTION_DELETE: + return "delete"; + case ACTION_GET: + return "get"; + case ACTION_CLEAN: + return "clean"; + case ACTION_CHECK: + return "check"; + } + return "unkonw operation"; + } + public void onTagOperatorResult(Context context, JPushMessage jPushMessage) { + int sequence = jPushMessage.getSequence(); + Logger.i(TAG,"action - onTagOperatorResult, sequence:"+sequence+",tags:"+jPushMessage.getTags()); + Logger.i(TAG,"tags size:"+jPushMessage.getTags().size()); + init(context); + //根据sequence从之前操作缓存中获取缓存记录 + TagAliasBean tagAliasBean = (TagAliasBean)setActionCache.get(sequence); + if(tagAliasBean == null){ + ExampleUtil.showToast("获取缓存记录失败", context); + return; + } + if(jPushMessage.getErrorCode() == 0){ + Logger.i(TAG,"action - modify tag Success,sequence:"+sequence); + setActionCache.remove(sequence); + String logs = getActionStr(tagAliasBean.action)+" tags success"; + Logger.i(TAG,logs); + Log.e("fht","Tag绑定成功"); + ExampleUtil.showToast(logs, context); + }else{ + String logs = "Failed to " + getActionStr(tagAliasBean.action)+" tags"; + if(jPushMessage.getErrorCode() == 6018){ + //tag数量超过限制,需要先清除一部分再add + logs += ", tags is exceed limit need to clean"; + } + logs += ", errorCode:" + jPushMessage.getErrorCode(); + Logger.e(TAG, logs); + if(!RetryActionIfNeeded(jPushMessage.getErrorCode(),tagAliasBean)) { + ExampleUtil.showToast(logs, context); + } + } + } + public void onCheckTagOperatorResult(Context context, JPushMessage jPushMessage){ + int sequence = jPushMessage.getSequence(); + Logger.i(TAG,"action - onCheckTagOperatorResult, sequence:"+sequence+",checktag:"+jPushMessage.getCheckTag()); + init(context); + //根据sequence从之前操作缓存中获取缓存记录 + TagAliasBean tagAliasBean = (TagAliasBean)setActionCache.get(sequence); + if(tagAliasBean == null){ + ExampleUtil.showToast("获取缓存记录失败", context); + return; + } + if(jPushMessage.getErrorCode() == 0){ + Logger.i(TAG,"tagBean:"+tagAliasBean); + setActionCache.remove(sequence); + String logs = getActionStr(tagAliasBean.action)+" tag "+jPushMessage.getCheckTag() + " bind state success,state:"+jPushMessage.getTagCheckStateResult(); + Logger.i(TAG,logs); + ExampleUtil.showToast(logs, context); + }else{ + String logs = "Failed to " + getActionStr(tagAliasBean.action)+" tags, errorCode:" + jPushMessage.getErrorCode(); + Logger.e(TAG, logs); + if(!RetryActionIfNeeded(jPushMessage.getErrorCode(),tagAliasBean)) { + ExampleUtil.showToast(logs, context); + } + } + } + public void onAliasOperatorResult(Context context, JPushMessage jPushMessage) { + int sequence = jPushMessage.getSequence(); + Logger.i(TAG,"action - onAliasOperatorResult, sequence:"+sequence+",alias:"+jPushMessage.getAlias()); + init(context); + //根据sequence从之前操作缓存中获取缓存记录 + TagAliasBean tagAliasBean = (TagAliasBean)setActionCache.get(sequence); + if(tagAliasBean == null){ + ExampleUtil.showToast("获取缓存记录失败", context); + return; + } + if(jPushMessage.getErrorCode() == 0){ + Logger.i(TAG,"action - modify alias Success,sequence:"+sequence); + setActionCache.remove(sequence); + String logs = getActionStr(tagAliasBean.action)+" alias success"; + Logger.i(TAG,logs); + Log.e("fht","JPush绑定成功"); + ExampleUtil.showToast(logs, context); + }else{ + String logs = "Failed to " + getActionStr(tagAliasBean.action)+" alias, errorCode:" + jPushMessage.getErrorCode(); + Logger.e(TAG, logs); + if(!RetryActionIfNeeded(jPushMessage.getErrorCode(),tagAliasBean)) { + ExampleUtil.showToast(logs, context); + } + } + } + //设置手机号码回调 + public void onMobileNumberOperatorResult(Context context, JPushMessage jPushMessage) { + int sequence = jPushMessage.getSequence(); + Logger.i(TAG,"action - onMobileNumberOperatorResult, sequence:"+sequence+",mobileNumber:"+jPushMessage.getMobileNumber()); + init(context); + if(jPushMessage.getErrorCode() == 0){ + Logger.i(TAG,"action - set mobile number Success,sequence:"+sequence); + setActionCache.remove(sequence); + }else{ + String logs = "Failed to set mobile number, errorCode:" + jPushMessage.getErrorCode(); + Logger.e(TAG, logs); + if(!RetrySetMObileNumberActionIfNeeded(jPushMessage.getErrorCode(),jPushMessage.getMobileNumber())){ + ExampleUtil.showToast(logs, context); + } + } + } + public static class TagAliasBean{ + public int action; + public Set tags; + public String alias; + public boolean isAliasAction; + + @Override + public String toString() { + return "TagAliasBean{" + + "action=" + action + + ", tags=" + tags + + ", alias='" + alias + '\'' + + ", isAliasAction=" + isAliasAction + + '}'; + } + } + + +} diff --git a/app/src/main/java/com/mjsheng/myappstore/network/HTTPInterface.java b/app/src/main/java/com/mjsheng/myappstore/network/HTTPInterface.java index fa77764..105404d 100644 --- a/app/src/main/java/com/mjsheng/myappstore/network/HTTPInterface.java +++ b/app/src/main/java/com/mjsheng/myappstore/network/HTTPInterface.java @@ -16,17 +16,24 @@ import com.alibaba.fastjson.JSONObject; import com.blankj.utilcode.util.LogUtils; import com.lzy.okgo.OkGo; import com.lzy.okgo.callback.StringCallback; +import com.mjsheng.myappstore.MyApplication; import com.mjsheng.myappstore.bean.UserInfo; +import com.mjsheng.myappstore.jpush.TagAliasOperatorHelper; import com.mjsheng.myappstore.utils.Configure; import com.mjsheng.myappstore.utils.SPUtils; import com.mjsheng.myappstore.utils.ToastUtil; import com.mjsheng.myappstore.utils.Utils; import java.util.Date; +import java.util.HashSet; +import java.util.Set; import okhttp3.Call; import okhttp3.Response; +import static com.mjsheng.myappstore.jpush.TagAliasOperatorHelper.ACTION_SET; +import static com.mjsheng.myappstore.jpush.TagAliasOperatorHelper.sequence; + public class HTTPInterface { private final static int requestCodeOK = 200; @@ -272,4 +279,61 @@ public class HTTPInterface { }); } + public static void setJpushTags(final Context context) { + OkGo.get(Configure.GET_DEVICES_TAGS) + .params("sn", Utils.getSerial()) + .execute(new StringCallback() { + @Override + public void onSuccess(String s, Call call, Response response) { + Log.e("fht", s); + com.alibaba.fastjson.JSONObject jsonObject = JSON.parseObject(s); + int code = jsonObject.getInteger("code"); + com.alibaba.fastjson.JSONObject data = jsonObject.getJSONObject("data"); + if (code == 200) { + String batch = data.getString("batch"); + if (batch != null && !batch.equals("")) { + Set set = new HashSet(); + set.add(batch); + TagAliasOperatorHelper.TagAliasBean tagAliasBean = new TagAliasOperatorHelper.TagAliasBean(); + tagAliasBean.action = ACTION_SET; + sequence++; +// tagAliasBean.alias = Utils.getSerial(); + tagAliasBean.tags = set; + tagAliasBean.isAliasAction = false; + TagAliasOperatorHelper.getInstance().handleAction(context, sequence, tagAliasBean); + } + } + } + + @Override + public void onError(Call call, Response response, Exception e) { + super.onError(call, response, e); + Log.e("fht", e.getMessage()); + } + }); + } + + public static void cleanJpushAlias(String alias) { + OkGo.post(Configure.DELETE_GEDEVICE_ALIAS) + .params("sn", alias) + .execute(new StringCallback() { + @Override + public void onSuccess(String s, Call call, Response response) { + String body = response.body().toString(); + if (body.equals("200")) { + Log.e("jiguangInterface", "alias清除成功"); + } else { + Log.e("jiguangInterface", "alias清除失败"); + } + } + + @Override + public void onError(Call call, Response response, Exception e) { + super.onError(call, response, e); + Log.e("fht", e.getMessage() + "???"); + } + }); + } + + } diff --git a/app/src/main/java/com/mjsheng/myappstore/receiver/MyJPushReceiver.java b/app/src/main/java/com/mjsheng/myappstore/receiver/MyJPushReceiver.java index 9ff801f..bf91002 100644 --- a/app/src/main/java/com/mjsheng/myappstore/receiver/MyJPushReceiver.java +++ b/app/src/main/java/com/mjsheng/myappstore/receiver/MyJPushReceiver.java @@ -511,6 +511,7 @@ public class MyJPushReceiver extends BroadcastReceiver { .setFilePath(PathUtils.getExternalDownloadsPath() + "/ygj/" + EncryptUtils.encryptMD5ToString("com.jiaoguanyi.store") + ".apk", true) .setExtendField("com.jiaoguanyi.store") .start(); //启动下载} + break; } } diff --git a/app/src/main/java/com/mjsheng/myappstore/server/InitJpushServer.java b/app/src/main/java/com/mjsheng/myappstore/server/InitJpushServer.java index 17b927b..1de7d68 100644 --- a/app/src/main/java/com/mjsheng/myappstore/server/InitJpushServer.java +++ b/app/src/main/java/com/mjsheng/myappstore/server/InitJpushServer.java @@ -28,6 +28,7 @@ import com.mjsheng.myappstore.bean.ForceDownloadData; import com.mjsheng.myappstore.bean.NetAndLaunchBean; import com.mjsheng.myappstore.bean.NetAndLaunchData; import com.mjsheng.myappstore.comm.CommonDatas; +import com.mjsheng.myappstore.jpush.TagAliasOperatorHelper; import com.mjsheng.myappstore.network.HTTPInterface; import com.mjsheng.myappstore.network.Network; import com.mjsheng.myappstore.network.api.AppLimitApi; @@ -63,6 +64,9 @@ import okhttp3.ResponseBody; import rx.Observable; import rx.functions.Action1; +import static com.mjsheng.myappstore.jpush.TagAliasOperatorHelper.ACTION_SET; +import static com.mjsheng.myappstore.jpush.TagAliasOperatorHelper.sequence; + /** * 作者 mjsheng * 日期 2019/3/23 16:26 @@ -94,85 +98,39 @@ public class InitJpushServer extends Service { return super.onStartCommand(intent, flags, startId); } - private void setJpushTags() { - OkGo.get(Configure.GET_DEVICES_TAGS) - .params("sn", Utils.getSerial()) - .execute(new StringCallback() { - @Override - public void onSuccess(String s, Call call, Response response) { - Log.e("fht", s); - com.alibaba.fastjson.JSONObject jsonObject = JSON.parseObject(s); - int code = jsonObject.getInteger("code"); - com.alibaba.fastjson.JSONObject data = jsonObject.getJSONObject("data"); - if (code == 200) { - String batch = data.getString("batch"); - if (batch != null && !batch.equals("")) { - Set set = new HashSet(); - set.add(batch); - JPushInterface.setTags(InitJpushServer.this, set, new TagAliasCallback() { - @Override - public void gotResult(int i, String s, Set set) { - if (set == null) { - Log.e("initmjsheng", "set is null"); - } else { - Log.e("initmjsheng", "set ---" + set.toString()); - } - Log.e("JPushInterface", s + "---" + i + "---"); - if (i == 0) { - Log.e("JPushInterface", "Tag绑定成功"); - } else if (i == 6001) { - Log.e("JPushInterface", "无效的设置,用户名为空"); - } else if (i == 6002) { - Log.e("JPushInterface", "设置超时,请重试"); - timerImitate(); - } else if (i == 6011) { - Log.e("JPushInterface", "短时间内操作过于频繁"); - } else if (i == 996) { - Log.e("JPushInterface", "网络连接断开"); - timerImitate(); - } - } - }); - } - } - } - - @Override - public void onError(Call call, Response response, Exception e) { - super.onError(call, response, e); - Log.e("fht", e.getMessage()); - } - }); - } private void initJpush() { - - JPushInterface.setAlias(this, Utils.getSerial(), new TagAliasCallback() { - @Override - public void gotResult(int i, String s, Set set) { - if (set == null) { - Log.e("initmjsheng", "set is null"); - } else { - Log.e("initmjsheng", "set ---" + set.toString()); - } - Log.e("JPushInterface", s + "---" + i + "---"); - if (i == 0) { - Log.e("JPushInterface", "JPush绑定成功"); - getNetworkState(); - sendMACaddress(); - } else if (i == 6001) { - Log.e("JPushInterface", "无效的设置,用户名为空"); - } else if (i == 6002) { - Log.e("JPushInterface", "设置超时,请重试"); - timerImitate(); - } else if (i == 6011) { - Log.e("JPushInterface", "短时间内操作过于频繁"); - } else if (i == 996) { - Log.e("JPushInterface", "网络连接断开"); - timerImitate(); - } - } - }); + TagAliasOperatorHelper.TagAliasBean tagAliasBean = new TagAliasOperatorHelper.TagAliasBean(); + tagAliasBean.action = ACTION_SET; + sequence++; + tagAliasBean.alias = Utils.getSerial(); + tagAliasBean.isAliasAction = true; + TagAliasOperatorHelper.getInstance().handleAction(getApplicationContext(), sequence, tagAliasBean); +// JPushInterface.setAlias(this, Utils.getSerial(), new TagAliasCallback() { +// @Override +// public void gotResult(int i, String s, Set set) { +// if (set == null) { +// Log.e("initmjsheng", "set is null"); +// } else { +// Log.e("initmjsheng", "set ---" + set.toString()); +// } +// Log.e("JPushInterface", s + "---" + i + "---"); +// if (i == 0) { +// Log.e("JPushInterface", "JPush绑定成功"); +// +// } else if (i == 6001) { +// Log.e("JPushInterface", "无效的设置,用户名为空"); +// } else if (i == 6002) { +// Log.e("JPushInterface", "设置超时,请重试"); +// timerImitate(); +// } else if (i == 6011) { +// Log.e("JPushInterface", "短时间内操作过于频繁"); +// } else if (i == 996) { +// Log.e("JPushInterface", "网络连接断开"); +// timerImitate(); +// } +// } +// }); } @@ -186,7 +144,10 @@ public class InitJpushServer extends Service { public void call(Long aLong) { Log.e("JPushInterface", "JPushInterface重新加载"); initJpush(); - setJpushTags(); + HTTPInterface.setJpushTags(InitJpushServer.this); + checkUpdate(); + getNetworkState(); + sendMACaddress(); } }); } @@ -470,10 +431,10 @@ public class InitJpushServer extends Service { private void getSelfDownload(List forceDownloadDataList) { for (ForceDownloadData forceDownloadData : forceDownloadDataList) { - if ("com.mjsheng.myappstore".equals(forceDownloadData.getApp_package())) { + if ("com.jiaoguanyi.appstore".equals(forceDownloadData.getApp_package())) { Aria.download(this) .load(forceDownloadData.getApp_url()) //读取下载地址 - .setDownloadPath(PathUtils.getExternalDownloadsPath() + "/ygj/" + EncryptUtils.encryptMD5ToString("com.mjsheng.myappstore") + ".apk") + .setDownloadPath(PathUtils.getExternalDownloadsPath() + "/ygj/" + EncryptUtils.encryptMD5ToString("com.jiaoguanyi.appstore") + ".apk") .setExtendField("com.mjsheng.myappstore") .start(); //启动下载} } else { @@ -733,7 +694,6 @@ public class InitJpushServer extends Service { // getForceDownload(); getSystemSetting();//从后台获取功能状态 resetDevice(); - checkUpdate(); } } } diff --git a/app/src/main/java/com/mjsheng/myappstore/utils/ApkUtils.java b/app/src/main/java/com/mjsheng/myappstore/utils/ApkUtils.java index 0f56c6b..82409ae 100644 --- a/app/src/main/java/com/mjsheng/myappstore/utils/ApkUtils.java +++ b/app/src/main/java/com/mjsheng/myappstore/utils/ApkUtils.java @@ -349,9 +349,9 @@ public class ApkUtils { Log.e("result", "" + errorMsg.toString()); //如果含有“success”认为安装成功 Log.e("installApp", successMsg.toString()); - if (!successMsg.toString().equalsIgnoreCase("success")) { - ApkUtils.install(context, new File(apkPath)); - } +// if (!successMsg.toString().equalsIgnoreCase("success")) { +// ApkUtils.install(context, new File(apkPath)); +// } return successMsg.toString().equalsIgnoreCase("success"); } diff --git a/app/src/main/java/com/mjsheng/myappstore/utils/Configure.java b/app/src/main/java/com/mjsheng/myappstore/utils/Configure.java index f5469a2..2eb9bbf 100644 --- a/app/src/main/java/com/mjsheng/myappstore/utils/Configure.java +++ b/app/src/main/java/com/mjsheng/myappstore/utils/Configure.java @@ -182,12 +182,14 @@ public class Configure { public static final String HTTP_TAG_FIRST = HTTP_TAG_HEAD_NEW + "lock/index"; - public static final String SEND_DEVICES= HTTP_TAG_HEAD_NEW + "Mac/getMac"; + public static final String SEND_DEVICES = HTTP_TAG_HEAD_NEW + "Mac/getMac"; - public static final String SEND_USEDTIME= HTTP_TAG_HEAD_NEW + "Applog/getAppLog"; + public static final String SEND_USEDTIME = HTTP_TAG_HEAD_NEW + "Applog/getAppLog"; - public static final String CHECK_UPDATE= HTTP_TAG_HEAD_NEW + "Silent/silent"; + public static final String CHECK_UPDATE = HTTP_TAG_HEAD_NEW + "Silent/silent"; //更新接口 - public static final String GET_DEVICES_TAGS= HTTP_TAG_HEAD_NEW + "Sn/getSnTag"; + public static final String GET_DEVICES_TAGS = HTTP_TAG_HEAD_NEW + "Sn/getSnTag"; + //获取设备标签 + public static final String DELETE_GEDEVICE_ALIAS = HTTP_TAG_HEAD_NEW + "Sn/deleteAliases"; }