diff --git a/.gitignore b/.gitignore index f0c20a1..aac3b37 100644 --- a/.gitignore +++ b/.gitignore @@ -75,3 +75,6 @@ lint/generated/ lint/outputs/ lint/tmp/ # lint/reports/ +/.idea/ +/gradlew.bat +/gradlew diff --git a/app/.gitignore b/app/.gitignore index 42afabf..b1b19de 100644 --- a/app/.gitignore +++ b/app/.gitignore @@ -1 +1,3 @@ -/build \ No newline at end of file +/build +/src/androidTest/java/com/tt/ttutils/ +/src/test/java/com/tt/ttutils/ diff --git a/app/build.gradle b/app/build.gradle index 935c06b..fd9af64 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -2,28 +2,133 @@ apply plugin: 'com.android.application' apply plugin: 'kotlin-android' apply plugin: 'kotlin-android-extensions' +def appName() { + return "TT" +} + +def releaseTime() { + return new Date().format("yyyyMMdd", TimeZone.getDefault()) +} + android { - compileSdkVersion 30 + compileSdkVersion 29 buildToolsVersion "30.0.1" defaultConfig { applicationId "com.tt.ttutils" minSdkVersion 14 - targetSdkVersion 30 - versionCode 1 - versionName "1.0" + targetSdkVersion 29 +// versionCode 1 +// versionName "1.0" + multiDexEnabled true testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" + + ndk { + //选择要添加的对应 cpu 类型的 .so 库。 + abiFilters 'armeabi', 'armeabi-v7a', 'arm64-v8a','x86' + // 还可以添加 'x86', 'x86_64', 'mips', 'mips64' + } + manifestPlaceholders = [ + JPUSH_PKGNAME: applicationId, + JPUSH_APPKEY : "731637f412deca8540a1f873", //JPush 上注册的包名对应的 Appkey. + JPUSH_CHANNEL: "developer-default", //暂时填写默认值即可. + ] + } + + lintOptions { + checkReleaseBuilds false + } + dexOptions { + jumboMode true + } + //多版本 + productFlavors { + official { + flavorDimensions "default" + versionCode 1 + versionName "1.0" + signingConfig signingConfigs.debug + } + + beta { + flavorDimensions "default" + versionCode 1 + versionName "1.0" + signingConfig signingConfigs.debug + buildConfigField "String", "test", '"测试文本"' + } + } + sourceSets { + beta.res.srcDirs = ['src/beta/res'] + } + +//签名 + signingConfigs { + debug { + storeFile file("src/jks/tt.jks") + storePassword "fht19961207" + keyAlias "key0" + keyPassword "981964879aa" + v1SigningEnabled true + v2SigningEnabled false + } + + release { + storeFile file("src/jks/tt.jks") + storePassword "fht19961207" + keyAlias "key0" + keyPassword "981964879aa" + v1SigningEnabled true + v2SigningEnabled false + } } buildTypes { - release { + debug { + // 显示Log + buildConfigField "boolean", "LOG_DEBUG", "true" + versionNameSuffix "-debug" minifyEnabled false - proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro' + //Zipalign优化 + zipAlignEnabled true + signingConfig signingConfigs.debug + applicationVariants.all { variant -> + variant.outputs.each { output -> + def outputFile = output.outputFile + if (outputFile != null) { + def fileName = "${appName()}-${variant.versionCode}-V${variant.versionName}-${releaseTime()}-${buildType.name}.apk" + output.outputFileName = fileName + } + } + } + } + release { + // 不显示Log + buildConfigField "boolean", "LOG_DEBUG", "false" + //混淆 + minifyEnabled false + //Zipalign优化 + zipAlignEnabled true + //前一部分代表系统默认的android程序的混淆文件,该文件已经包含了基本的混淆声明,后一个文件是自己的定义混淆文件 + proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' + //签名 + signingConfig signingConfigs.release +// 将release版本的包名重命名,加上版本及日期 + applicationVariants.all { variant -> + variant.outputs.each { output -> + def outputFile = "" + if (outputFile != null) { + def fileName = "${appName()}-${variant.versionCode}-V${variant.versionName}-${releaseTime()}-${productFlavors[0].name}-${buildType.name}.apk" + output.outputFileName = new File(outputFile, fileName) + } + } + } } } } + dependencies { implementation fileTree(dir: "libs", include: ["*.jar"]) implementation "org.jetbrains.kotlin:kotlin-stdlib:$kotlin_version" @@ -33,5 +138,40 @@ dependencies { testImplementation 'junit:junit:4.12' androidTestImplementation 'androidx.test.ext:junit:1.1.1' androidTestImplementation 'androidx.test.espresso:espresso-core:3.2.0' + ////三方 + //极光推送 + implementation 'cn.jiguang.sdk:jpush:3.7.0' // 此处以JPush 3.7.0 版本为例。 + implementation 'cn.jiguang.sdk:jcore:2.4.2' // 此处以JCore 2.4.2 版本为例。 + //okhttp + implementation 'com.squareup.okhttp3:okhttp:4.6.0' + //RxJava和Retrofit + implementation 'io.reactivex.rxjava2:rxjava:2.2.5' + implementation 'io.reactivex.rxjava2:rxandroid:2.1.0' + implementation 'com.squareup.retrofit2:retrofit:2.3.0' + implementation 'com.squareup.retrofit2:converter-gson:2.3.0' + implementation 'com.squareup.retrofit2:adapter-rxjava2:2.3.0' + ////json解析 + //Gson + implementation 'com.google.code.gson:gson:2.8.6' + //Jackson + implementation 'org.codehaus.jackson:jackson-mapper-asl:1.9.13' + implementation 'org.codehaus.jackson:jackson-core-asl:1.9.13' + //二维码 + implementation 'com.google.zxing:core:3.3.0' + + //个人 + //更换字体框架 + implementation 'uk.co.chrisjenx:calligraphy:2.3.0' + ////图片加载框架 + //Glide + implementation 'com.github.bumptech.glide:glide:4.11.0' + annotationProcessor 'com.github.bumptech.glide:compiler:4.11.0' + //Fresco + implementation 'com.facebook.fresco:fresco:2.2.0' + //Picasso + implementation 'com.squareup.picasso:picasso:2.71828' + //屏幕适配方案 + //https://github.com/JessYanCoding/AndroidAutoSize + implementation 'me.jessyan:autosize:1.2.1' } \ No newline at end of file diff --git a/app/proguard-rules.pro b/app/proguard-rules.pro new file mode 100644 index 0000000..481bb43 --- /dev/null +++ b/app/proguard-rules.pro @@ -0,0 +1,21 @@ +# Add project specific ProGuard rules here. +# You can control the set of applied configuration files using the +# proguardFiles setting in build.gradle. +# +# For more details, see +# http://developer.android.com/guide/developing/tools/proguard.html + +# If your project uses WebView with JS, uncomment the following +# and specify the fully qualified class name to the JavaScript interface +# class: +#-keepclassmembers class fqcn.of.javascript.interface.for.webview { +# public *; +#} + +# Uncomment this to preserve the line number information for +# debugging stack traces. +#-keepattributes SourceFile,LineNumberTable + +# If you keep the line number information, uncomment this to +# hide the original source file name. +#-renamesourcefileattribute SourceFile \ No newline at end of file diff --git a/app/src/jks/tt.jks b/app/src/jks/tt.jks new file mode 100644 index 0000000..34e26b4 Binary files /dev/null and b/app/src/jks/tt.jks differ diff --git a/app/src/jks/xueshibaoos.jks b/app/src/jks/xueshibaoos.jks new file mode 100644 index 0000000..b94a626 Binary files /dev/null and b/app/src/jks/xueshibaoos.jks differ diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index 87955bf..97f5b0f 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -1,9 +1,53 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/java/com/tt/MyApplication.kt b/app/src/main/java/com/tt/MyApplication.kt deleted file mode 100644 index 9d129d9..0000000 --- a/app/src/main/java/com/tt/MyApplication.kt +++ /dev/null @@ -1,13 +0,0 @@ -package com.tt - -import android.app.Application -import com.tt.ttutils.java.ToastUtil - -class MyApplication : Application() { - override fun onCreate() { - super.onCreate() - ToastUtil.init(this) - } - - -} \ No newline at end of file diff --git a/app/src/main/java/com/tt/activity/JMainActivity.java b/app/src/main/java/com/tt/activity/JMainActivity.java new file mode 100644 index 0000000..cf01cd7 --- /dev/null +++ b/app/src/main/java/com/tt/activity/JMainActivity.java @@ -0,0 +1,22 @@ +package com.tt.activity; + +import com.tt.base.BaseActivity; +import com.tt.ttutils.R; + +public class JMainActivity extends BaseActivity { + + @Override + protected int setLayoutResourceID() { + return R.layout.activity_main; + } + + @Override + protected void initView() { + + } + + @Override + protected void initData() { + + } +} diff --git a/app/src/main/java/com/tt/activity/MainActivity.kt b/app/src/main/java/com/tt/activity/MainActivity.kt index 66ac0f8..3ea535d 100644 --- a/app/src/main/java/com/tt/activity/MainActivity.kt +++ b/app/src/main/java/com/tt/activity/MainActivity.kt @@ -1,16 +1,22 @@ package com.tt.activity -import androidx.appcompat.app.AppCompatActivity import android.os.Bundle +import android.util.Log +import androidx.appcompat.app.AppCompatActivity import com.tt.ttutils.R import com.tt.ttutils.java.CmdUtil +import com.tt.ttutils.java.DevicesUtils +import kotlinx.android.synthetic.main.activity_main.* +import me.jessyan.autosize.internal.CancelAdapt -class MainActivity : AppCompatActivity() { +class MainActivity : AppCompatActivity(), CancelAdapt { override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContentView(R.layout.activity_main) //截图 - CmdUtil.execute(" screencap -p /sdcard/" + "screen" + System.currentTimeMillis() + ".png"); - + CmdUtil.execute(" screencap -p /sdcard/" + "screen" + System.currentTimeMillis() + ".png") + textView.setText(DevicesUtils.getSerial()) } + + } \ No newline at end of file diff --git a/app/src/main/java/com/tt/base/BaseActivity.java b/app/src/main/java/com/tt/base/BaseActivity.java new file mode 100644 index 0000000..db869c5 --- /dev/null +++ b/app/src/main/java/com/tt/base/BaseActivity.java @@ -0,0 +1,131 @@ +package com.tt.base; + +import android.os.Build; +import android.os.Bundle; + + +import android.os.Handler; +import android.view.View; +import android.view.Window; +import android.view.WindowManager; + +import androidx.annotation.Nullable; +import androidx.appcompat.app.AppCompatActivity; + + +public abstract class BaseActivity extends AppCompatActivity { + private static Handler sHandler; + + @Override + protected void onCreate(@Nullable Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + requestWindowFeature(Window.FEATURE_NO_TITLE); + setContentView(setLayoutResourceID()); + getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN, WindowManager.LayoutParams.FLAG_FULLSCREEN); + sHandler = new Handler(); + sHandler.post(mHideRunnable); // hide the navigation bar + final View decorView = getWindow().getDecorView(); + decorView.setOnSystemUiVisibilityChangeListener(new View.OnSystemUiVisibilityChangeListener() { + @Override + public void onSystemUiVisibilityChange(int visibility) { + if (visibility == View.SYSTEM_UI_FLAG_VISIBLE) { + sHandler.postDelayed(mHideRunnable, 3000); // hide the navigation bar + } + } + }); + + initView(); + initData(); + setListener(); + + } + + + protected abstract int setLayoutResourceID(); + + protected abstract void initView(); + + + protected void setListener() { + } + + + protected abstract void initData(); + + @Override + public void onWindowFocusChanged(boolean hasFocus) { + super.onWindowFocusChanged(hasFocus); + if (hasFocus) { +// initViewFull(this); + } + } + +// public static void initViewFull(final Activity activity) { +// activity.getWindow().getDecorView().setOnSystemUiVisibilityChangeListener(new View.OnSystemUiVisibilityChangeListener() { +// @Override +// public void onSystemUiVisibilityChange(int visibility) { +// new Thread() { +// @Override +// public void run() { +// super.run(); +// try { +// Thread.sleep(3000); +// } catch (InterruptedException e) { +// e.printStackTrace(); +// } +// activity.runOnUiThread(new Runnable() { +// @Override +// public void run() { +// initViewFull(activity); +// +// } +// }); +// } +// }.start(); +// } +// }); +// // //设置无标题 +// activity.getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN, +// WindowManager.LayoutParams.FLAG_FULLSCREEN); +// activity.getWindow().getDecorView().setSystemUiVisibility( +// View.SYSTEM_UI_FLAG_LAYOUT_STABLE +// | View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION +// | View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN +// | View.SYSTEM_UI_FLAG_HIDE_NAVIGATION // hide nav bar +// | View.SYSTEM_UI_FLAG_FULLSCREEN // hide status bar +// | View.SYSTEM_UI_FLAG_IMMERSIVE); +// } + + Runnable mHideRunnable = new Runnable() { + @Override + public void run() { + int flags; + int curApiVersion = Build.VERSION.SDK_INT; + // This work only for android 4.4+ + if (curApiVersion >= Build.VERSION_CODES.KITKAT) { + // This work only for android 4.4+ + // hide navigation bar permanently in android activity + // touch the screen, the navigation bar will not show + flags = +// View.SYSTEM_UI_FLAG_HIDE_NAVIGATION +// | View.SYSTEM_UI_FLAG_IMMERSIVE +// | View.SYSTEM_UI_FLAG_FULLSCREEN; + View.SYSTEM_UI_FLAG_LAYOUT_STABLE + | View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION + | View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN + | View.SYSTEM_UI_FLAG_HIDE_NAVIGATION // hide nav bar + | View.SYSTEM_UI_FLAG_FULLSCREEN // hide status bar + | View.SYSTEM_UI_FLAG_IMMERSIVE; + getWindow().addFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS); + getWindow().addFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_NAVIGATION); + } else { + // touch the screen, the navigation bar will show + flags = View.SYSTEM_UI_FLAG_HIDE_NAVIGATION; + } + // must be executed in main thread + + getWindow().getDecorView().setSystemUiVisibility(flags); + } + }; + +} diff --git a/app/src/main/java/com/tt/base/JMyApplication.java b/app/src/main/java/com/tt/base/JMyApplication.java new file mode 100644 index 0000000..ba30f39 --- /dev/null +++ b/app/src/main/java/com/tt/base/JMyApplication.java @@ -0,0 +1,45 @@ +package com.tt.base; + +import android.app.Application; +import android.os.Handler; +import android.os.Looper; +import android.util.Log; + +import com.tt.ttutils.BuildConfig; + +public class JMyApplication extends Application { + @Override + public void onCreate() { + super.onCreate(); + if (!BuildConfig.DEBUG) { + catchException(); + } + } + private void catchException() { + Thread.setDefaultUncaughtExceptionHandler( + new Thread.UncaughtExceptionHandler() { + @Override + public void uncaughtException(Thread t, Throwable e) { + Log.d("捕获异常子线程:", Thread.currentThread().getName() + + "在:" + e.getStackTrace()[0].getClassName()); + } + } + ); + //下面是新增方法! + new Handler(Looper.getMainLooper()).post(new Runnable() { + @Override + public void run() { + while (true) { + try { + Looper.loop(); //会先执行这个方法,然后在执行下面的异常捕获方法! + } catch (Exception e) { + Log.d("捕获异常主线程:", Thread.currentThread().getName() + "在:" + e.getStackTrace()[0].getClassName()); + e.printStackTrace(); + } + } + } + }); + } + + +} diff --git a/app/src/main/java/com/tt/base/MyApplication.kt b/app/src/main/java/com/tt/base/MyApplication.kt new file mode 100644 index 0000000..5dad1b7 --- /dev/null +++ b/app/src/main/java/com/tt/base/MyApplication.kt @@ -0,0 +1,47 @@ +package com.tt.base + +import android.app.Application +import android.os.Handler +import android.os.Looper +import android.util.Log +import cn.jpush.android.api.JPushInterface +import com.tt.ttutils.BuildConfig +import com.tt.ttutils.java.ToastUtil + + +class MyApplication : Application() { + private val debug = BuildConfig.DEBUG; + override fun onCreate() { + super.onCreate() + ToastUtil.init(this) + JPushInterface.setDebugMode(debug) // 设置开启日志,发布时请关闭日志 + JPushInterface.init(this) // 初始化 JPush + if (!BuildConfig.DEBUG) { + catchException(); + } + + } + private fun catchException() { + Thread.setDefaultUncaughtExceptionHandler { t, e -> + Log.d( + "捕获异常子线程:", Thread.currentThread().name + + "在:" + e.stackTrace[0].className + ) + } + //下面是新增方法! + Handler(Looper.getMainLooper()).post(Runnable { + while (true) { + try { + Looper.loop() //会先执行这个方法,然后在执行下面的异常捕获方法! + } catch (e: Exception) { + Log.d( + "捕获异常主线程:", + Thread.currentThread().name + "在:" + e.stackTrace[0].className + ) + e.printStackTrace() + } + } + }) + } + +} \ No newline at end of file diff --git a/app/src/main/java/com/tt/sdk/jpush/jpushdemo/ExampleUtil.java b/app/src/main/java/com/tt/sdk/jpush/jpushdemo/ExampleUtil.java new file mode 100644 index 0000000..75fb5e7 --- /dev/null +++ b/app/src/main/java/com/tt/sdk/jpush/jpushdemo/ExampleUtil.java @@ -0,0 +1,133 @@ +package com.tt.sdk.jpush.jpushdemo; + +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 android.widget.Toast; + +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/tt/sdk/jpush/jpushdemo/LocalBroadcastManager.java b/app/src/main/java/com/tt/sdk/jpush/jpushdemo/LocalBroadcastManager.java new file mode 100644 index 0000000..c42beb3 --- /dev/null +++ b/app/src/main/java/com/tt/sdk/jpush/jpushdemo/LocalBroadcastManager.java @@ -0,0 +1,263 @@ +package com.tt.sdk.jpush.jpushdemo; + +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/tt/sdk/jpush/jpushdemo/Logger.java b/app/src/main/java/com/tt/sdk/jpush/jpushdemo/Logger.java new file mode 100644 index 0000000..d188b5a --- /dev/null +++ b/app/src/main/java/com/tt/sdk/jpush/jpushdemo/Logger.java @@ -0,0 +1,42 @@ +package com.tt.sdk.jpush.jpushdemo; + +import android.util.Log; + +import com.tt.ttutils.BuildConfig; + +/** + * Created by efan on 2017/4/13. + */ + +public class Logger { + + //设为false关闭日志 + private static final boolean LOG_ENABLE = BuildConfig.DEBUG; + + 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/tt/sdk/jpush/jpushdemo/MyReceiver.java b/app/src/main/java/com/tt/sdk/jpush/jpushdemo/MyReceiver.java new file mode 100644 index 0000000..3b86573 --- /dev/null +++ b/app/src/main/java/com/tt/sdk/jpush/jpushdemo/MyReceiver.java @@ -0,0 +1,123 @@ +package com.tt.sdk.jpush.jpushdemo; + +import android.content.BroadcastReceiver; +import android.content.Context; +import android.content.Intent; +import android.os.Bundle; +import android.text.TextUtils; + +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_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/tt/sdk/jpush/jpushdemo/PushMessageReceiver.java b/app/src/main/java/com/tt/sdk/jpush/jpushdemo/PushMessageReceiver.java new file mode 100644 index 0000000..1faaefe --- /dev/null +++ b/app/src/main/java/com/tt/sdk/jpush/jpushdemo/PushMessageReceiver.java @@ -0,0 +1,140 @@ +package com.tt.sdk.jpush.jpushdemo; + +import android.content.Context; +import android.content.Intent; +import android.os.Bundle; +import android.util.Log; + +import org.json.JSONException; +import org.json.JSONObject; + +import cn.jpush.android.api.CmdMessage; +import cn.jpush.android.api.CustomMessage; +import cn.jpush.android.api.JPushInterface; +import cn.jpush.android.api.JPushMessage; +import cn.jpush.android.api.NotificationMessage; +import cn.jpush.android.service.JPushMessageReceiver; + +public class PushMessageReceiver extends JPushMessageReceiver{ + private static final String TAG = "PushMessageReceiver"; + @Override + public void onMessage(Context context, CustomMessage customMessage) { + Log.e(TAG,"[onMessage] "+customMessage); +// processCustomMessage(context,customMessage); + } + + @Override + public void onNotifyMessageOpened(Context context, NotificationMessage message) { + Log.e(TAG,"[onNotifyMessageOpened] "+message); + try{ + //打开自定义的Activity + Intent i = new Intent(context, TestActivity.class); + Bundle bundle = new Bundle(); + bundle.putString(JPushInterface.EXTRA_NOTIFICATION_TITLE,message.notificationTitle); + bundle.putString(JPushInterface.EXTRA_ALERT,message.notificationContent); + 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); + }catch (Throwable throwable){ + + } + } + + @Override + public void onMultiActionClicked(Context context, Intent intent) { + Log.e(TAG, "[onMultiActionClicked] 用户点击了通知栏按钮"); + String nActionExtra = intent.getExtras().getString(JPushInterface.EXTRA_NOTIFICATION_ACTION_EXTRA); + + //开发者根据不同 Action 携带的 extra 字段来分配不同的动作。 + if(nActionExtra==null){ + Log.d(TAG,"ACTION_NOTIFICATION_CLICK_ACTION nActionExtra is null"); + return; + } + if (nActionExtra.equals("my_extra1")) { + Log.e(TAG, "[onMultiActionClicked] 用户点击通知栏按钮一"); + } else if (nActionExtra.equals("my_extra2")) { + Log.e(TAG, "[onMultiActionClicked] 用户点击通知栏按钮二"); + } else if (nActionExtra.equals("my_extra3")) { + Log.e(TAG, "[onMultiActionClicked] 用户点击通知栏按钮三"); + } else { + Log.e(TAG, "[onMultiActionClicked] 用户点击通知栏按钮未定义"); + } + } + + @Override + public void onNotifyMessageArrived(Context context, NotificationMessage message) { + Log.e(TAG,"[onNotifyMessageArrived] "+message); + } + + @Override + public void onNotifyMessageDismiss(Context context, NotificationMessage message) { + Log.e(TAG,"[onNotifyMessageDismiss] "+message); + } + + @Override + public void onRegister(Context context, String registrationId) { + Log.e(TAG,"[onRegister] "+registrationId); + } + + @Override + public void onConnected(Context context, boolean isConnected) { + Log.e(TAG,"[onConnected] "+isConnected); + } + + @Override + public void onCommandResult(Context context, CmdMessage cmdMessage) { + Log.e(TAG,"[onCommandResult] "+cmdMessage); + } + + @Override + public void onTagOperatorResult(Context context,JPushMessage jPushMessage) { + TagAliasOperatorHelper.getInstance().onTagOperatorResult(context,jPushMessage); + super.onTagOperatorResult(context, 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); + } + + @Override + public void onMobileNumberOperatorResult(Context context, JPushMessage jPushMessage) { + TagAliasOperatorHelper.getInstance().onMobileNumberOperatorResult(context,jPushMessage); + super.onMobileNumberOperatorResult(context, jPushMessage); + } + + //send msg to MainActivity +// private void processCustomMessage(Context context, CustomMessage customMessage) { +// if (MainActivity.isForeground) { +// String message = customMessage.message; +// String extras = customMessage.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); +// } +// } + + @Override + public void onNotificationSettingsCheck(Context context, boolean isOn, int source) { + super.onNotificationSettingsCheck(context, isOn, source); + Log.e(TAG,"[onNotificationSettingsCheck] isOn:"+isOn+",source:"+source); + } + +} diff --git a/app/src/main/java/com/tt/sdk/jpush/jpushdemo/PushService.java b/app/src/main/java/com/tt/sdk/jpush/jpushdemo/PushService.java new file mode 100644 index 0000000..f6116b2 --- /dev/null +++ b/app/src/main/java/com/tt/sdk/jpush/jpushdemo/PushService.java @@ -0,0 +1,8 @@ +package com.tt.sdk.jpush.jpushdemo; + + +import cn.jpush.android.service.JCommonService; + +public class PushService extends JCommonService { + +} diff --git a/app/src/main/java/com/tt/sdk/jpush/jpushdemo/TagAliasOperatorHelper.java b/app/src/main/java/com/tt/sdk/jpush/jpushdemo/TagAliasOperatorHelper.java new file mode 100644 index 0000000..8485a56 --- /dev/null +++ b/app/src/main/java/com/tt/sdk/jpush/jpushdemo/TagAliasOperatorHelper.java @@ -0,0 +1,338 @@ +package com.tt.sdk.jpush.jpushdemo; + +import android.content.Context; +import android.os.Handler; +import android.os.Message; +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); + 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); + 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{ + int action; + Set tags; + String alias; + boolean isAliasAction; + + @Override + public String toString() { + return "TagAliasBean{" + + "action=" + action + + ", tags=" + tags + + ", alias='" + alias + '\'' + + ", isAliasAction=" + isAliasAction + + '}'; + } + } + + +} diff --git a/app/src/main/java/com/tt/sdk/jpush/jpushdemo/TestActivity.java b/app/src/main/java/com/tt/sdk/jpush/jpushdemo/TestActivity.java new file mode 100644 index 0000000..75d2590 --- /dev/null +++ b/app/src/main/java/com/tt/sdk/jpush/jpushdemo/TestActivity.java @@ -0,0 +1,32 @@ +package com.tt.sdk.jpush.jpushdemo; + +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/tt/ttutils/java/DevicesUtils.java b/app/src/main/java/com/tt/ttutils/java/DevicesUtils.java new file mode 100644 index 0000000..fbf0120 --- /dev/null +++ b/app/src/main/java/com/tt/ttutils/java/DevicesUtils.java @@ -0,0 +1,45 @@ +package com.tt.ttutils.java; + +import android.annotation.SuppressLint; +import android.os.Build; +import android.util.Log; + +import java.lang.reflect.Method; + +public class DevicesUtils { + /** + * 获取设备序列号 + */ + public static String getSerial() { + String serial = "unknow"; + try { + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) {//9.0+ + serial = Build.getSerial(); + } else if (Build.VERSION.SDK_INT > Build.VERSION_CODES.N) {//8.0+ + serial = Build.SERIAL; + } else {//8.0- + Class c = Class.forName("android.os.SystemProperties"); + Method get = c.getMethod("get", String.class); + serial = (String) get.invoke(c, "ro.serialno"); + } + } catch (Exception e) { + e.printStackTrace(); + Log.e("e", "读取设备序列号异常:" + e.toString()); + } + return serial; + } + + public static String getDeviceSN() { + String serial = null; + try { + Class c = Class.forName("android.os.SystemProperties"); + Method get = c.getMethod("get", String.class); + serial = (String) get.invoke(c, "persist.sys.hrSerial"); + } catch (Exception e) { + e.printStackTrace(); + } + return serial; + } + + +} diff --git a/app/src/main/java/com/tt/ttutils/java/ToastUtil.java b/app/src/main/java/com/tt/ttutils/java/ToastUtil.java index 77ad1be..4f90b61 100644 --- a/app/src/main/java/com/tt/ttutils/java/ToastUtil.java +++ b/app/src/main/java/com/tt/ttutils/java/ToastUtil.java @@ -25,7 +25,6 @@ public class ToastUtil { mContext = context; toast = Toast.makeText(mContext, "", Toast.LENGTH_SHORT); debugToast = Toast.makeText(mContext, "", Toast.LENGTH_SHORT); - } private static long time1 = 0L; diff --git a/app/src/main/java/com/tt/ttutils/kt/ToastUtil.kt b/app/src/main/java/com/tt/ttutils/kt/ToastUtil.kt new file mode 100644 index 0000000..b654ca0 --- /dev/null +++ b/app/src/main/java/com/tt/ttutils/kt/ToastUtil.kt @@ -0,0 +1,7 @@ +package com.tt.ttutils.kt + +import java.util.logging.Handler + +class ToastUtil { + +} \ No newline at end of file diff --git a/app/src/main/jni/getSn.cpp b/app/src/main/jni/getSn.cpp new file mode 100644 index 0000000..009de25 --- /dev/null +++ b/app/src/main/jni/getSn.cpp @@ -0,0 +1,18 @@ +// +// Created by Administrator on 2020/8/21. +// +#include + + + //读取序号 + __system_property_get("ro.serialno",m_szDevID); + LOGE("%s", m_szDevID); + + //读取机型 + __system_property_get("ro.product.model",m_szDevModel); + LOGE("%s", m_szDevName); + + //读取sdk版本 + __system_property_get("ro.build.version.sdk", m_szSdkVer); + LOGE("%s",m_szSdkVer); + diff --git a/app/src/main/res/layout-land/activity_main.xml b/app/src/main/res/layout-land/activity_main.xml index 4500292..cef4901 100644 --- a/app/src/main/res/layout-land/activity_main.xml +++ b/app/src/main/res/layout-land/activity_main.xml @@ -4,9 +4,10 @@ xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" - tools:context="com.tt.activity.MainActivity"> + tools:context="com.tt.activity.JMainActivity"> + tools:context="com.tt.activity.JMainActivity">