Compare commits
12 Commits
feature-me
...
feature-is
| Author | SHA1 | Date | |
|---|---|---|---|
| 8a7d588206 | |||
| 42ae45c743 | |||
| 3246dd0d70 | |||
| 06ac1fd8b0 | |||
| 81da40d786 | |||
| 9eb919b3cf | |||
| b4cbff3d6a | |||
| c7dfac8f46 | |||
| 08af4a99f8 | |||
| f3a358eb2d | |||
| 6abac72ee7 | |||
| b027c57a7c |
@ -759,6 +759,12 @@
|
||||
android:resource="@xml/provider_paths" />
|
||||
</provider>
|
||||
|
||||
<provider
|
||||
android:name="com.gh.gamecenter.provider.GhContentProvider"
|
||||
android:authorities="${applicationId}.provider"
|
||||
android:enabled="true"
|
||||
android:exported="true"/>
|
||||
|
||||
<provider
|
||||
android:name="androidx.startup.InitializationProvider"
|
||||
android:authorities="${applicationId}.androidx-startup"
|
||||
|
||||
@ -3,16 +3,23 @@ package com.gh.common.util;
|
||||
import android.annotation.SuppressLint;
|
||||
import android.app.Activity;
|
||||
import android.app.Application;
|
||||
import android.content.ContentResolver;
|
||||
import android.content.ContentValues;
|
||||
import android.content.Context;
|
||||
import android.net.Uri;
|
||||
import android.os.Build;
|
||||
import android.preference.PreferenceManager;
|
||||
import android.text.TextUtils;
|
||||
|
||||
import androidx.annotation.RequiresApi;
|
||||
|
||||
import com.gh.common.AppExecutor;
|
||||
import com.gh.common.constant.Constants;
|
||||
import com.gh.common.exposure.meta.MetaUtil;
|
||||
import com.gh.gamecenter.BuildConfig;
|
||||
import com.gh.gamecenter.entity.IdCardEntity;
|
||||
import com.gh.gamecenter.entity.UserInfoEntity;
|
||||
import com.gh.gamecenter.provider.GhContentProvider;
|
||||
import com.gh.gamecenter.retrofit.BiResponse;
|
||||
import com.gh.gamecenter.retrofit.RetrofitManager;
|
||||
import com.gh.gid.GidCallback;
|
||||
@ -24,7 +31,6 @@ import com.lightgame.utils.Utils;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
import io.reactivex.android.schedulers.AndroidSchedulers;
|
||||
import io.reactivex.schedulers.Schedulers;
|
||||
import io.sentry.Sentry;
|
||||
import io.sentry.android.core.SentryAndroid;
|
||||
@ -42,11 +48,10 @@ public class DataUtils {
|
||||
* @param channel
|
||||
*/
|
||||
public static void init(final Application context, String channel) {
|
||||
|
||||
if (CommonDebug.IS_DEBUG) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
// 初始化 Sentry 约占用 90ms,这里切换到子线程初始化
|
||||
AppExecutor.getIoExecutor().execute(() -> initSentry(context, channel));
|
||||
|
||||
@ -118,7 +123,7 @@ public class DataUtils {
|
||||
// }
|
||||
|
||||
}
|
||||
|
||||
|
||||
private static void initSentry(Context context, String channel) {
|
||||
SentryAndroid.init(context, options -> {
|
||||
// Sentry 疯狂报 ANR (很大一部分还是莫名奇妙的 ANR)严重影响到其它闪退日志的收集
|
||||
@ -129,12 +134,12 @@ public class DataUtils {
|
||||
} else {
|
||||
options.setAnrEnabled(false);
|
||||
}
|
||||
|
||||
|
||||
options.setDebug(BuildConfig.DEBUG);
|
||||
options.setEnableSessionTracking(true);
|
||||
options.setEnvironment(BuildConfig.FLAVOR);
|
||||
options.setDsn("https://6b1caf0d17c1408e8680f3f73ff80bd0@sentry.shanqu.cc/22");
|
||||
|
||||
|
||||
options.setBeforeSend((event, hint) -> {
|
||||
if (BuildConfig.DEBUG) {
|
||||
return null;
|
||||
@ -143,7 +148,7 @@ public class DataUtils {
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
Sentry.configureScope(scope -> {
|
||||
if (BuildConfig.BUILD_TIME != 0L) {
|
||||
scope.setTag("alias", "内测版" + BuildConfig.VERSION_NAME);
|
||||
@ -203,6 +208,22 @@ public class DataUtils {
|
||||
@Override
|
||||
public void onSuccess(UserInfoEntity data) {
|
||||
SPUtils.setString(Constants.SP_DEVICE_CERTIFICATION_PREFIX + gid, GsonUtils.toJson(data));
|
||||
|
||||
ContentValues values = new ContentValues();
|
||||
IdCardEntity idCardEntity = data.getIdCard();
|
||||
|
||||
if (idCardEntity != null) {
|
||||
values.put(GhContentProvider.KEY_IS_CERTIFICATED, !TextUtils.isEmpty(data.getIdCard().getId())); // 是否认证
|
||||
values.put(GhContentProvider.KEY_IS_ADULT,
|
||||
data.getIdCard().getMinor() == null
|
||||
|| !data.getIdCard().getMinor()
|
||||
);
|
||||
} else {
|
||||
values.put(GhContentProvider.KEY_IS_CERTIFICATED, false);
|
||||
values.put(GhContentProvider.KEY_IS_ADULT, false);
|
||||
}
|
||||
|
||||
HaloApp.getInstance().getContentResolver().insert(Uri.parse("content://com.gh.gamecenter.provider/certification"), values);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@ -47,6 +47,7 @@ public class EntranceUtils {
|
||||
public static final String KEY_GAMENAME = "gameName";
|
||||
public static final String KEY_PACKAGE_MD5 = "package_md5";
|
||||
public static final String HOST_ARTICLE = "article";
|
||||
public static final String HOST_INVOKE_ONLY = "invoke_only";
|
||||
public static final String HOST_UPLOAD_VIDEO = "upload_video";//上传视频
|
||||
public static final String HOST_UPLOAD_VIDEO_NEW = "upload_video_new"; // 上传视频新(AKA 发视频)
|
||||
public static final String HOST_VIDEO_SINGLE = "video_single";//指定视频-不能划动
|
||||
|
||||
@ -38,6 +38,7 @@ import static com.gh.common.util.EntranceUtils.HOST_DOWNLOAD;
|
||||
import static com.gh.common.util.EntranceUtils.HOST_GAME;
|
||||
import static com.gh.common.util.EntranceUtils.HOST_GAME_COLLECTION_DETAIL;
|
||||
import static com.gh.common.util.EntranceUtils.HOST_GAME_COLLECTION_SQUARE;
|
||||
import static com.gh.common.util.EntranceUtils.HOST_INVOKE_ONLY;
|
||||
import static com.gh.common.util.EntranceUtils.HOST_LIBAO;
|
||||
import static com.gh.common.util.EntranceUtils.HOST_QQ;
|
||||
import static com.gh.common.util.EntranceUtils.HOST_QQ_GROUP;
|
||||
@ -100,6 +101,9 @@ public class SkipActivity extends BaseActivity {
|
||||
if (host != null) {
|
||||
Intent intent;
|
||||
switch (host) {
|
||||
case HOST_INVOKE_ONLY:
|
||||
// 仅唤起光环助手,不进入光环页面。用于类似 ContentProvider 的用途
|
||||
break;
|
||||
case HOST_ARTICLE:
|
||||
DirectUtils.directToArticle(this, path, ENTRANCE_BROWSER);
|
||||
break;
|
||||
|
||||
@ -8,6 +8,7 @@ data class IdCardEntity(
|
||||
var id: String? = null,
|
||||
var name: String? = null,
|
||||
var revise: Boolean? = false,
|
||||
var minor: Boolean? = false, // 是否是未成年人
|
||||
@SerializedName("id_photo")
|
||||
var idPhoto: String? = null
|
||||
)
|
||||
@ -0,0 +1,177 @@
|
||||
package com.gh.gamecenter.provider
|
||||
|
||||
import android.content.ContentProvider
|
||||
import android.content.ContentUris
|
||||
import android.content.ContentValues
|
||||
import android.content.UriMatcher
|
||||
import android.database.Cursor
|
||||
import android.database.sqlite.SQLiteDatabase
|
||||
import android.database.sqlite.SQLiteOpenHelper
|
||||
import android.net.Uri
|
||||
import android.text.TextUtils
|
||||
import android.util.Base64
|
||||
import com.gh.common.constant.Constants
|
||||
import com.gh.common.util.GsonUtils
|
||||
import com.gh.common.util.SPUtils
|
||||
import com.gh.gamecenter.BuildConfig
|
||||
import com.gh.gamecenter.entity.UserInfoEntity
|
||||
import com.gh.gamecenter.user.UserRepository
|
||||
import com.halo.assistant.HaloApp
|
||||
import com.lightgame.utils.Utils
|
||||
|
||||
class GhContentProvider : ContentProvider() {
|
||||
|
||||
private var mUriMatcher: UriMatcher = UriMatcher(UriMatcher.NO_MATCH)
|
||||
private var mSqLiteDatabase: SQLiteDatabase? = null
|
||||
|
||||
init {
|
||||
mUriMatcher.addURI(AUTHORITY, CERTIFICATION_TABLE_NAME, 1)
|
||||
mUriMatcher.addURI(AUTHORITY, SYNC_CERTIFICATION_TABLE_NAME, 2)
|
||||
}
|
||||
|
||||
override fun onCreate(): Boolean {
|
||||
val helper: SQLiteOpenHelper =
|
||||
object : SQLiteOpenHelper(context, CERTIFICATION_DATABASE_NAME, null, 1) {
|
||||
override fun onCreate(db: SQLiteDatabase) {
|
||||
// 创建表格
|
||||
val sql = "CREATE TABLE $CERTIFICATION_TABLE_NAME(" +
|
||||
"$KEY_PRIMARY_KEY INTEGER PRIMARY KEY AUTOINCREMENT," +
|
||||
"$KEY_IS_CERTIFICATED BOOL," +
|
||||
"$KEY_IS_ADULT BOOL" +
|
||||
")"
|
||||
db.execSQL(sql)
|
||||
|
||||
val syncSql = "CREATE TABLE ${SYNC_CERTIFICATION_TABLE_NAME}(" +
|
||||
"$KEY_PRIMARY_KEY INTEGER PRIMARY KEY AUTOINCREMENT," +
|
||||
"$KEY_REAL_NAME TEXT," +
|
||||
"$KEY_ID_CARD TEXT" +
|
||||
")"
|
||||
db.execSQL(syncSql)
|
||||
}
|
||||
|
||||
override fun onUpgrade(db: SQLiteDatabase, oldVersion: Int, newVersion: Int) {
|
||||
// do nothing
|
||||
}
|
||||
}
|
||||
mSqLiteDatabase = helper.writableDatabase
|
||||
|
||||
return true
|
||||
}
|
||||
|
||||
override fun query(
|
||||
uri: Uri,
|
||||
projection: Array<out String>?,
|
||||
selection: String?,
|
||||
selectionArgs: Array<out String>?,
|
||||
sortOrder: String?
|
||||
): Cursor? {
|
||||
when(mUriMatcher.match(uri)){
|
||||
1 -> return mSqLiteDatabase?.query(
|
||||
CERTIFICATION_TABLE_NAME,
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
null
|
||||
)
|
||||
2 -> return mSqLiteDatabase?.query(
|
||||
SYNC_CERTIFICATION_TABLE_NAME,
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
null
|
||||
)
|
||||
}
|
||||
return null
|
||||
|
||||
}
|
||||
|
||||
override fun getType(uri: Uri): String? = null
|
||||
|
||||
override fun insert(uri: Uri, values: ContentValues?): Uri? {
|
||||
val context = context ?: return null
|
||||
|
||||
if (mUriMatcher.match(uri) == 1) {
|
||||
// 固定主键(只保留一条数据即可)
|
||||
values?.put(KEY_PRIMARY_KEY, 1)
|
||||
// 如果已存在则直接替换
|
||||
val rowId: Long? = mSqLiteDatabase?.insertWithOnConflict(
|
||||
CERTIFICATION_TABLE_NAME,
|
||||
null,
|
||||
values,
|
||||
SQLiteDatabase.CONFLICT_REPLACE
|
||||
)
|
||||
if (rowId != null && rowId > 0) {
|
||||
val nameUri = ContentUris.withAppendedId(uri, rowId)
|
||||
context.contentResolver.notifyChange(nameUri, null)
|
||||
Utils.log("CertificationContentProvider", "insert success:" + uri.authority + ", status => " + values?.toString())
|
||||
return nameUri
|
||||
}
|
||||
} else if (mUriMatcher.match(uri) == 2) {
|
||||
val certificationStr =
|
||||
SPUtils.getString(Constants.SP_DEVICE_CERTIFICATION_PREFIX + HaloApp.getInstance().gid)
|
||||
val isCertification = if (TextUtils.isEmpty(certificationStr)) {
|
||||
false
|
||||
} else {
|
||||
val userInfo: UserInfoEntity =
|
||||
GsonUtils.fromJson(certificationStr, UserInfoEntity::class.java)
|
||||
if (userInfo != null) {
|
||||
!TextUtils.isEmpty(userInfo.idCard?.id)
|
||||
} else {
|
||||
false
|
||||
}
|
||||
|
||||
}
|
||||
if (!isCertification) {//如果未实名的话 就直接将写入的信息进行实名信息绑定
|
||||
val realName = values?.getAsString(KEY_REAL_NAME)
|
||||
val idCard = values?.getAsString(KEY_ID_CARD)
|
||||
if (!TextUtils.isEmpty(realName) && !TextUtils.isEmpty(idCard)) {
|
||||
//base64解密存储的数据
|
||||
val finalRealName = String(Base64.decode(realName, Base64.DEFAULT))
|
||||
val finalIdCard = String(Base64.decode(idCard, Base64.DEFAULT))
|
||||
// Utils.log("解密后的数据:$finalRealName ------ $finalIdCard")
|
||||
//发送同步实名认证请求
|
||||
UserRepository.getInstance().syncCertificate(finalRealName, finalIdCard)
|
||||
return ContentUris.withAppendedId(uri, 1)
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
return null
|
||||
}
|
||||
|
||||
override fun delete(uri: Uri, selection: String?, selectionArgs: Array<out String>?): Int {
|
||||
// delete from outside is forbidden
|
||||
if (mUriMatcher.match(uri) == 2){
|
||||
return mSqLiteDatabase?.delete(SYNC_CERTIFICATION_TABLE_NAME,selection,selectionArgs) ?: 0
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
override fun update(
|
||||
uri: Uri,
|
||||
values: ContentValues?,
|
||||
selection: String?,
|
||||
selectionArgs: Array<out String>?
|
||||
): Int {
|
||||
return 0
|
||||
}
|
||||
|
||||
companion object {
|
||||
private const val AUTHORITY = "${BuildConfig.APPLICATION_ID}.provider"
|
||||
private const val CERTIFICATION_DATABASE_NAME = "gh_certification.db"
|
||||
private const val CERTIFICATION_TABLE_NAME = "certification"
|
||||
|
||||
const val KEY_PRIMARY_KEY = "primary_key"
|
||||
const val KEY_IS_CERTIFICATED = "is_certificated"
|
||||
const val KEY_IS_ADULT = "is_adult"
|
||||
|
||||
private const val SYNC_CERTIFICATION_TABLE_NAME = "sync_certification"
|
||||
|
||||
const val KEY_REAL_NAME = "real_name"
|
||||
const val KEY_ID_CARD = "id_card"
|
||||
}
|
||||
}
|
||||
@ -3534,4 +3534,13 @@ public interface ApiService {
|
||||
*/
|
||||
@POST("videos/{video_id}/comments/{comment_id}:unset-top")
|
||||
Observable<ResponseBody> postVideoCommentUnTop(@Path("video_id") String videoId, @Path("comment_id") String commentId);
|
||||
|
||||
/**
|
||||
* 同步从其他游戏传过来的实名认证
|
||||
*/
|
||||
@POST("./certification:sync")
|
||||
Observable<ResponseBody> postSyncCertification(@Body RequestBody body);
|
||||
|
||||
|
||||
|
||||
}
|
||||
@ -55,6 +55,7 @@ import org.json.JSONException;
|
||||
import org.json.JSONObject;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
import io.reactivex.Observable;
|
||||
import io.reactivex.android.schedulers.AndroidSchedulers;
|
||||
@ -502,6 +503,37 @@ public class UserRepository {
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 同步实名信息
|
||||
*/
|
||||
@SuppressLint("CheckResult")
|
||||
public void syncCertificate(final String realName, final String idCard) {
|
||||
Map<String,Map<String,String>> map = new HashMap<>();
|
||||
Map<String,String> info = new HashMap<>();
|
||||
info.put("id",idCard);
|
||||
info.put("name",realName);
|
||||
map.put("id_card",info);
|
||||
RequestBody body = RequestBody.create(
|
||||
MediaType.parse("application/json"), new JSONObject(map).toString());
|
||||
RetrofitManager.getInstance().getApi().postSyncCertification(body)
|
||||
.subscribeOn(Schedulers.io())
|
||||
.observeOn(AndroidSchedulers.mainThread())
|
||||
.subscribe(new Response<ResponseBody>(){
|
||||
@Override
|
||||
public void onResponse(@Nullable ResponseBody response) {
|
||||
super.onResponse(response);
|
||||
DataUtils.getDeviceCertification(HaloApp.getInstance().getGid());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onApiFailure(ApiResponse<ResponseBody> e) {
|
||||
super.onApiFailure(e);
|
||||
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private Response<UserInfoEntity> userInfoResponse(final LoginTag loginTag) {
|
||||
return new Response<UserInfoEntity>() {
|
||||
@Override
|
||||
|
||||
@ -0,0 +1,6 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<shape xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:shape="rectangle">
|
||||
<corners android:radius="20dp" />
|
||||
<solid android:color="@color/theme" />
|
||||
</shape>
|
||||
@ -0,0 +1,6 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<shape xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:shape="rectangle">
|
||||
<corners android:radius="20dp" />
|
||||
<solid android:color="@color/divider" />
|
||||
</shape>
|
||||
@ -880,4 +880,7 @@
|
||||
<string name="attempt_tips_2">该游戏暂时仅提供试玩版本。试玩版可能存在bug或兼容性问题。敬请留意后续相关消息。</string>
|
||||
<string name="rating_protection">游戏停服更新维护中,为避免情绪化内容对游戏评分带来的影响,因此开启停服保护功能。在停服保护状态期间,所新增及修改发布的评分将不计入总分,所评分评论内容在展示上也会有文字提示告知其他玩家。\n\n感谢您的配合及谅解,祝您游戏愉快!\n\n光环助手会持续关注产品建议及反馈,如您在使用过程中有任何问题,欢迎向我们反馈。</string>
|
||||
<string name="teenager_mode_description">开启青少年模式后,系统将自动关闭所有游戏的下载功能,需要输入密码才能恢复使用\n\n开启青少年模式,需要先设置独立密码,如忘记密码可联系客服申述重置\n\n青少年模式是光环助手响应国家政策,为促进青少年健康成长的一种模式,我们优先针对核心场景进行优化,也将继续致力于优化更多场景</string>
|
||||
|
||||
<string name="dialog_sync_certification_content">您是否同意将您在光环平台游戏内的实名信息与状态同步至光环助手,您的信息将仅用于\n1、部分游戏在助手内无需再次实名即可下载\n2、游戏内使用快速认证方式,无需重复实名</string>
|
||||
|
||||
</resources>
|
||||
|
||||
Reference in New Issue
Block a user