Xiaomi game APK access

1. The steps for laya are the same as those for packaging other apk.
Special attention needs to be paid to:
Attached Xiaomi SDK privacy agreement to the game privacy agreement: This game is connected to Xiaomi game services
SDK, providing login and payment and real-name services. Please read the "Xiaomi Game Service Privacy Policy" for the information collected.
https://privacy.mi.com/xiaomigame-sdk/zh_CN/
Regarding the privacy agreement, the work that Android engineering needs to do:
 
Privacy Agreement When the user opens the game for the first time, the relevant privacy agreement needs to be displayed. After the user selects it, call
2.android project, sdk initialization:
Development environment and version requirements:
1. To connect to the SDK, the game also needs to rely on Android Support V4, version 27.1.1 or above.
2.Andoird Studio recommends 3.0.0 or above, Gradle recommends 3.6.3 or above, and JDK recommends 1.8
3.targetSdkVersion requires >=26
4.minSdkVersion recommended>=18, compileSdkVersion recommended>=28, targetSdkVersion>=26, buildToolsVersion recommended 28.0.3
classpath 'com.android.tools.build:gradle:3.6.3'
It should be noted that the Gradle configuration here is The configuration of gradle plugin needs to correspond to gradle version:
The development environment configuration is as follows:
android {
    compileSdkVersion 29
    buildToolsVersion "30.0.2"
    useLibrary 'org.apache.http.legacy'
    defaultConfig {
        applicationId "com.cszs.jgdnc.mi"
        minSdkVersion 24
        targetSdkVersion 28
        versionCode 1
        versionName "2.0"
    }
    sourceSets.main{
        jniLibs.srcDir 'libs'
    }
    buildTypes {
        release {
            minifyEnabled false
            proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
        }
    }
    
    compileOptions {
        targetCompatibility JavaVersion.VERSION_1_8
        sourceCompatibility JavaVersion.VERSION_1_8
    }
}
First access the sdk of the online game:
(1) Introduce files in the res and lib folders
* Create an application on Xiaomi Developer and obtain the AppId, AppKey and AppSecret (note that AppSecret is used for server-side signature, do not use it on the client). When creating an application, if it is a game, the PackageName must be suffixed with ".mi".
* Completely add the resources in the res directory in the SDK package to the res directory of the game Android project. If there are conflicts in styles, they can be modified as appropriate.
* Place the files in the libs directory of the SDK package in the libs directory of your project (the name of the mio_sdk_base_3.2.0_12748.jar package in the picture will change according to different versions. The actual name shall prevail. Some third-party packages It may also change due to different versions, whichever is actual), reference it in the buildpath, and then initialize the SDK (if x86 is not supported, do not copy the x86 directory and its contents, because armeabi-v7a is compatible with armeabi, armeabi-v7a or The so files under armeabi are actually the same, please put them in the directory of armeabi-v7a and/or armeabi architecture that your game actually supports).
Library file path:
New files in the arm64-v8a folder, armeabi-v7a file, and x86 folder:
Then add the folder:
Possible errors:
Solution: Add dependencies back
implementation 'com.android.support:appcompat-v7:22.1.1'
(2) Introduce the jar package body:
implementation files('libs/mio_sdk_base_3.2.8_12822.jar')
implementation files('libs/alipaySdk-20180601.jar')
implementation files('libs/eventbus-3.0.0.jar')
implementation files('libs/gaid.jar')
implementation files('libs/onetrack-sdk-1.1.3.jar')
implementation files('libs/org.apache.http.legacy.jar')
implementation files('libs/protobuf-java-2.6.1.jar')
implementation files('libs/zxing-3.1.0.jar')
(3) SDK initialization code: Create MMApplication.java under the demo package and initialize Xiaomi sdk:
package demo;


import android.support.multidex.MultiDexApplication;
import android.util.Log;

//这些包要等小米的广告sdk包引入后再引入
import com.xiaomi.ad.mediation.internal.config.IMediationConfigInitListener;
import com.xiaomi.ad.mediation.mimonew.MIMOAdSdkConfig;
import com.xiaomi.ad.mediation.mimonew.MiMoNewSdk;

import com.cszs.jgdnc.mi.R;  //这里包名要改

import com.xiaomi.gamecenter.sdk.MiCommplatform;
import com.xiaomi.gamecenter.sdk.MiErrorCode;
import com.xiaomi.gamecenter.sdk.OnInitProcessListener;
import com.xiaomi.gamecenter.sdk.OnLoginProcessListener;
import com.xiaomi.gamecenter.sdk.entry.MiAccountInfo;
import com.xiaomi.gamecenter.sdk.entry.MiAppInfo;


import java.util.List;


/**
* Copyright (C) 2013, Xiaomi Inc. All rights reserved.
*/


public class MMApplication  extends MultiDexApplication {
    private static final String TAG = "MMApplication";
    private static MainActivity mActivity;


    private static final String APPID = "2882303761520039686";




    @Override
    public void onCreate() {
        super.onCreate();
        //网游sdk初始化
        MiAppInfo appInfo = new MiAppInfo();
        //正式环境下的appid
        appInfo.setAppId(APPID);
        //测试广告包的appid
//        appInfo.setAppId("2882303761517973922");
        //正式包体的appKey
        appInfo.setAppKey("5852003941686");
//        appInfo.setAppKey("");
        Log.d("initSDK", "initSDK");
        MiCommplatform.Init(this, appInfo, new OnInitProcessListener() {
            @Override
            public void finishInitProcess(List<String> loginMethod, int gameConfig) {
                Log.i("Demo","Init success");
            }
            @Override
            public void onMiSplashEnd() {
                //小米闪屏⻚结束回调,小米闪屏可配,无闪屏也会返回此回调,游戏的闪屏应当在收到此回调之后
            }
        });
    }
    
}

Then declare this Application in AndroidManifest.xml:
These two lines of code are very important and cannot be left out! ! !
android:extractNativeLibs="true"
android:name="demo.MMApplication"
A problem may arise here:
Solution: It turns out that introducing the package is not enough; Need to introduce dependencies  build.gradle file:  :
/**sdk**/
implementation 'com.github.bumptech.glide:glide:4.9.0'
annotationProcessor 'com.github.bumptech.glide:compiler:4.9.0'
implementation 'com.google.code.gson:gson:2.8.5'
implementation 'com.android.support:multidex:1.0.3'
(4) New permissions are required in AndroidManifest.xml:
<uses-permission android:name="com.xiaomi.permission.AUTH_SERVICE"/>
<uses-permission android:name="com.xiaomi.sdk.permission.PAYMENT" />
(5) If you run it directly at this time, an error will be reported, because The activity configuration and resource files required for running are missing : Please ensure that the following Activity is declared in AndroidManifest.xml: [com.xiaomi.gamecenter.sdk .ui.MiActivity, com.xiaomi.gamecenter.sdk.ui.PayListActivity, com.xiaomi.hy.dj.HyDjActivity, com.alipay.sdk.app.H5PayActivity, com.xiaomi.gamecenter.sdk.ui.notice.NoticeActivity , com.xiaomi.gamecenter.sdk.ui.fault.ViewFaultNoticeActivity, com.xiaomi.gamecenter.sdk.anti.ui.MiAntiAlertActivity, com.xiaomi.gamecenter.sdk.ui.MiPayAntiActivity, ]
Solution: The AndroidManifest manifest configuration required by the SDK, is configured in AndroidManifest.xml:


<!-- Xiaomi SDK Need -->
<meta-data
    android:name="notch.config"
    android:value="portrait|landscape" />


<activity
    android:name="com.xiaomi.gamecenter.sdk.ui.MiActivity"
    android:configChanges="orientation|screenSize"
    android:screenOrientation="behind"
    android:theme="@android:style/Theme.Light.NoTitleBar.Fullscreen">


</activity>
<activity
    android:name="com.xiaomi.gamecenter.sdk.ui.PayListActivity"
    android:configChanges="orientation|screenSize"
    android:exported="true"
    android:theme="@android:style/Theme.Light.NoTitleBar.Fullscreen" />
<activity
    android:name="com.xiaomi.hy.dj.HyDjActivity"
    android:configChanges="orientation|screenSize"
    android:exported="true"
    android:theme="@android:style/Theme.Light.NoTitleBar.Fullscreen" />
<activity
    android:name="com.alipay.sdk.app.H5PayActivity"
    android:configChanges="orientation|keyboardHidden|navigation|screenSize"
    android:exported="false"
    android:screenOrientation="behind"
    android:windowSoftInputMode="adjustResize|stateHidden" />
<!--不支持${applicationId}的请替换为包名-->


<provider
    android:name="com.xiaomi.gamecenter.sdk.utils.MiFileProvider"
    android:authorities="${applicationId}.mi_fileprovider"
    android:exported="false"
    android:grantUriPermissions="true">
    <meta-data
        android:name="android.support.FILE_PROVIDER_PATHS"
        android:resource="@xml/mio_file_paths" />
</provider>




<activity
    android:name="com.xiaomi.gamecenter.sdk.ui.fault.ViewFaultNoticeActivity"
    android:configChanges="orientation|screenSize"
    android:excludeFromRecents="true"
    android:screenOrientation="behind"
    android:theme="@android:style/Theme.Light.NoTitleBar.Fullscreen" />


<activity
    android:name="com.xiaomi.gamecenter.sdk.ui.notice.NoticeActivity"
    android:configChanges="orientation|screenSize"
    android:excludeFromRecents="true"
    android:screenOrientation="behind"
    android:theme="@android:style/Theme.Light.NoTitleBar.Fullscreen" />


<activity
    android:name="com.xiaomi.gamecenter.sdk.anti.ui.MiAntiAlertActivity"
    android:configChanges="orientation|screenSize"
    android:excludeFromRecents="true"
    android:screenOrientation="behind"
    android:theme="@android:style/Theme.Light.NoTitleBar.Fullscreen">
    <intent-filter>
        <data
            android:host="open_anti_alert"
            android:scheme="mioauthsdk" />
        <category android:name="android.intent.category.DEFAULT" />
        <action android:name="android.intent.action.VIEW" />
    </intent-filter>
</activity>
<activity
    android:name="com.xiaomi.gamecenter.sdk.ui.MiPayAntiActivity"
    android:configChanges="orientation|screenSize"
    android:screenOrientation="behind"
    android:theme="@android:style/Theme.Light.NoTitleBar.Fullscreen" />


<activity android:name="com.xiaomi.gamecenter.sdk.ui.MiVerifyActivity"
    android:configChanges="orientation|screenSize"
    android:theme="@android:style/Theme.Light.NoTitleBar.Fullscreen"
    android:screenOrientation="behind"/>


<!-- Xiaomi SDK Need End-->

After configuring AndroidManifest.xml, since these activities rely on many xml files for layout, all dependent xml files must be copied to the corresponding folders. There are many files, and none of them can be missing. They are all dependent on each other, which is very difficult. trouble:
also, Introducing this xml layout file is not enough. You need to introduce the dependencies of these xml layout files into the build.gradle file:
/**Introduce some dependencies required for xml layout**/
implementation 'com.android.support.constraint:constraint-layout:1.1.3'
implementation 'com.android.support:design:28.0.0'
implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk8:1.3.31"
implementation 'com.jakewharton:butterknife:8.8.1'
annotationProcessor 'com.jakewharton:butterknife-compiler:8.8.1'
implementation 'android.arch.navigation:navigation-fragment:1.0.0'
implementation 'android.arch.navigation:navigation-ui:1.0.0'
implementation 'android.arch.lifecycle:extensions:1.1.1'
(6) If you run it directly at this time, an error will be reported because The jsBridge-mix.js file is missing:
Caused by: java.lang.IllegalStateException: Please ensure that the file exists in the Assets directory: jsBridge-mix.js
Solution:
Add to here:
(7) I tried to package, but during the packaging process, an error was reported:
Solution: In the gradle.properties file, add:
android.enableBuildCache=false
(8) Call Xiaomi SDK login interface: The login interface must be called every time you log in to the game: define the login interface in MMApplication.java:
public void initSDK(MainActivity _mActivity){
    mActivity =_mActivity;
    
    MiCommplatform.getInstance().miLogin(mActivity,
            new OnLoginProcessListener()
            {
                @Override
                public void finishLoginProcess(int code , MiAccountInfo arg1)
                {
                    switch( code )
                    {
                        case MiErrorCode.MI_XIAOMI_PAYMENT_SUCCESS:// 登陆成功
                            Log.i(TAG,"小米登录成功");


                            //获取用户的登陆后的UID(即用户唯一标识)
                            String uid = arg1.getUid();
                            //以下为获取session并校验流程,如果是网络游戏必须校验,(12小时过期)
                            //获取用户的登陆的Session(请参考5.3.3流程校验Session有效性)
                            String session = arg1.getSessionId();
                            //请开发者完成将uid和session提交给开发者自己服务器进行session验证
                            break;
                        case MiErrorCode.MI_XIAOMI_PAYMENT_ERROR_LOGIN_FAIL:
                            Log.i(TAG,"登录失败");
                            // 登陆失败
                            break;
                        case MiErrorCode.MI_XIAOMI_PAYMENT_ERROR_CANCEL:
                            Log.i(TAG,"取消登录");
                            // 取消登录
                            break;
                        case MiErrorCode.MI_XIAOMI_PAYMENT_ERROR_ACTION_EXECUTED:
                            //登录操作正在进行中
                            Log.i(TAG,"登录操作正在进行中");
                            break;
                        default:
                            // 登录失败
                            Log.i(TAG,"登录失败");
                            break;
                    }
                }
            } );
}

(9) Required interface, the game exit interface is defined in MainActivity.java:
 
public void  exitGame(){
    MiCommplatform.getInstance().miAppExit( this, new OnExitListner()
    {
        @Override
        public void onExit( int code )
        {
            Log.i("Demo","小米游戏退出");
            if ( code == MiErrorCode.MI_XIAOMI_EXIT )
            {
                android.os.Process.killProcess( android.os.Process.myPid() );
            }
        }
    } );
}

3. Advertising sdk access:
(1) Introduce the aar package of advertising sdk: The correct way to introduce the aar package is as follows
implementation files('libs/mimo_sdk.aar')
When using the wrong reference method, an error may occur: Could not resolve all files for configuration ':app:debugCompileClasspath'.
Solution: Place google() in front of jcenter()
buildscript {
    repositories {
        google()
        jcenter()
        mavenCentral()
        maven { url 'https://maven.aliyun.com/repository/google'}
    }
    dependencies {
        classpath 'com.android.tools.build:gradle:3.6.3'
        // NOTE: Do not place your application dependencies here; they belong
        // in the individual module build.gradle files
    }
}
allprojects {
    repositories {
        google()
        jcenter()
        mavenCentral()
        maven {url 'https://dl.bintray.com/jetbrains/anko'}
        maven {url 'https://maven.aliyun.com/repository/google'}
    }
}
If this still doesn’t work, try another reference method:
dependencies {
    implementation fileTree(dir: 'libs', include: ['*.jar','*.aar'])
    testImplementation 'junit:junit:4.12'
    implementation 'com.android.support:appcompat-v7:22.1.1'
    implementation 'com.android.support:support-v4:27.1.1'
    implementation files('libs/mio_sdk_base_3.2.8_12822.jar')
    implementation files('libs/alipaySdk-20180601.jar')
    implementation files('libs/eventbus-3.0.0.jar')
    implementation files('libs/gaid.jar')
    implementation files('libs/onetrack-sdk-1.1.3.jar')
    implementation files('libs/org.apache.http.legacy.jar')
    implementation files('libs/protobuf-java-2.6.1.jar')
    implementation files('libs/zxing-3.1.0.jar')
    implementation files('libs/mimo_sdk.aar')
}
(2) Advertising sdk initialization: Initialized in MMapplication.java: Here the advertising sdk initialization and calling the login interface are placed in the initSDK function:
Because the SDK initialization interface must be called after the user chooses whether to unify the privacy agreement, if the user rejects the privacy agreement, the advertising SDK initialization interface cannot be called, so must be called after calling android privacy In the policy pop-up window, click Agree before calling the initSDK function here
The appid here is the test id during the test, and the advertising sdk needs to be set to test mode:
Otherwise, an error message for loading ads will appear: -400
 
   public void initSDK(MainActivity _mActivity){
        mActivity =_mActivity;


        //广告sdk初始化
        Log.i(TAG,"广告sdk初始化");
        MiMoNewSdk.init(this, APPID, getString(R.string.app_name),
                new MIMOAdSdkConfig.Builder()
                        .setDebug(false)
                        .setStaging(false).build(), new IMediationConfigInitListener() {
                    @Override
                    public void onSuccess() {
                        Log.i(TAG,"广告sdk初始化成功");
                    }

                    @Override
                    public void onFailed(int errorCode) {
                        Log.i(TAG,"广告sdk初始化失败"+errorCode);
                    }
                });

        MiCommplatform.getInstance().miLogin(mActivity,
                new OnLoginProcessListener()
                {
                    @Override
                    public void finishLoginProcess(int code , MiAccountInfo arg1)
                    {
                        switch( code )
                        {
                            case MiErrorCode.MI_XIAOMI_PAYMENT_SUCCESS:// 登陆成功
                                Log.i(TAG,"小米登录成功");


                                //获取用户的登陆后的UID(即用户唯一标识)
                                String uid = arg1.getUid();
                                //以下为获取session并校验流程,如果是网络游戏必须校验,(12小时过期)
                                //获取用户的登陆的Session(请参考5.3.3流程校验Session有效性)
                                String session = arg1.getSessionId();
                                //请开发者完成将uid和session提交给开发者自己服务器进行session验证
                                break;
                            case MiErrorCode.MI_XIAOMI_PAYMENT_ERROR_LOGIN_FAIL:
                                Log.i(TAG,"登录失败");
                                // 登陆失败
                                break;
                            case MiErrorCode.MI_XIAOMI_PAYMENT_ERROR_CANCEL:
                                Log.i(TAG,"取消登录");
                                // 取消登录
                                break;
                            case MiErrorCode.MI_XIAOMI_PAYMENT_ERROR_ACTION_EXECUTED:
                                //登录操作正在进行中
                                Log.i(TAG,"登录操作正在进行中");
                                break;
                            default:
                                // 登录失败
                                Log.i(TAG,"登录失败");
                                break;
                        }
                    }
                } );
    }

When developers access the SDK, the application package may not have been put on the app store. When accessing, it is recommended to use the test advertising space in the demo for debugging, and then switch to the official environment and replace it with the official environment after ensuring that there are no problems with the access method. Advertising slot id. The APP_ID used in the test is: 2882303761517973922
advertisement type
Test ad slot ID
Width
28e12557924f47bcde1fb4122527a6bc
Horizontal interstitial advertising
dc7cc080d643693f4f835b1a7718283d
Vertical interstitial advertising
a61183c0f3899bc138a320925df3d862
Horizontal full screen interstitial advertising
756c0d2cdb935266522249c90ca04dbe
Vertical full-screen interstitial advertising
b539ee9934e2e869c6aced477a02fa0e
Horizontal rewarded video ads
feff23d4d67802626433de32bd1b327d
Vertical rewarded video ads
95297e164e1dfb6c0ce4a2eaf61cc791
Open the screen horizontally
f22820b630d6d453f956cbe31235d11a
Native template - picture above and below (with title)
bfa05071958648861ef32be94c4ac200
Native template - text on the left and image on the right (with title)
77c1a503091c597f8a03d57010637d7c
Native template - picture on the left and text on the right (version A with title)
8db571afaf731ec727d42db9894d688d
Native template - picture on the left and text on the right (version B with title)
5d1bab599fc4443c17021ea75dfa729d
Native template - picture above and below (large picture)
671f83d6d6c1f2356c1a14de9f7ec9cf
Native template - picture above and below (group picture)
b72a783f1f1952c09e429f777cf2426e
Self-rendering - big picture of information flow
c09e2a394366b0819fd3ac2bc142ed20
Self-rendering - information flow thumbnail
11cc7b67acfc800ac6228af78f122acf
Self-rendering - information flow diagram
949f4411ceceb8d14042dffb1112af6b
(3) Modification provider statement required by SDK:
 
Add the file file_paths.xml under res/xml/ for reference demo
content:
      
   <?xml version="1.0" encoding="utf-8"?>
        <paths>
            <files-path name="tt_internal_file_download" path="Download" />
            <cache-path name="tt_internal_cache_download" path="Download" />
        </paths>
**/
/**
在 res/xml/下添加文件 mimo_file_paths.xml 参考demo
内容:
  <?xml version="1.0" encoding="utf-8"?>
  <paths>
    <external-path path="mimoDownload" name="files_root" />
    <external-path path="." name="external_storage_root" />
  </paths>
**/

AndroidMainfest.xml新增provider声明:


<!-- 广告sdk需要的-->
<provider
    android:name="com.bytedance.sdk.openadsdk.TTFileProvider"
    android:authorities="${applicationId}.TTFileProvider"
    android:exported="false"
    android:grantUriPermissions="true">
    <meta-data
        android:name="android.support.FILE_PROVIDER_PATHS"
        android:resource="@xml/file_paths" />
</provider>
<provider
    android:name="com.bytedance.sdk.openadsdk.multipro.TTMultiProvider"
    android:authorities="${applicationId}.TTMultiProvider"
    android:exported="false" />
<provider
    android:name="android.support.v4.content.FileProvider"
    android:authorities="${applicationId}.fileprovider"
    android:exported="false"
    android:grantUriPermissions="true">
    <meta-data
        android:name="android.support.FILE_PROVIDER_PATHS"
        android:resource="@xml/mimo_file_paths" />
</provider>

4.Banner access:
Xiaomi's banner advertisement requires creating a ViewGround in the android project and rendering it inside. The specific steps are:
(1) Create a new activity_main.xml file:
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    tools:ignore="HardcodedText"
    android:layout_width="match_parent"
    android:layout_height="match_parent">
    <!-- BannerView的Container -->
    <FrameLayout
        android:id="@+id/game_container"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_centerInParent="true"
        android:background="#D5D5D5" />
    <FrameLayout
        android:id="@+id/banner_container"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_centerInParent="true"
        android:background="#D5D5D5"
        android:layout_alignParentBottom="true"/>


</RelativeLayout>

(2) Reset ContentView in MainActivity’s initEngin:
//声明变量先:
private ViewGroup gameContainer;
public ViewGroup banner_container;


public void initEngine()
    {
        mProxy = new RuntimeProxy(this);
        mPlugin = new GameEngine(this);
        mPlugin.game_plugin_set_runtime_proxy(mProxy);
        mPlugin.game_plugin_set_option("localize","false");
        mPlugin.game_plugin_set_option("gameUrl", App_Startup_Entry);
        mPlugin.game_plugin_init(3);
        View gameView = mPlugin.game_plugin_get_view();
        this.setContentView(R.layout.activity_main);
        this.gameContainer = findViewById(R.id.game_container);
        this.banner_container = findViewById(R.id.banner_container);
        this.gameContainer.addView(gameView);

        mProxy.InitAD();

        isLoad=true;
    }

(3) The interface getApplication(), which is needed to create a banner, needs to call the MMApplication.java created before:
5. Review rejection: Automated test rejection, for Android 9 and 10 machines, reason: Failed to install /tmp/.omni/apks/0915153229_null_0255928c3835f474ea0a7fffe9f5b9b4b83f8ac40.apk: Failure [INSTALL_FAILED_INVALID_APK: Failed to extract native libraries, res=-2]
Solution: Open AndroidManifest.xml   Add in the application node:
android:extractNativeLibs="true"
6. Review and rejection:
Solve the problem:
(1) Hide status bar and virtual keys:
[Tencent Documentation] How to hide the status bar and virtual keys How to hide the status bar and virtual keys . Test model: MI11 MIUI12.5 stable version
View decorView = getWindow().getDecorView();
int visibility = View.SYSTEM_UI_FLAG_LAYOUT_STABLE
        | View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN | View.SYSTEM_UI_FLAG_FULLSCREEN //Hide the status bar
        | View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION | View.SYSTEM_UI_FLAG_HIDE_NAVIGATION //Hide virtual keys
        | View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY;
decorView.setSystemUiVisibility(visibility);
//On versions greater than android P, you need to set flag: LAYOUT_IN_DISPLAY_CUTOUT_MODE_SHORT_EDGES to ensure that the application can display the notch area.
//If this flag is set, on notch screen phones, pay attention to the position of the internal controls of the application, which should be kept at a certain distance from the edge of the screen to prevent occlusion.
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) {
    getWindow().getAttributes().layoutInDisplayCutoutMode = WindowManager.LayoutParams.LAYOUT_IN_DISPLAY_CUTOUT_MODE_SHORT_EDGES;
}
(2) Set the app to full screen:
<style name="Theme.AppCompat.NoActionBar">
    <item name="windowActionBar">false</item>
    <item name="windowNoTitle">true</item>
</style>
7. Review and rejection issues:
8. Problem that the close button is not displayed after it is defined in the xml file: Solution:
(1) RelativeLayout or FrameLayout layout, if you do not set the position and fill the entire layout view later, it will be covered, check it yourself!
(2) Modify the xml attribute in ImageView:
<ImageView
    android:id="@+id/view_ad_close"
    android:layout_width="35dp"
    android:layout_height="35dp"
    android:layout_marginTop="8dp"
    android:layout_marginEnd="40dp"
    android:layout_marginBottom="16dp"
    android:contentDescription="Close button"
    android:src="@drawable/float_hide_tip_sel"
    app:layout_constraintBottom_toTopOf="@+id/view_desc"
    app:layout_constraintEnd_toEndOf="parent"
    app:layout_constraintStart_toEndOf="@+id/view_title"
    app:layout_constraintTop_toTopOf="parent"
    app:layout_constraintVertical_bias="1.0" />
(3) It has nothing to do with whether the picture is in jpg or png format! !
9. Audit failure problem: the real-name authentication pop-up window is closed
Solution:
(1) In the call to agree to the privacy agreement, pass in the callback: JSBridge.java
//Called after the user agrees to the privacy agreement
public static void onUserAgreed(String json) {
    Log.e("1111111", "User agrees to privacy policy");
    try {
        JSONObject jsonObj = new JSONObject(json);
        ((MainActivity) JSBridge.mMainActivity).onUserAgreed(jsonObj, new ValueCallback<JSONObject>() {
            @Override
            public void onReceiveValue(JSONObject value) {
                ExportJavaFunction.CallBackToJS(JSBridge.class, "onUserAgreed", value.toString());
            }
        });
    } catch (JSONException e) {
        e.printStackTrace();
    }
}
Called in MainActivity.java: Only when the login is successful will a result=1 in the js layer be called back, otherwise the game will be exited;
public void onUserAgreed(JSONObject jsonObj, final ValueCallback<JSONObject> callback){
        Log.d("UserAgreed", "Login info = " + jsonObj.toString());
        if (Build.VERSION.SDK_INT > Build.VERSION_CODES.LOLLIPOP_MR1) {
            /**
             * 如果你的targetSDKVersion >= 23,就要主动申请好权限。如果您的App没有适配到Android6.0(即targetSDKVersion < 23),那么只需要在这里直接调用fetchSplashAd方法。
             *
             */
            checkAndRequestPermissions();
        } else {
            /**
             * 如果是Android6.0以下的机器,默认在安装时获得了所有权限,可以直接调用SDK。
             */
        }


        MiCommplatform.getInstance().onUserAgreed(this);
        MiCommplatform.getInstance().miLogin(this,
                new OnLoginProcessListener()
                {
                    @Override
                    public void finishLoginProcess(int code , MiAccountInfo arg1)
                    {
                        switch( code )
                        {
                            case MiErrorCode.MI_XIAOMI_PAYMENT_SUCCESS:// 登陆成功
                                Log.i("Demo","小米登录成功");

                                //获取用户的登陆后的UID(即用户唯一标识)
                                String uid = arg1.getUid();
                                //以下为获取session并校验流程,如果是网络游戏必须校验,(12小时过期)
                                //获取用户的登陆的Session(请参考5.3.3流程校验Session有效性)
                                String session = arg1.getSessionId();
                                //请开发者完成将uid和session提交给开发者自己服务器进行session验证
                                Log.e("UserAgreed", "登陆成功");
                                JSONObject result3 = new JSONObject();
                                try {
                                    result3.put("result", 1);
                                } catch (JSONException e) {
                                    e.printStackTrace();
                                }
                                callback.onReceiveValue(result3);
                                break;
                            case MiErrorCode.MI_XIAOMI_PAYMENT_ERROR_LOGIN_FAIL:
                                loginFail(callback);
                                // 登陆失败
                                break;
                            case MiErrorCode.MI_XIAOMI_PAYMENT_ERROR_CANCEL:
                                loginFail(callback);
                                // 取消登录
                                break;
                            case MiErrorCode.MI_XIAOMI_PAYMENT_ERROR_ACTION_EXECUTED:
                                //登录操作正在进行中
                                break;
                            default:
                                // 登录失败
                                loginFail(callback);
                                break;
                        }
                    }
                } );


    }

Login failed callback:
 
public void loginFail(final ValueCallback<JSONObject> callback){
    Log.e("UserAgreed", "登陆失败");
    JSONObject result = new JSONObject();
    try {
        result.put("result", 0);
    } catch (JSONException e) {
        e.printStackTrace();
    }
    callback.onReceiveValue(result);
}

(2)退出游戏:

MainActivity.java:

public void  exitGame(){
    MiCommplatform.getInstance().miAppExit( this, new OnExitListner()
    {
        @Override
        public void onExit( int code )
        {
            Log.i("Demo","小米游戏退出");
            if ( code == MiErrorCode.MI_XIAOMI_EXIT )
            {
                android.os.Process.killProcess( android.os.Process.myPid() );
            }
        }
    } );
}

JSBridge.java:
//exit the game
public static void ExitGame(){
    ((MainActivity) JSBridge.mMainActivity).exitGame();
}
The functions at the js level are as follows:
        static onUserAgreed(thisAry, callback) {
            if (!this.isReady) {
                callback({ result: 1 });
                return;
            }
            let obj = {};
            this.bridge.callWithBack((value) => {
                console.log("JS layer login callback", value)
                console.log(value)
                if (callback) {
                    let jsonObj = JSON.parse(value);
                    callback.call(thisAry, jsonObj);
                }
            }, 'onUserAgreed', JSON.stringify(obj));
        }
        static ExitGame() {
            console.log("Exit game");
            if (!this.isReady)
                return;
            this.bridge.callWithBack(null, 'ExitGame');
        }
10. Ad loading error: This error is that the ad type selected in the background does not match the ad type actually requested and has been filtered.
Template ad loading error {errorCode=-300, externalErrorCode='301007', errorMessage=''}
11. Permission issue: Advertising SDK should not be initialized before using it to agree to the terms of the privacy policy
Solution: Only call login and advertising sdk initialization after agreeing to the privacy policy:
In MainActivity.java:
 
public void onUserAgreed(JSONObject jsonObj, final ValueCallback<JSONObject> callback){
    Log.d("UserAgreed", "Login info = " + jsonObj.toString());
    if (Build.VERSION.SDK_INT > Build.VERSION_CODES.LOLLIPOP_MR1) {
        /**
         * 如果你的targetSDKVersion >= 23,就要主动申请好权限。如果您的App没有适配到Android6.0(即targetSDKVersion < 23),那么只需要在这里直接调用fetchSplashAd方法。
         *
         */
        checkAndRequestPermissions();
    } else {
        /**
         * 如果是Android6.0以下的机器,默认在安装时获得了所有权限,可以直接调用SDK。
         */
    }
    MiCommplatform.getInstance().onUserAgreed(this);


    MMApplication mApplication = (MMApplication) getApplication();
    mApplication.initSDK(callback,this);
}

MMApplication.java中,但是联运SDK的初始化,还是应该在onCreate函数中调用才行,不然会无法运行apk

    public void initSDK(final ValueCallback<JSONObject> callback, MainActivity _mActivity){
        mActivity =_mActivity;


        MiCommplatform.getInstance().miLogin(mActivity,
                new OnLoginProcessListener()
                {
                    @Override
                    public void finishLoginProcess(int code , MiAccountInfo arg1)
                    {
                        switch( code )
                        {
                            case MiErrorCode.MI_XIAOMI_PAYMENT_SUCCESS:// 登陆成功
                                Log.i("Demo","小米登录成功");


                                //获取用户的登陆后的UID(即用户唯一标识)
                                String uid = arg1.getUid();
                                //以下为获取session并校验流程,如果是网络游戏必须校验,(12小时过期)
                                //获取用户的登陆的Session(请参考5.3.3流程校验Session有效性)
                                String session = arg1.getSessionId();
                                //请开发者完成将uid和session提交给开发者自己服务器进行session验证
                                Log.e("UserAgreed", "登陆成功");
                                JSONObject result3 = new JSONObject();
                                try {
                                    result3.put("result", 1);
                                } catch (JSONException e) {
                                    e.printStackTrace();
                                }
                                callback.onReceiveValue(result3);
                                break;
                            case MiErrorCode.MI_XIAOMI_PAYMENT_ERROR_LOGIN_FAIL:
                                mActivity.loginFail(callback);
                                // 登陆失败
                                break;
                            case MiErrorCode.MI_XIAOMI_PAYMENT_ERROR_CANCEL:
                                mActivity.loginFail(callback);
                                // 取消登录
                                break;
                            case MiErrorCode.MI_XIAOMI_PAYMENT_ERROR_ACTION_EXECUTED:
                                //登录操作正在进行中
                                break;
                            default:
                                // 登录失败
                                mActivity.loginFail(callback);
                                break;
                        }
                    }
                } );
        //广告sdk初始化
        MiMoNewSdk.init(this, APPID, getString(R.string.app_name),
                new MIMOAdSdkConfig.Builder()
                        .setDebug(false)
                        .setStaging(false).build(), new IMediationConfigInitListener() {
                    @Override
                    public void onSuccess() {
                        MLog.d(TAG, "mediation config init success");
                        mActivity.mProxy.InitAD();
                    }


                    @Override
                    public void onFailed(int errorCode) {
                        MLog.d(TAG, "mediation config init failed");
                    }
                });
    }

12. The tentative game timeline in Xiaomi apk can be used:
if(Laya.timer.scale == 1)Laya.timer.pause();
if(Laya.timer.scale == 0)Laya.timer.resume()
13. Access and open the webpage in Xiaomi apk:
(1) Define VIEW in xml:
<FrameLayout
    android:id="@+id/view_url_container"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:layout_marginLeft="0dp"
    android:layout_marginTop="0dp"
    android:layout_marginRight="0dp"
    android:layout_marginBottom="0dp"
    android:background="#FFFFFF">


    <WebView
        android:layout_width="fill_parent"
        android:layout_height="fill_parent"
        android:id="@+id/wv"
        android:layout_alignParentLeft="true"
        android:layout_alignParentStart="true"
        android:layout_alignParentTop="true" />


    <ImageView
        android:id="@+id/view_url_close"
        android:layout_width="32dp"
        android:layout_height="32dp"
        android:layout_marginStart="9dp"
        android:layout_marginTop="20dp"
        android:layout_marginEnd="400dp"
        android:contentDescription="关闭按钮"
        android:src="@drawable/float_hide_tip_sel"
        app:layout_constraintBottom_toTopOf="@+id/view_feedBox_image"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintHorizontal_bias="0.78"
        app:layout_constraintStart_toEndOf="@+id/view_feedBox_image"
        app:layout_constraintTop_toTopOf="parent"
        app:layout_constraintVertical_bias="0.0" />

(2) Define the class that opens the View:
 
public class SecretUrlView {


    private MainActivity mActivity;
    private static String TAG = "SecretUrlView";
    private View mView;
    private WebView wv;
    public SecretUrlView(MainActivity mActivity) {
        this.mActivity = mActivity;
        this.init();


    }


    public void init(){


        mView = (ViewGroup) mActivity.urlView_container;


        wv=(WebView)mView.findViewById(R.id.wv);
        WebSettings ws=wv.getSettings();
        ws.setJavaScriptEnabled(true);
        wv.loadUrl("https://res.wqop2018.com//app/common/privacy.html");
        wv.setWebViewClient(new WebViewClient());
        mView.findViewById(R.id.view_url_close).setOnClickListener(new View.OnClickListener() {


            @Override
            public void onClick(View v) {
                mView.setVisibility(View.GONE);
            }
        });
        mView.setVisibility(View.GONE);
    }


    public void showUrlView(){
        mView.setVisibility(View.VISIBLE);


    }


    public  void  hideUrlView(){
        mView.setVisibility(View.GONE);


    }


}

14. Solutions to privacy issues:
(1) Open the game > Pop up the privacy agreement (initialize Xiaomi sdk) > Agree to the privacy agreement > Obtain mobile phone information authorization > Initialize Xiaomi advertising sdk (Xiaomi login) > Log in successfully > Game loading starts
If login fails, you need to continue calling the login interface.
(2) TD initialization needs to be placed after the user agrees to the privacy agreement and agrees to grant permissions
(3) Privacy agreement address: Privacy Policy
"https://res.wqop2018.com/app/web/privacy/v3/privacy.html?app_name=" + Constant.APP_NAME + "&company="+Constant.COMPANY+"&package_name="+Constant.PACKAGE_NAME
15. This does not solve the problem: It is found that obtaining mobile phone information is done when the Laya engine is initialized, so it is necessary to use Android to make a privacy interface, and then initialize the Laya engine after agreeing to privacy:
Read IMEI
发生时间 2021-11-23 10:07:42 md5=5743438D7E55887D2CFA5AFEE84D9F6B,pkg=com.cszs.aycsmnq.mi,action=android.permission.READ_PHONE_STATE_IMEI,content=,callstack:android.telephony.TelephonyManager.getDeviceId:1247;layaair.game.device.DevID.GetIMEI:14;layaair.game.browser.ExportJavaFunction.GetDeviceInfo:28;java.lang.reflect.Method.invoke:-2;layaair.game.browser.ExportJavaFunction.callMethod:43;layaair.game.browser.ConchJNI.OnGLReady:-2;layaair.game.browser.c.a:125;layaair.game.browser.x.i:384;layaair.game.browser.x.run:22;
Read IMSI
发生时间 2021-11-23 10:07:42 md5=5743438D7E55887D2CFA5AFEE84D9F6B,pkg=com.cszs.aycsmnq.mi,action=android.permission.READ_PHONE_STATE_IMSI,content=,callstack:android.telephony.TelephonyManager.getSubscriberId:3030;android.telephony.TelephonyManager.getSubscriberId:3011;layaair.game.device.DevID.GetIMSI:13;layaair.game.browser.ExportJavaFunction.GetDeviceInfo:40;java.lang.reflect.Method.invoke:-2;layaair.game.browser.ExportJavaFunction.callMethod:43;layaair.game.browser.ConchJNI.OnGLReady:-2;layaair.game.browser.c.a:125;layaair.game.browser.x.i:384;layaair.game.browser.x.run:22;
Get MAC address
发生时间 2021-11-23 10:07:42 md5=5743438D7E55887D2CFA5AFEE84D9F6B,pkg=com.cszs.aycsmnq.mi,action=android.permission.GET_MAC,content=wlan0:64:A2:F9:9C:72:1E,callstack:java.net.NetworkInterface.getHardwareAddress:574;layaair.game.device.DevID.getMac:61;layaair.game.device.DevID.GetWifiMac:0;layaair.game.browser.ExportJavaFunction.GetDeviceInfo:95;java.lang.reflect.Method.invoke:-2;layaair.game.browser.ExportJavaFunction.callMethod:43;layaair.game.browser.ConchJNI.OnGLReady:-2;layaair.game.browser.c.a:125;layaair.game.browser.x.i:384;layaair.game.browser.x.run:22;
Read personal information without permission: Read IMEI Read IMSI Get MAC address
16. Occasionally, interstitial advertising errors are reported. It seems that the timing is wrong, and the interstitial advertising is displayed before the advertising sdk is initialized:
java.lang.NullPointerException: Attempt to invoke virtual method 'void demo.ui.fullscreenInterstitialad.InterstitialView.showFullScreenAd(android.webkit.ValueCallback)' on a null object reference
17. Xiaomi must log in to load and enter the game:
(1) Process: After agreeing to the privacy policy in Android, initEngine, then log in on laya's loading page. If the login is successful, call back to laya, and then enter the game home page.
JS layer:
//Xiaomi must log in first
if (window.zs && zs.Native && zs.Native.Login) zs.Native.Login(this, this.apkLoginBack$.bind(this));
    /**
     * * Xiaomi login callback
     */
    apkLoginBack$(data) {
        console.log(data);
        if (data.result == 1) {
            this.loadingComplete$();
        }
    }
apk.mi.js:
        static Login(thisAry, callback) {
            if (!this.isReady)
                return;
            let obj = {};
            obj['uid'] = "uid";
            this.bridge.callWithBack((value) => {
                if (callback) {
                    let jsonObj = JSON.parse(value);
                    callback.call(thisAry, jsonObj);
                }
            }, 'Login', JSON.stringify(obj));
        }
(2) Android project in progress:
******JSBridge.java
public static void Login(String json){
    try {
        JSONObject jsonObj = new JSONObject(json);
        MainActivity.mProxy.loginMi(jsonObj, new ValueCallback<JSONObject>() {
            @Override
            public void onReceiveValue(JSONObject value) {
                ExportJavaFunction.CallBackToJS(JSBridge.class, "Login", value.toString());
            }
        });
    } catch (JSONException e) {
        e.printStackTrace();
    }
}
******RuntimeProxy.java:
@Override
public void loginMi(JSONObject jsonObj, final ValueCallback<JSONObject> callback) {
    Log.d(TAG, "loginMi " + jsonObj.toString());
    if (hasNecessaryPMSGranted()) {
        new Thread(new Runnable() {
            @Override
            public void run() {
                mActivity.runOnUiThread(new Runnable() {
                    @Override
                    public void run() {
                        mActivity.loginMi(callback);
                    }
                });
            }
        }).start();
    } else {
        Toast.makeText(mActivity, "Without READ_PHONE_STATE or WRITE_EXTERNAL_STORAGE permissions, the SDK cannot run properly!!!", Toast.LENGTH_SHORT).show();
    }
}
******MainActivity.java:
public  void loginMi(ValueCallback<JSONObject> callback_){
    MMApplication mApplication = (MMApplication) getApplication();
    mApplication.loginMI(callback_);
}
******MMApplication.java:
public void loginMI(ValueCallback<JSONObject> callback_){
    if(loginSuccess)return;
    callback = callback_;
    Log.i(TAG,"Xiaomi login....");
    MiCommplatform.getInstance().miLogin(mActivity,
            new OnLoginProcessListener()
            {
                @Override
                public void finishLoginProcess(int code , MiAccountInfo arg1)
                {
                    switch( code )
                    {
                        case MiErrorCode.MI_XIAOMI_PAYMENT_SUCCESS:// Login successful
                            Log.i(TAG,"Xiaomi login successful");
                            //Get the user's UID after login (that is, the user's unique identifier)
                            String uid = arg1.getUid();
                            // The following is the process of obtaining the session and checking the process. If it is an online game, it must be verified, (12 hours expires)
                            //Get the user’s login Session (please refer to 5.3.3 process to verify Session validity)
                            String session = arg1.getSessionId();
                            // Please developers to complete the submission of UID and Session to the developer's own server for session verification
                            loginSuccess = true;
                            JSONObject result = new JSONObject();
                            try {
                                result.put("result", 1);
                            } catch (JSONException e) {
                                e.printStackTrace();
                            }
                            callback.onReceiveValue(result);
                            break;
                        case MiErrorCode.MI_XIAOMI_PAYMENT_ERROR_LOGIN_FAIL:
                            Log.i(TAG,"Login failed 22");
                            loginMI(callback_);
                            // Login failed
                            break;
                        case MiErrorCode.MI_XIAOMI_PAYMENT_ERROR_CANCEL:
                            Log.i(TAG,"Cancel Login");
                            loginMI(callback_);
                            
                            break;
                        case MiErrorCode.MI_XIAOMI_PAYMENT_ERROR_ACTION_EXECUTED:
                            
                            Log.i(TAG,"Login operation in progress 333");
                            break;
                        default:
                            // Login failed
                            Log.i(TAG,"Login failed");
                            break;
                    }
                }
            } );
}
18. Advertising loading error reporting:
Self-rendering ad loading error {errorCode=-400, externalErrorCode='', errorMessage='adPositionInfo is null'}
Usually you need to enable debugging:
MiMoNewSdk.init(this, "2882303761517973922", getString(R.string.app_name),
        new MIMOAdSdkConfig.Builder()
                .setDebug(true) // true turns on debugging and outputs debugging logs; false turns off debugging
                .setStaging(true).build(), new IMediationConfigInitListener() { // true turns on the test request switch and requests test advertising; false turns off the test request switch
            @Override
            public void onSuccess() {
                Log.i(TAG,"Advertising sdk initialization successful");
            }
            @Override
            public void onFailed(int errorCode) {
                Log.i(TAG,"Advertising sdk initialization failed"+errorCode);
            }
        });

Guess you like

Origin blog.csdn.net/woshiyuyanjia/article/details/134709000