@@ -3,17 +3,31 @@ package cn.org.bjca.trust.pushdemo | |||||
import android.os.Bundle | import android.os.Bundle | ||||
import android.widget.TextView | import android.widget.TextView | ||||
import androidx.appcompat.app.AppCompatActivity | import androidx.appcompat.app.AppCompatActivity | ||||
import androidx.lifecycle.lifecycleScope | |||||
import cn.org.bjca.trust.push.PushSdk | import cn.org.bjca.trust.push.PushSdk | ||||
import cn.org.bjca.trust.push.common.FileHelper | |||||
import cn.org.bjca.trust.push.api.PushService | |||||
import cn.org.bjca.trust.push.common.LogHelper | |||||
import cn.org.bjca.trust.push.common.SendMessageHelper | import cn.org.bjca.trust.push.common.SendMessageHelper | ||||
import cn.org.bjca.trust.push.di.manager.HttpManager | |||||
import com.xuqm.base.extensions.http | |||||
class MainActivity : AppCompatActivity() { | class MainActivity : AppCompatActivity() { | ||||
override fun onCreate(savedInstanceState: Bundle?) { | override fun onCreate(savedInstanceState: Bundle?) { | ||||
super.onCreate(savedInstanceState) | super.onCreate(savedInstanceState) | ||||
setContentView(R.layout.activity_main) | setContentView(R.layout.activity_main) | ||||
PushSdk.instance.register("xuqinmin") | PushSdk.instance.register("xuqinmin") | ||||
findViewById<TextView>(R.id.register).setOnClickListener { | findViewById<TextView>(R.id.register).setOnClickListener { | ||||
FileHelper.openFile() | |||||
lifecycleScope.http( | |||||
request = { | |||||
HttpManager.getApi( | |||||
HttpManager.getAppComponent("http://192.168.115.173:8080"), | |||||
PushService::class.java | |||||
) | |||||
.getArticle(231231) | |||||
}, | |||||
resp = { LogHelper.d(it) } | |||||
) | |||||
} | } | ||||
findViewById<TextView>(R.id.send).setOnClickListener { | findViewById<TextView>(R.id.send).setOnClickListener { | ||||
SendMessageHelper.sendTextMessage("xuqinmin", "你好啊${System.currentTimeMillis()}") | SendMessageHelper.sendTextMessage("xuqinmin", "你好啊${System.currentTimeMillis()}") | ||||
@@ -74,8 +74,23 @@ dependencies { | |||||
implementation 'org.eclipse.paho:org.eclipse.paho.client.mqttv3:1.2.5' | implementation 'org.eclipse.paho:org.eclipse.paho.client.mqttv3:1.2.5' | ||||
implementation 'org.eclipse.paho:org.eclipse.paho.android.service:1.1.1' | implementation 'org.eclipse.paho:org.eclipse.paho.android.service:1.1.1' | ||||
//网络请求 | |||||
implementation 'com.squareup.retrofit2:retrofit:2.9.0' | |||||
implementation 'com.squareup.retrofit2:converter-gson:2.9.0' | |||||
api 'com.squareup.okhttp3:logging-interceptor:4.9.1' | |||||
implementation 'com.github.franmontiel:PersistentCookieJar:v1.0.1' | |||||
//Dagger | |||||
implementation 'com.google.dagger:hilt-android:2.40.5' | |||||
kapt 'com.google.dagger:hilt-android-compiler:2.40.5' | |||||
//Coroutine | |||||
api "org.jetbrains.kotlinx:kotlinx-coroutines-android:1.6.4" | |||||
api "org.jetbrains.kotlinx:kotlinx-coroutines-core:1.6.4" | |||||
api "androidx.lifecycle:lifecycle-runtime-ktx:2.5.0-alpha05" | |||||
//gson | //gson | ||||
implementation 'com.google.code.gson:gson:2.9.0' | |||||
api 'com.google.code.gson:gson:2.9.0' | |||||
// 小米推送 | // 小米推送 | ||||
// implementation (name: 'MiPush_SDK_Client_5_3_0-C_3rd', ext: 'aar') | // implementation (name: 'MiPush_SDK_Client_5_3_0-C_3rd', ext: 'aar') | ||||
@@ -0,0 +1,40 @@ | |||||
package cn.org.bjca.trust.push.api; | |||||
public class HttpResult<T> { | |||||
private String status; | |||||
private String msg; | |||||
private T data; | |||||
public String getStatus() { | |||||
return status; | |||||
} | |||||
public void setStatus(String status) { | |||||
this.status = status; | |||||
} | |||||
public T getData() { | |||||
return data; | |||||
} | |||||
public void setData(T data) { | |||||
this.data = data; | |||||
} | |||||
public String getMsg() { | |||||
return msg; | |||||
} | |||||
public void setMsg(String msg) { | |||||
this.msg = msg; | |||||
} | |||||
@Override | |||||
public String toString() { | |||||
return "HttpResult{" + | |||||
"status='" + status + '\'' + | |||||
", msg='" + msg + '\'' + | |||||
", data=" + data + | |||||
'}'; | |||||
} | |||||
} |
@@ -0,0 +1,9 @@ | |||||
package cn.org.bjca.trust.push.api | |||||
import retrofit2.http.GET | |||||
import retrofit2.http.Path | |||||
interface PushService { | |||||
@GET("hello/{id}") | |||||
suspend fun getArticle(@Path("id") id: Int): HttpResult<String> | |||||
} |
@@ -10,27 +10,27 @@ object LogHelper { | |||||
* e | * e | ||||
*/ | */ | ||||
@JvmStatic | @JvmStatic | ||||
fun e(message: String) { | |||||
fun e(message: Any?) { | |||||
e(message, null, null) | e(message, null, null) | ||||
} | } | ||||
@JvmStatic | @JvmStatic | ||||
fun e(message: String, tag: String) { | |||||
fun e(message: Any?, tag: String) { | |||||
e(message, null, tag) | e(message, null, tag) | ||||
} | } | ||||
@JvmStatic | @JvmStatic | ||||
fun e(message: String, tr: Throwable) { | |||||
fun e(message: Any?, tr: Throwable) { | |||||
e(message, tr, null) | e(message, tr, null) | ||||
} | } | ||||
@JvmStatic | @JvmStatic | ||||
fun e(message: String, tr: Throwable?, tag: String?) { | |||||
println(tr, tag) { | |||||
fun e(message: Any?, tr: Throwable?, tag: String?) { | |||||
println(tag, tr) { | |||||
if (tr != null) { | if (tr != null) { | ||||
Log.e(TAG, message, tr) | |||||
Log.e(TAG, CommonHelper.anyToString(message), tr) | |||||
} else { | } else { | ||||
Log.e(TAG, message) | |||||
Log.e(TAG, CommonHelper.anyToString(message)) | |||||
} | } | ||||
} | } | ||||
} | } | ||||
@@ -39,32 +39,32 @@ object LogHelper { | |||||
* d | * d | ||||
*/ | */ | ||||
@JvmStatic | @JvmStatic | ||||
fun d(message: String) { | |||||
fun d(message: Any?) { | |||||
d(message, null, null) | d(message, null, null) | ||||
} | } | ||||
@JvmStatic | @JvmStatic | ||||
fun d(message: String, tag: String) { | |||||
fun d(message: Any?, tag: String) { | |||||
d(message, null, tag) | d(message, null, tag) | ||||
} | } | ||||
@JvmStatic | @JvmStatic | ||||
fun d(message: String, tr: Throwable) { | |||||
fun d(message: Any?, tr: Throwable) { | |||||
d(message, tr, null) | d(message, tr, null) | ||||
} | } | ||||
@JvmStatic | @JvmStatic | ||||
fun d(message: String, tr: Throwable?, tag: String?) { | |||||
println(tr, tag) { | |||||
fun d(message: Any?, tr: Throwable?, tag: String?) { | |||||
println(tag, tr) { | |||||
if (tr != null) { | if (tr != null) { | ||||
Log.d(TAG, message, tr) | |||||
Log.d(TAG, CommonHelper.anyToString(message), tr) | |||||
} else { | } else { | ||||
Log.d(TAG, message) | |||||
Log.d(TAG, CommonHelper.anyToString(message)) | |||||
} | } | ||||
} | } | ||||
} | } | ||||
private fun println(tr: Throwable?, tag: String?, log: () -> Unit) { | |||||
private fun println(tag: String?, tr: Throwable?, log: () -> Unit) { | |||||
if (!showLog) return | if (!showLog) return | ||||
Log.d( | Log.d( | ||||
TAG, "" | TAG, "" | ||||
@@ -6,6 +6,7 @@ import cn.org.bjca.trust.push.message.ImManager | |||||
import cn.org.bjca.trust.push.message.bean.* | import cn.org.bjca.trust.push.message.bean.* | ||||
import cn.org.bjca.trust.push.message.msg.Message | import cn.org.bjca.trust.push.message.msg.Message | ||||
import cn.org.bjca.trust.push.message.msg.SendMessage | import cn.org.bjca.trust.push.message.msg.SendMessage | ||||
import java.io.File | |||||
object SendMessageHelper { | object SendMessageHelper { | ||||
private fun sendMessage(message: Message) { | private fun sendMessage(message: Message) { | ||||
@@ -30,6 +31,13 @@ object SendMessageHelper { | |||||
@JvmStatic | @JvmStatic | ||||
fun sendImageMessage( | fun sendImageMessage( | ||||
toUserId: String, | toUserId: String, | ||||
file: File | |||||
) { | |||||
} | |||||
@JvmStatic | |||||
fun sendImageMessage( | |||||
toUserId: String, | |||||
imageStorageId: String, | imageStorageId: String, | ||||
thumbnail: String, | thumbnail: String, | ||||
thumbnailWidth: Int, | thumbnailWidth: Int, | ||||
@@ -0,0 +1,21 @@ | |||||
package cn.org.bjca.trust.push.common | |||||
import android.content.Context | |||||
import android.content.SharedPreferences | |||||
object SharedPreferencesHelper { | |||||
private lateinit var preferences: SharedPreferences | |||||
fun getPreferences(context: Context): SharedPreferences { | |||||
if (!::preferences.isInitialized) { | |||||
preferences = context.getSharedPreferences("CookiePersistence", Context.MODE_PRIVATE) | |||||
} | |||||
return preferences | |||||
} | |||||
fun getPreferences(): SharedPreferences { | |||||
if (!::preferences.isInitialized) { | |||||
throw Throwable("未初始化") | |||||
} | |||||
return preferences | |||||
} | |||||
} |
@@ -0,0 +1,270 @@ | |||||
package cn.org.bjca.trust.push.common; | |||||
import android.content.Context; | |||||
import android.text.Editable; | |||||
import android.text.TextUtils; | |||||
import android.text.TextWatcher; | |||||
import android.view.View; | |||||
import android.widget.EditText; | |||||
import android.widget.Toast; | |||||
import com.google.android.material.snackbar.Snackbar; | |||||
import com.google.android.material.textfield.TextInputLayout; | |||||
import java.lang.reflect.Field; | |||||
import java.util.HashMap; | |||||
import java.util.Map; | |||||
public class ToolsHelper { | |||||
public static boolean isNull(Object obj) { | |||||
if (null == obj) | |||||
return true; | |||||
String str = obj.toString(); | |||||
if (str.isEmpty()) | |||||
return true; | |||||
return str.equalsIgnoreCase("null"); | |||||
} | |||||
public static Long toLong(Object obj) { | |||||
if (isNull(obj)) | |||||
return 0L; | |||||
try { | |||||
return Long.parseLong(obj.toString()); | |||||
} catch (Exception e) { | |||||
return 0L; | |||||
} | |||||
} | |||||
public static int toInt(Object obj) { | |||||
if (isNull(obj)) | |||||
return 0; | |||||
try { | |||||
return Integer.parseInt(obj.toString()); | |||||
} catch (Exception e) { | |||||
return 0; | |||||
} | |||||
} | |||||
public static Double toDouble(Object obj) { | |||||
if (isNull(obj)) | |||||
return 0.0; | |||||
try { | |||||
return Double.parseDouble(obj.toString()); | |||||
} catch (Exception e) { | |||||
return 0D; | |||||
} | |||||
} | |||||
public static String toString(Object obj) { | |||||
if (isNull(obj)) | |||||
return ""; | |||||
return obj.toString(); | |||||
} | |||||
/** | |||||
* 格式化json字符串 | |||||
* | |||||
* @param jsonStr 需要格式化的json串 | |||||
* @return 格式化后的json串 | |||||
*/ | |||||
public static String formatJson(String jsonStr) { | |||||
if (null == jsonStr || "".equals(jsonStr)) return ""; | |||||
StringBuilder sb = new StringBuilder(); | |||||
char last = '\0'; | |||||
char current = '\0'; | |||||
int indent = 0; | |||||
for (int i = 0; i < jsonStr.length(); i++) { | |||||
last = current; | |||||
current = jsonStr.charAt(i); | |||||
//遇到{ [换行,且下一行缩进 | |||||
switch (current) { | |||||
case '{': | |||||
case '[': | |||||
sb.append(current); | |||||
sb.append('\n'); | |||||
indent++; | |||||
addIndentBlank(sb, indent); | |||||
break; | |||||
//遇到} ]换行,当前行缩进 | |||||
case '}': | |||||
case ']': | |||||
sb.append('\n'); | |||||
indent--; | |||||
addIndentBlank(sb, indent); | |||||
sb.append(current); | |||||
break; | |||||
//遇到,换行 | |||||
case ',': | |||||
sb.append(current); | |||||
if (last != '\\') { | |||||
sb.append('\n'); | |||||
addIndentBlank(sb, indent); | |||||
} | |||||
break; | |||||
default: | |||||
sb.append(current); | |||||
} | |||||
} | |||||
return sb.toString(); | |||||
} | |||||
/** | |||||
* 添加space | |||||
*/ | |||||
private static void addIndentBlank(StringBuilder sb, int indent) { | |||||
for (int i = 0; i < indent; i++) { | |||||
sb.append('\t'); | |||||
} | |||||
} | |||||
/** | |||||
* http 请求数据返回 json 中中文字符为 unicode 编码转汉字转码 | |||||
* | |||||
* @param theString | |||||
* @return 转化后的结果. | |||||
*/ | |||||
public static String decodeUnicode(String theString) { | |||||
char aChar; | |||||
int len = theString.length(); | |||||
StringBuilder outBuffer = new StringBuilder(len); | |||||
for (int x = 0; x < len; ) { | |||||
aChar = theString.charAt(x++); | |||||
if (aChar == '\\') { | |||||
aChar = theString.charAt(x++); | |||||
if (aChar == 'u') { | |||||
int value = 0; | |||||
for (int i = 0; i < 4; i++) { | |||||
aChar = theString.charAt(x++); | |||||
switch (aChar) { | |||||
case '0': | |||||
case '1': | |||||
case '2': | |||||
case '3': | |||||
case '4': | |||||
case '5': | |||||
case '6': | |||||
case '7': | |||||
case '8': | |||||
case '9': | |||||
value = (value << 4) + aChar - '0'; | |||||
break; | |||||
case 'a': | |||||
case 'b': | |||||
case 'c': | |||||
case 'd': | |||||
case 'e': | |||||
case 'f': | |||||
value = (value << 4) + 10 + aChar - 'a'; | |||||
break; | |||||
case 'A': | |||||
case 'B': | |||||
case 'C': | |||||
case 'D': | |||||
case 'E': | |||||
case 'F': | |||||
value = (value << 4) + 10 + aChar - 'A'; | |||||
break; | |||||
default: | |||||
throw new IllegalArgumentException( | |||||
"Malformed \\uxxxx encoding."); | |||||
} | |||||
} | |||||
outBuffer.append((char) value); | |||||
} else { | |||||
if (aChar == 't') { | |||||
aChar = '\t'; | |||||
} else if (aChar != 'r') { | |||||
if (aChar == 'n') { | |||||
aChar = '\n'; | |||||
} else if (aChar == 'f') { | |||||
aChar = '\f'; | |||||
} | |||||
} else { | |||||
aChar = '\r'; | |||||
} | |||||
outBuffer.append(aChar); | |||||
} | |||||
} else { | |||||
outBuffer.append(aChar); | |||||
} | |||||
} | |||||
return outBuffer.toString(); | |||||
} | |||||
/** | |||||
* 弹出提示信息 感觉比Toast好看点 不过Toast不需要依赖view | |||||
* | |||||
* @param view 绑定一个view才能展示 | |||||
* @param content 需要展示的内容 | |||||
*/ | |||||
public static void snack(View view, CharSequence content) { | |||||
Snackbar.make(view, content, Snackbar.LENGTH_SHORT).show(); | |||||
} | |||||
public static void showMessage(Context context, CharSequence content) { | |||||
Toast.makeText(context, content, Toast.LENGTH_SHORT).show(); | |||||
} | |||||
/** | |||||
* EditText绑定TextInputLayout,处理一下 | |||||
* | |||||
* @param editText editText | |||||
* @param textInputLayout textInputLayout | |||||
*/ | |||||
public static void addTextChangedListener(EditText editText, TextInputLayout textInputLayout) { | |||||
editText.addTextChangedListener(new TextWatcher() { | |||||
@Override | |||||
public void beforeTextChanged(CharSequence s, int start, int count, int after) { | |||||
} | |||||
@Override | |||||
public void onTextChanged(CharSequence s, int start, int before, int count) { | |||||
} | |||||
@Override | |||||
public void afterTextChanged(Editable s) { | |||||
if (!TextUtils.isEmpty(textInputLayout.getError())) {//输入的时候不提示错误信息 | |||||
textInputLayout.setErrorEnabled(true); | |||||
textInputLayout.setError(""); | |||||
textInputLayout.setErrorEnabled(false); | |||||
} | |||||
} | |||||
}); | |||||
} | |||||
/** | |||||
* 使用 TextInputLayout 提示错误信息 | |||||
* | |||||
* @param textInputLayout TextInputLayout | |||||
* @param msg 错判的内容 | |||||
*/ | |||||
public static void showError(TextInputLayout textInputLayout, String msg) { | |||||
textInputLayout.setErrorEnabled(true); | |||||
textInputLayout.setError(msg); | |||||
} | |||||
/** | |||||
* 将Object对象里面的属性和值转化成Map对象 | |||||
* | |||||
* @param obj | |||||
* @return | |||||
* @throws IllegalAccessException | |||||
*/ | |||||
public static <T> Map<String, T> objectToMap(Object obj) throws IllegalAccessException { | |||||
Map<String, T> map = new HashMap<>(); | |||||
Class<?> clazz = obj.getClass(); | |||||
for (Field field : clazz.getDeclaredFields()) { | |||||
field.setAccessible(true); | |||||
String fieldName = field.getName(); | |||||
T value = (T) field.get(obj); | |||||
if (null != value) | |||||
map.put(fieldName, value); | |||||
} | |||||
return map; | |||||
} | |||||
} |
@@ -0,0 +1,29 @@ | |||||
package cn.org.bjca.trust.push.di.component; | |||||
import com.franmontiel.persistentcookiejar.PersistentCookieJar; | |||||
import java.util.List; | |||||
import javax.inject.Singleton; | |||||
import cn.org.bjca.trust.push.di.module.NetworkModule; | |||||
import dagger.Component; | |||||
import okhttp3.Cookie; | |||||
import okhttp3.OkHttpClient; | |||||
import retrofit2.Retrofit; | |||||
/** | |||||
* 可以获取到Retrofit、OkHttpClient、PersistentCookieJar、cookies | |||||
*/ | |||||
@Singleton | |||||
@Component(modules = NetworkModule.class) | |||||
public interface AppComponent { | |||||
Retrofit retrofit(); | |||||
OkHttpClient okHttpClient(); | |||||
PersistentCookieJar persistentCookieJar(); | |||||
List<Cookie> cookies(); | |||||
} |
@@ -0,0 +1,28 @@ | |||||
package cn.org.bjca.trust.push.di.interceptor; | |||||
import cn.org.bjca.trust.push.common.LogHelper; | |||||
import cn.org.bjca.trust.push.common.ToolsHelper; | |||||
import okhttp3.logging.HttpLoggingInterceptor; | |||||
public class HttpLogger implements HttpLoggingInterceptor.Logger { | |||||
private StringBuilder mMessage = new StringBuilder(); | |||||
@Override | |||||
public void log(String message) { | |||||
// 请求或者响应开始 | |||||
if (message.startsWith("--> POST")) { | |||||
mMessage.setLength(0); | |||||
} | |||||
// 以{}或者[]形式的说明是响应结果的json数据,需要进行格式化 | |||||
if ((message.startsWith("{") && message.endsWith("}")) | |||||
|| (message.startsWith("[") && message.endsWith("]"))) { | |||||
message = ToolsHelper.formatJson(ToolsHelper.decodeUnicode(message)); | |||||
} | |||||
mMessage.append(message.concat("\n")); | |||||
// 响应结束,打印整条日志 | |||||
if (message.startsWith("<-- END HTTP")) { | |||||
LogHelper.d("___http",mMessage.toString()); | |||||
} | |||||
} | |||||
} |
@@ -0,0 +1,56 @@ | |||||
package cn.org.bjca.trust.push.di.interceptor; | |||||
import static java.nio.charset.StandardCharsets.UTF_8; | |||||
import java.io.IOException; | |||||
import java.nio.charset.Charset; | |||||
import cn.org.bjca.trust.push.common.LogHelper; | |||||
import okhttp3.Interceptor; | |||||
import okhttp3.MediaType; | |||||
import okhttp3.Request; | |||||
import okhttp3.Response; | |||||
import okhttp3.ResponseBody; | |||||
import okio.Buffer; | |||||
public class LoggingInterceptor implements Interceptor { | |||||
String TAG = "_____Http"; | |||||
@Override | |||||
public Response intercept(Chain chain) throws IOException { | |||||
Request request = chain.request(); | |||||
long startTime = System.currentTimeMillis(); | |||||
Response response = chain.proceed(chain.request()); | |||||
long endTime = System.currentTimeMillis(); | |||||
long duration = endTime - startTime; | |||||
ResponseBody responseBody = response.body(); | |||||
if (responseBody == null) { | |||||
return response; | |||||
} | |||||
okhttp3.MediaType mediaType = responseBody.contentType(); | |||||
String content = response.body().string(); | |||||
LogHelper.e(request.toString(), TAG); | |||||
LogHelper.e(response.code() + " : " + response.message(), TAG); | |||||
String method = request.method(); | |||||
if ("POST".equals(method)) { | |||||
Buffer buffer = new Buffer(); | |||||
try { | |||||
request.body().writeTo(buffer); | |||||
Charset charset = Charset.forName("UTF-8"); | |||||
MediaType contentType = request.body().contentType(); | |||||
if (contentType != null) { | |||||
charset = contentType.charset(UTF_8); | |||||
} | |||||
String params = buffer.readString(charset); | |||||
LogHelper.e(params, TAG); | |||||
} catch (IOException e) { | |||||
e.printStackTrace(); | |||||
} | |||||
} | |||||
LogHelper.d(content, TAG); | |||||
LogHelper.e("耗时: " + duration + "毫秒", TAG); | |||||
return response.newBuilder().body(okhttp3.ResponseBody.create(mediaType, content)).build(); | |||||
} | |||||
} |
@@ -0,0 +1,68 @@ | |||||
package cn.org.bjca.trust.push.di.manager; | |||||
import java.util.HashMap; | |||||
import java.util.Map; | |||||
import cn.org.bjca.trust.push.di.component.AppComponent; | |||||
import cn.org.bjca.trust.push.di.component.DaggerAppComponent; | |||||
import cn.org.bjca.trust.push.di.interceptor.HttpLogger; | |||||
import cn.org.bjca.trust.push.di.module.NetworkModule; | |||||
import okhttp3.Interceptor; | |||||
import okhttp3.logging.HttpLoggingInterceptor; | |||||
/** | |||||
* 网络访问的管理类, | |||||
*/ | |||||
public class HttpManager { | |||||
private static Map<String, Object> apis = new HashMap<>(); | |||||
private static Map<String, AppComponent> appComponentMap = new HashMap<>(); | |||||
/** | |||||
* 根据给定的appComponent和service获取一个service实例 | |||||
* appComponent可以使用{@link #getAppComponent(String)} 方法获得 | |||||
* service 可以参照retrofit的使用方法 | |||||
* | |||||
* @param appComponent {@link #getAppComponent(String)} | |||||
* @param service service | |||||
* @param <T> service实例class类型 | |||||
* @return service实例 | |||||
*/ | |||||
public static <T> T getApi(AppComponent appComponent, final Class<T> service) { | |||||
String key = appComponent.hashCode() + service.getCanonicalName(); | |||||
if (!apis.containsKey(key)) | |||||
synchronized (HttpManager.class) { | |||||
if (!apis.containsKey(key)) | |||||
apis.put(key, appComponent.retrofit().create(service)); | |||||
} | |||||
return (T) apis.get(key); | |||||
} | |||||
/** | |||||
* 根据指定的baseUrl 获取一个{@link AppComponent} 用来做后续事件 | |||||
* | |||||
* @param baseUrl 换地地址 例如 | |||||
* @return AppComponent | |||||
*/ | |||||
public static AppComponent getAppComponent(String baseUrl) { | |||||
return getAppComponent(baseUrl, new HttpLoggingInterceptor(new HttpLogger()).setLevel(HttpLoggingInterceptor.Level.BASIC)); | |||||
} | |||||
/** | |||||
* 根据指定的baseUrl 获取一个{@link AppComponent} 用来做后续事件 | |||||
* | |||||
* @param baseUrl 换地地址 | |||||
* @param interceptor 自定义拦截器 | |||||
* @return AppComponent | |||||
*/ | |||||
public static AppComponent getAppComponent(String baseUrl, Interceptor... interceptor) { | |||||
if (!appComponentMap.containsKey(baseUrl)) | |||||
synchronized (HttpManager.class) { | |||||
if (!appComponentMap.containsKey(baseUrl)) | |||||
appComponentMap.put(baseUrl, DaggerAppComponent.builder().networkModule(new NetworkModule(baseUrl, interceptor)).build()); | |||||
} | |||||
return appComponentMap.get(baseUrl); | |||||
} | |||||
} |
@@ -0,0 +1,100 @@ | |||||
package cn.org.bjca.trust.push.di.module; | |||||
import com.franmontiel.persistentcookiejar.PersistentCookieJar; | |||||
import com.franmontiel.persistentcookiejar.cache.SetCookieCache; | |||||
import com.franmontiel.persistentcookiejar.persistence.SharedPrefsCookiePersistor; | |||||
import java.util.ArrayList; | |||||
import java.util.Arrays; | |||||
import java.util.List; | |||||
import java.util.concurrent.TimeUnit; | |||||
import javax.inject.Singleton; | |||||
import cn.org.bjca.trust.push.common.SharedPreferencesHelper; | |||||
import cn.org.bjca.trust.push.di.interceptor.HttpLogger; | |||||
import dagger.Module; | |||||
import dagger.Provides; | |||||
import dagger.hilt.InstallIn; | |||||
import dagger.hilt.components.SingletonComponent; | |||||
import okhttp3.Cookie; | |||||
import okhttp3.Interceptor; | |||||
import okhttp3.OkHttpClient; | |||||
import okhttp3.logging.HttpLoggingInterceptor; | |||||
import retrofit2.Retrofit; | |||||
import retrofit2.converter.gson.GsonConverterFactory; | |||||
@Module | |||||
@InstallIn(SingletonComponent.class) | |||||
public class NetworkModule { | |||||
private String BaseUrl = "https://xuqinmin.com/"; | |||||
private final List<Interceptor> interceptor = new ArrayList<>(); | |||||
public NetworkModule() { | |||||
} | |||||
public NetworkModule(String baseUrl, Interceptor... interceptor) { | |||||
BaseUrl = baseUrl; | |||||
this.interceptor.clear(); | |||||
if (null != interceptor) | |||||
this.interceptor.addAll(Arrays.asList(interceptor)); | |||||
} | |||||
@Provides | |||||
@Singleton | |||||
Retrofit provideRetrofit(OkHttpClient okHttpClient) { | |||||
return new Retrofit.Builder() | |||||
.baseUrl(BaseUrl) | |||||
.client(okHttpClient) | |||||
.addConverterFactory(GsonConverterFactory.create()) | |||||
// .addCallAdapterFactory(RxJava2CallAdapterFactory.create()) | |||||
.build(); | |||||
} | |||||
@Provides | |||||
@Singleton | |||||
OkHttpClient provideOkHttpClient(HttpLoggingInterceptor httpLoggingInterceptor, PersistentCookieJar persistentCookieJar) { | |||||
OkHttpClient.Builder builder = new OkHttpClient.Builder() | |||||
.connectTimeout(30, TimeUnit.SECONDS) | |||||
.pingInterval(5, TimeUnit.SECONDS) | |||||
.readTimeout(60, TimeUnit.SECONDS) | |||||
.writeTimeout(60, TimeUnit.SECONDS); | |||||
// builder.addNetworkInterceptor(httpLoggingInterceptor); | |||||
if (0 != interceptor.size()) { | |||||
for (Interceptor interceptor1 : this.interceptor) { | |||||
builder.addInterceptor(interceptor1); | |||||
} | |||||
} | |||||
return builder.cookieJar(persistentCookieJar) | |||||
.build(); | |||||
} | |||||
@Provides | |||||
@Singleton | |||||
HttpLoggingInterceptor provideHttpLoggingInterceptor() { | |||||
return new HttpLoggingInterceptor(new HttpLogger()).setLevel(HttpLoggingInterceptor.Level.BASIC); | |||||
} | |||||
@Provides | |||||
@Singleton | |||||
PersistentCookieJar providePersistentCookieJar(SharedPrefsCookiePersistor sharedPrefsCookiePersistor) { | |||||
return new PersistentCookieJar(new SetCookieCache(), sharedPrefsCookiePersistor); | |||||
} | |||||
@Provides | |||||
@Singleton | |||||
SharedPrefsCookiePersistor provideSharedPrefsCookiePersistor() { | |||||
return new SharedPrefsCookiePersistor(SharedPreferencesHelper.INSTANCE.getPreferences()); | |||||
} | |||||
@Provides | |||||
@Singleton | |||||
List<Cookie> provideCookies(SharedPrefsCookiePersistor sharedPrefsCookiePersistor) { | |||||
return sharedPrefsCookiePersistor.loadAll(); | |||||
} | |||||
} |
@@ -0,0 +1,174 @@ | |||||
package com.xuqm.base.extensions | |||||
import android.app.Activity | |||||
import android.content.Context | |||||
import android.view.inputmethod.InputMethodManager | |||||
import androidx.annotation.NonNull | |||||
import androidx.appcompat.app.AlertDialog | |||||
import androidx.fragment.app.Fragment | |||||
import cn.org.bjca.trust.push.BuildConfig | |||||
import cn.org.bjca.trust.push.api.HttpResult | |||||
import cn.org.bjca.trust.push.common.LogHelper | |||||
import kotlinx.coroutines.CoroutineScope | |||||
import kotlinx.coroutines.Job | |||||
import kotlinx.coroutines.launch | |||||
fun Any.log(message: Any) { | |||||
LogHelper.d(message) | |||||
} | |||||
fun Any.loge(message: Any) { | |||||
LogHelper.e(message) | |||||
} | |||||
fun Any.log() { | |||||
LogHelper.d(this) | |||||
} | |||||
fun Any.loge() { | |||||
LogHelper.e(this) | |||||
} | |||||
/** | |||||
* 弹出窗口 | |||||
* @param title 标题 | |||||
* @param message 提示信息 | |||||
* @param confirm 点击确认按钮 | |||||
* @param cancel 点击取消按钮的事件 | |||||
*/ | |||||
fun Activity.showDialog(title: String, message: String, confirm: () -> Unit, cancel: () -> Unit) { | |||||
AlertDialog.Builder(this).setTitle(title) | |||||
.setMessage(message) | |||||
.setPositiveButton( | |||||
"确定" | |||||
) { _, _ -> | |||||
confirm() | |||||
} | |||||
.setNegativeButton( | |||||
"取消" | |||||
) { _, _ -> | |||||
cancel() | |||||
}.create().show() | |||||
} | |||||
/** | |||||
* 弹出窗口---只有一个确认按钮 | |||||
* @param title 标题 | |||||
* @param message 提示信息 | |||||
* @param confirm 点击确认按钮 | |||||
*/ | |||||
fun Activity.showDialog(title: String, message: String, confirm: () -> Unit) { | |||||
AlertDialog.Builder(this).setTitle(title) | |||||
.setMessage(message) | |||||
.setPositiveButton( | |||||
"确定" | |||||
) { _, _ -> | |||||
confirm() | |||||
}.create().show() | |||||
} | |||||
/* | |||||
隐藏软键盘 | |||||
*/ | |||||
fun Activity.hideSoftInput() { | |||||
val imm = getSystemService(Context.INPUT_METHOD_SERVICE) as InputMethodManager | |||||
imm.hideSoftInputFromWindow(window.decorView.windowToken, 0) | |||||
} | |||||
fun Fragment.hideSoftInput() { | |||||
activity?.hideSoftInput() | |||||
} | |||||
fun Context.putInt(key: String, value: Int) { | |||||
val sharedPref = | |||||
getSharedPreferences(BuildConfig.versionName, Context.MODE_PRIVATE) ?: return | |||||
with(sharedPref.edit()) { | |||||
putInt(key, value) | |||||
apply() | |||||
} | |||||
} | |||||
fun Context.getIntForPreferences(key: String): Int { | |||||
val sharedPref = | |||||
getSharedPreferences(BuildConfig.versionName, Context.MODE_PRIVATE) | |||||
return sharedPref?.getInt(key, -1) ?: -1 | |||||
} | |||||
fun Context.getIntForPreferences(key: String, @NonNull defValue: Int): Int { | |||||
val sharedPref = | |||||
getSharedPreferences(BuildConfig.versionName, Context.MODE_PRIVATE) | |||||
return sharedPref?.getInt(key, defValue) ?: defValue | |||||
} | |||||
fun Context.putLong(key: String, value: Long) { | |||||
val sharedPref = | |||||
getSharedPreferences(BuildConfig.versionName, Context.MODE_PRIVATE) ?: return | |||||
with(sharedPref.edit()) { | |||||
putLong(key, value) | |||||
apply() | |||||
} | |||||
} | |||||
fun Context.getLongForPreferences(key: String): Long { | |||||
val sharedPref = | |||||
getSharedPreferences(BuildConfig.versionName, Context.MODE_PRIVATE) | |||||
return sharedPref?.getLong(key, -1) ?: -1 | |||||
} | |||||
fun Context.getLongForPreferences(key: String, @NonNull defValue: Long): Long { | |||||
val sharedPref = | |||||
getSharedPreferences(BuildConfig.versionName, Context.MODE_PRIVATE) | |||||
return sharedPref?.getLong(key, defValue) ?: defValue | |||||
} | |||||
fun Context.putString(key: String, value: String) { | |||||
val sharedPref = | |||||
getSharedPreferences(BuildConfig.versionName, Context.MODE_PRIVATE) ?: return | |||||
with(sharedPref.edit()) { | |||||
putString(key, value) | |||||
apply() | |||||
} | |||||
} | |||||
fun Context.getStringForPreferences(key: String): String { | |||||
val sharedPref = | |||||
getSharedPreferences(BuildConfig.versionName, Context.MODE_PRIVATE) | |||||
return sharedPref?.getString(key, "") ?: "" | |||||
} | |||||
fun Context.getStringForPreferences(key: String, @NonNull defValue: String): String { | |||||
val sharedPref = | |||||
getSharedPreferences(BuildConfig.versionName, Context.MODE_PRIVATE) | |||||
return sharedPref?.getString(key, defValue) ?: defValue | |||||
} | |||||
/** | |||||
* http 请求扩展 | |||||
*/ | |||||
fun <T> CoroutineScope.http( | |||||
start: () -> Unit = {}, | |||||
request: suspend CoroutineScope.() -> HttpResult<T>, | |||||
resp: (T?) -> Unit, | |||||
err: (String) -> Unit = {}, | |||||
end: () -> Unit = {} | |||||
): Job { | |||||
return launch { | |||||
try { | |||||
start() | |||||
val data = request() | |||||
if (data.status == "200") { | |||||
resp(data.data) | |||||
} else { | |||||
err(data.msg) | |||||
} | |||||
} catch (e: Exception) { | |||||
err(e.message ?: "") //可根据具体异常显示具体错误提示 | |||||
LogHelper.e(e, "CoroutineScope::") | |||||
} finally { | |||||
end() | |||||
} | |||||
} | |||||
} | |||||
@@ -2,13 +2,17 @@ package cn.org.bjca.trust.push.manager | |||||
import android.content.Context | import android.content.Context | ||||
import cn.org.bjca.trust.push.BuildConfig | import cn.org.bjca.trust.push.BuildConfig | ||||
import cn.org.bjca.trust.push.api.PushService | |||||
import cn.org.bjca.trust.push.common.DeviceHelper | import cn.org.bjca.trust.push.common.DeviceHelper | ||||
import cn.org.bjca.trust.push.common.LogHelper | |||||
import cn.org.bjca.trust.push.di.manager.HttpManager | |||||
import cn.org.bjca.trust.push.enums.OsType | import cn.org.bjca.trust.push.enums.OsType | ||||
import cn.org.bjca.trust.push.kit.SdkInterface | import cn.org.bjca.trust.push.kit.SdkInterface | ||||
import cn.org.bjca.trust.push.message.ImCallback | import cn.org.bjca.trust.push.message.ImCallback | ||||
import cn.org.bjca.trust.push.message.ImManager | import cn.org.bjca.trust.push.message.ImManager | ||||
import cn.org.bjca.trust.push.message.callback.CallbackListener | import cn.org.bjca.trust.push.message.callback.CallbackListener | ||||
import cn.org.bjca.trust.push.message.client.ImConnectOptions | import cn.org.bjca.trust.push.message.client.ImConnectOptions | ||||
import kotlinx.coroutines.runBlocking | |||||
class PushSdkManager : SdkInterface { | class PushSdkManager : SdkInterface { | ||||
@@ -21,6 +25,17 @@ class PushSdkManager : SdkInterface { | |||||
private fun registerPush(userId: String) {} | private fun registerPush(userId: String) {} | ||||
private fun registerIm(userId: String) { | private fun registerIm(userId: String) { | ||||
runBlocking { | |||||
HttpManager.getApi( | |||||
HttpManager.getAppComponent("http://192.168.115.173:8080"), | |||||
PushService::class.java | |||||
) | |||||
.getArticle(42) | |||||
}.also { | |||||
LogHelper.e(it, "初始化登录") | |||||
} | |||||
//先关闭已有连接 | //先关闭已有连接 | ||||
if (ImManager.instance.isConnect() || ImManager.instance.isConnecting()) { | if (ImManager.instance.isConnect() || ImManager.instance.isConnecting()) { | ||||
ImManager.instance.disConnect() | ImManager.instance.disConnect() | ||||
@@ -10,6 +10,7 @@ import androidx.sqlite.db.SupportSQLiteQueryBuilder | |||||
import cn.org.bjca.trust.push.CrashHandler | import cn.org.bjca.trust.push.CrashHandler | ||||
import cn.org.bjca.trust.push.common.CommonHelper | import cn.org.bjca.trust.push.common.CommonHelper | ||||
import cn.org.bjca.trust.push.common.LogHelper | import cn.org.bjca.trust.push.common.LogHelper | ||||
import cn.org.bjca.trust.push.common.SharedPreferencesHelper | |||||
import cn.org.bjca.trust.push.db.DbHelper | import cn.org.bjca.trust.push.db.DbHelper | ||||
import cn.org.bjca.trust.push.db.device.Device | import cn.org.bjca.trust.push.db.device.Device | ||||
import com.huawei.hms.push.HmsMessaging | import com.huawei.hms.push.HmsMessaging | ||||
@@ -28,6 +29,7 @@ class PushProvider : ContentProvider() { | |||||
} | } | ||||
override fun onCreate(): Boolean { | override fun onCreate(): Boolean { | ||||
context?.let { SharedPreferencesHelper.getPreferences(it) } | |||||
// 初始化数据库 | // 初始化数据库 | ||||
initDb() | initDb() | ||||
//初始化日志收集系统 | //初始化日志收集系统 | ||||