The privacy policy issue of Android domestic applications, the solution to the problem of loading Html interface in WebView to obtain device information

background

  • Due to national policy reasons, apps or games are required to provide privacy agreement pop-up windows, and device information such as MAC, AndroidID, SSID, WIFI information, etc., must not be obtained before the user agrees to the privacy agreement. When your app is released on major channels We all need to do this function, and the further the implementation of this policy will be, the stronger it will be. At the beginning, just make a privacy pop-up box, and the channel will be able to fool you. Later, the channel will notify you of the privacy agreement. If it is not in compliance, it needs to be rectified, otherwise it will be removed from the shelves. There are too many specific rectification contents. Many major channels have provided detection mechanisms, first machine review and then manual review.

Privacy pop-up window and protocol interface implementation

  • I believe that most applications or games use WebView to load web pages when implementing privacy protocols, because this can dynamically load different privacy protocol addresses as much as possible, and multiple applications can be reused, and the front end can dynamically obtain different URLs. The protocol required by the application and displayed to the user

The WebView method is detected to obtain device information

  • Suddenly one day our app was notified that it had collected user information in violation of regulations. Later, the package was taken to a third-party platform for testing, but it failed. Read information such as location information every 30s, which is not necessary for services and has no reasonable application scenarios, and exceeds the minimum frequency necessary to realize the business functions of products or services; I was a little confused at the beginning, and our application must be used after consent. Obtaining device information, why did I report this suddenly, and the culprit found in the end is this WebView, when we go to load the privacy agreement, it goes back to obtain WIFI, location and other information
  • The chromium SDK obtains the stack information of Wifi information every 2 seconds as follows
    {"stackTrace": [{"className": "libcore.util.Janus", "level": 0, "fileName": "Janus.java", "methodName": "getData", "lineNumber": 831}, {"className": "android.net.wifi.WifiManager", "level": 0, "fileName": "WifiManager.java", "methodName": "getConnectionInfo", "lineNumber": 1676}, {"className": "org.chromium.net.NetworkChangeNotifierAutoDetect$WifiManagerDelegate", "level": 0, "fileName": "NetworkChangeNotifierAutoDetect.java", "methodName": "getWifiInfoLocked", "lineNumber": 28}, {"className": "org.chromium.net.NetworkChangeNotifierAutoDetect$WifiManagerDelegate", "level": 0, "fileName": "NetworkChangeNotifierAutoDetect.java", "methodName": "getWifiSsid", "lineNumber": 22}, {"className": "org.chromium.net.NetworkChangeNotifierAutoDetect", "level": 0, "fileName": "NetworkChangeNotifierAutoDetect.java", "methodName": "getCurrentNetworkState", "lineNumber": 67}, {"className": "org.chromium.net.NetworkChangeNotifierAutoDetect", "level": 0, "fileName": "NetworkChangeNotifierAutoDetect.java", "methodName": "<init>", "lineNumber": 21}, {"className": "org.chromium.content.browser.BackgroundSyncNetworkObserver", "level": 0, "fileName": "BackgroundSyncNetworkObserver.java", "methodName": "createObserver", "lineNumber": 15}, {"className": "org.chromium.base.SystemMessageHandler", "level": 0, "fileName": "SystemMessageHandler.java", "methodName": "nativeDoRunLoopOnce", "lineNumber": -2}, {"className": "org.chromium.base.SystemMessageHandler", "level": 0, "fileName": "SystemMessageHandler.java", "methodName": "handleMessage", "lineNumber": 9}, {"className": "android.os.Handler", "level": 0, "fileName": "Handler.java", "methodName": "dispatchMessage", "lineNumber": 106}, {"className": "android.os.Looper", "level": 0, "fileName": "Looper.java", "methodName": "loop", "lineNumber": 193}, {"className": "android.app.ActivityThread", "level": 0, "fileName": "ActivityThread.java", "methodName": "main", "lineNumber": 6754}, {"className": "java.lang.reflect.Method", "level": 0, "fileName": "Method.java", "methodName": "invoke", "lineNumber": -2}, {"className": "com.android.internal.os.RuntimeInit$MethodAndArgsCaller", "level": 0, "fileName": "RuntimeInit.java", "methodName": "run", "lineNumber": 506}, {"className": "com.android.internal.os.ZygoteInit", "level": 0, "fileName": "ZygoteInit.java", "methodName": "main", "lineNumber": 863}], "permisson_group": "", "permisson": "", "result": {"WifiInfo": "android.net.wifi.WifiInfo@abe5a02"}, "stack_txt": 2, "permisson_level": ""}
  • The chromium SDK obtains the stack information of ssid every 2 seconds as follows
    {"stackTrace": [{"className": "libcore.util.Janus", "level": 0, "fileName": "Janus.java", "methodName": "getData", "lineNumber": 831}, {"className": "android.net.wifi.WifiInfo", "level": 0, "fileName": "WifiInfo.java", "methodName": "getSSID", "lineNumber": 272}, {"className": "org.chromium.net.NetworkChangeNotifierAutoDetect$WifiManagerDelegate", "level": 0, "fileName": "NetworkChangeNotifierAutoDetect.java", "methodName": "getWifiSsid", "lineNumber": 24}, {"className": "org.chromium.net.NetworkChangeNotifierAutoDetect", "level": 0, "fileName": "NetworkChangeNotifierAutoDetect.java", "methodName": "getCurrentNetworkState", "lineNumber": 67}, {"className": "org.chromium.net.NetworkChangeNotifierAutoDetect", "level": 0, "fileName": "NetworkChangeNotifierAutoDetect.java", "methodName": "connectionTypeChanged", "lineNumber": 100}, {"className": "org.chromium.android_webview.AwNetworkChangeNotifierRegistrationPolicy", "level": 0, "fileName": "AwNetworkChangeNotifierRegistrationPolicy.java", "methodName": "onFirstWebViewCreated", "lineNumber": 13}, {"className": "org.chromium.android_webview.AwContentsLifecycleNotifier", "level": 0, "fileName": "AwContentsLifecycleNotifier.java", "methodName": "onWebViewCreated", "lineNumber": 5}, {"className": "org.chromium.android_webview.AwContents", "level": 0, "fileName": "AwContents.java", "methodName": "nativeInit", "lineNumber": -2}, {"className": "org.chromium.android_webview.AwContents", "level": 0, "fileName": "AwContents.java", "methodName": "<init>", "lineNumber": 80}, {"className": "com.android.webview.chromium.WebViewChromium$1", "level": 0, "fileName": "WebViewChromium.java", "methodName": "run", "lineNumber": 14}, {"className": "org.chromium.android_webview.WebViewChromiumRunQueue", "level": 0, "fileName": "WebViewChromiumRunQueue.java", "methodName": "drainQueue", "lineNumber": 13}, {"className": "org.chromium.android_webview.WebViewChromiumRunQueue$1", "level": 0, "fileName": "WebViewChromiumRunQueue.java", "methodName": "run", "lineNumber": 2}, {"className": "org.chromium.base.ThreadUtils", "level": 0, "fileName": "ThreadUtils.java", "methodName": "runOnUiThread", "lineNumber": 30}, {"className": "org.chromium.android_webview.WebViewChromiumRunQueue", "level": 0, "fileName": "WebViewChromiumRunQueue.java", "methodName": "addTask", "lineNumber": 7}, {"className": "com.android.webview.chromium.WebViewChromiumFactoryProvider", "level": 0, "fileName": "WebViewChromiumFactoryProvider.java", "methodName": "addTask", "lineNumber": 6}, {"className": "com.android.webview.chromium.WebViewChromium", "level": 0, "fileName": "WebViewChromium.java", "methodName": "init", "lineNumber": 88}, {"className": "android.webkit.WebView", "level": 0, "fileName": "WebView.java", "methodName": "<init>", "lineNumber": 427}, {"className": "android.webkit.WebView", "level": 0, "fileName": "WebView.java", "methodName": "<init>", "lineNumber": 353}, {"className": "android.webkit.WebView", "level": 0, "fileName": "WebView.java", "methodName": "<init>", "lineNumber": 336}, {"className": "android.webkit.WebView", "level": 0, "fileName": "WebView.java", "methodName": "<init>", "lineNumber": 323}, {"className": "java.lang.reflect.Constructor", "level": 0, "fileName": "Constructor.java", "methodName": "newInstance0", "lineNumber": -2}, {"className": "java.lang.reflect.Constructor", "level": 0, "fileName": "Constructor.java", "methodName": "newInstance", "lineNumber": 343}, {"className": "android.view.LayoutInflater", "level": 0, "fileName": "LayoutInflater.java", "methodName": "createView", "lineNumber": 647}, {"className": "com.android.internal.policy.PhoneLayoutInflater", "level": 0, "fileName": "PhoneLayoutInflater.java", "methodName": "onCreateView", "lineNumber": 58}, {"className": "android.view.LayoutInflater", "level": 0, "fileName": "LayoutInflater.java", "methodName": "onCreateView", "lineNumber": 720}, {"className": "android.view.LayoutInflater", "level": 0, "fileName": "LayoutInflater.java", "methodName": "createViewFromTag", "lineNumber": 788}, {"className": "android.view.LayoutInflater", "level": 0, "fileName": "LayoutInflater.java", "methodName": "createViewFromTag", "lineNumber": 730}, {"className": "android.view.LayoutInflater", "level": 0, "fileName": "LayoutInflater.java", "methodName": "rInflate", "lineNumber": 863}, {"className": "android.view.LayoutInflater", "level": 0, "fileName": "LayoutInflater.java", "methodName": "rInflateChildren", "lineNumber": 824}, {"className": "android.view.LayoutInflater", "level": 0, "fileName": "LayoutInflater.java", "methodName": "inflate", "lineNumber": 515}, {"className": "android.view.LayoutInflater", "level": 0, "fileName": "LayoutInflater.java", "methodName": "inflate", "lineNumber": 423}, {"className": "android.view.LayoutInflater", "level": 0, "fileName": "LayoutInflater.java", "methodName": "inflate", "lineNumber": 374}, {"className": "com.android.internal.policy.PhoneWindow", "level": 0, "fileName": "PhoneWindow.java", "methodName": "setContentView", "lineNumber": 436}, {"className": "android.app.Dialog", "level": 0, "fileName": "Dialog.java", "methodName": "setContentView", "lineNumber": 557}, {"className": "com.archly.asdk.privacy.PrivacyDialog", "level": 0, "fileName": "PrivacyDialog.java", "methodName": "onCreate", "lineNumber": 45}, {"className": "android.app.Dialog", "level": 0, "fileName": "Dialog.java", "methodName": "dispatchOnCreate", "lineNumber": 407}, {"className": "android.app.Dialog", "level": 0, "fileName": "Dialog.java", "methodName": "show", "lineNumber": 302}, {"className": "com.archly.asdk.privacy.PrivacyDialog", "level": 0, "fileName": "PrivacyDialog.java", "methodName": "show", "lineNumber": 110}, {"className": "com.archly.asdk.privacy.PrivacyHelper$1", "level": 0, "fileName": "PrivacyHelper.java", "methodName": "onCall", "lineNumber": 45}, {"className": "com.archly.asdk.privacy.PrivacyHelper$3$1", "level": 0, "fileName": "PrivacyHelper.java", "methodName": "run", "lineNumber": 96}, {"className": "android.os.Handler", "level": 0, "fileName": "Handler.java", "methodName": "handleCallback", "lineNumber": 873}, {"className": "android.os.Handler", "level": 0, "fileName": "Handler.java", "methodName": "dispatchMessage", "lineNumber": 99}, {"className": "android.os.Looper", "level": 0, "fileName": "Looper.java", "methodName": "loop", "lineNumber": 193}, {"className": "android.app.ActivityThread", "level": 0, "fileName": "ActivityThread.java", "methodName": "main", "lineNumber": 6754}, {"className": "java.lang.reflect.Method", "level": 0, "fileName": "Method.java", "methodName": "invoke", "lineNumber": -2}, {"className": "com.android.internal.os.RuntimeInit$MethodAndArgsCaller", "level": 0, "fileName": "RuntimeInit.java", "methodName": "run", "lineNumber": 506}, {"className": "com.android.internal.os.ZygoteInit", "level": 0, "fileName": "ZygoteInit.java", "methodName": "main", "lineNumber": 863}], "permisson_group": "", "permisson": "android.permission.ACCESS_WIFI_STATE", "result": {"String": "<unknown ssid>"}, "stack_txt": 2, "permisson_level": "normal"}

how to deal with

  • There are many solutions on the Internet for WebWiew to implement the privacy policy function, such as the use of hooks ( Android WebView violations to obtain MAC address solutions - Code Pioneer Network ), we have tried this method, but it does not work
  • Use a third-party open source framework to load remote html files. It is unnecessary for us to introduce a library to load this thing. Finally, we tried it, but it didn’t work.
  • Later, we will directly consider using TextView to load rich text for processing. The backend of the server still needs to develop an html interface, but this interface has few elements, and some elements that TextView can recognize. The server provides an api interface to convert htlm The content is returned to the android front-end, and then the front-end renders the rich text through TextView. Just fix a few privacy agreements in the pop-up window and click to jump to the privacy interface. Don’t add any links to the specific html content. TextView It is not supported either. Generally, privacy pop-up windows are placed on the startup page. As long as you do not call any third-party SDK in the startup page and the Application has the code to obtain device information, you can guarantee that you will not obtain device information before agreeing.

Re-test finally passed

  • The html package loaded by TextView is tested on a third-party platform, and finally passed, which also confirms that WebView loads html files to obtain device information.
  • If you have other better solutions, please provide them

 

Guess you like

Origin blog.csdn.net/qq_19942717/article/details/126797591