Search Unity

  1. Welcome to the Unity Forums! Please take the time to read our Code of Conduct to familiarize yourself with the forum rules and how to post constructively.
  2. Dismiss Notice

Question Unity is collecting installed app list when start up on Android, how can we disable it?

Discussion in 'Android' started by GiverDP, May 17, 2022.

  1. GiverDP

    GiverDP

    Joined:
    Jan 16, 2019
    Posts:
    34
    Recently we encountered an issue:

    Unity is collecting installed app list when start up on Android. This will cause privacy issue that before user agree with privacy policy, it's collecting installed app list data.

    How can we disable it?

    We also checked stack trace, it's been called from the UnityPlayer. You can see the screenshot below. How can we prevent Unity collecting installed app list? Any idea?

     
  2. Aurimas-Cernius

    Aurimas-Cernius

    Unity Technologies

    Joined:
    Jul 31, 2013
    Posts:
    3,637
    This java file is not part of default Unity build for Android.
    Is it from one of our packages?
     
  3. jj-unity

    jj-unity

    Unity Technologies

    Joined:
    Jan 4, 2017
    Posts:
    69
    The specific code in question is checking to see if the Oculus VR intent handler is present. On non-Oculus devices, it actually returns an empty list since no other application should be exposing this specific intent. Looking into it, it looks like some stores are implementing security policies around this call. And in Android 11+, the scope of returned information is limited even further: https://medium.com/androiddevelopers/package-visibility-in-android-11-cc857f221cd9

    I'm going to be looking into whether there is a better way to handle this. It would be helpful to know what specific situations are causing this to be an issue. Android version, API versions, specific store fronts?

    Does adding the intent queries entry to the manifest as mentioned in the above Android 11 blog post resolve the issue for you? That would be helpful to know as we investigate this issue.

    Thanks!
     
  4. GiverDP

    GiverDP

    Joined:
    Jan 16, 2019
    Posts:
    34
    I just tried with an empty Unity project and it still reports that we have the issue. This time I didn't include Oculus VR. And I'll show you the stack trace they had. It's from the store review check. The device is Android 9, Mi Note 3
     

    Attached Files:

  5. GiverDP

    GiverDP

    Joined:
    Jan 16, 2019
    Posts:
    34
    We are making games in China, since the privacy policy updated. We are not allowed to collect any information before user agree with the privacy policy. But Unity is collecting this data when app start, so we got rejection from the Chinese platforms. Is there any way we can disable or prevent Unity from collecting data like this?
     
  6. GiverDP

    GiverDP

    Joined:
    Jan 16, 2019
    Posts:
    34
    Which queries you mean, we already added the queries we'll interact with. But it still have the issue there.
     
  7. GiverDP

    GiverDP

    Joined:
    Jan 16, 2019
    Posts:
    34
    Hello is there any update about issue?
     
  8. GiverDP

    GiverDP

    Joined:
    Jan 16, 2019
    Posts:
    34
    I also tried to remove the build-in packages for VR and XR, but it still doesn't help.

    upload_2022-5-18_17-57-30.png
     
  9. JeffDUnity3D

    JeffDUnity3D

    Unity Technologies

    Joined:
    May 2, 2017
    Posts:
    14,446
    Can you confirm using Charles Proxy that this information is being sent over the wire?
     
  10. JeffDUnity3D

    JeffDUnity3D

    Unity Technologies

    Joined:
    May 2, 2017
    Posts:
    14,446
    What was the specific rejection reason?
     
  11. GiverDP

    GiverDP

    Joined:
    Jan 16, 2019
    Posts:
    34
    It doesn't relate to send anything. The rejection reason I already post in the first commit with the screenshot. Because when Unity starts on Android, it is calling queryIntenActivitiesAsUser through the nativeRender from Unity Engine code. This is not allowed to be called on start up in China. Because user didn't agree with privacy policy yet.
     
  12. GiverDP

    GiverDP

    Joined:
    Jan 16, 2019
    Posts:
    34
    And the Charles Proxy will not show anything relate to this. You can also see the stack trace I posted above with the txt file.
     
  13. Voxel-Busters

    Voxel-Busters

    Joined:
    Feb 25, 2015
    Posts:
    1,829
    I understand that but if you can share the rejection reason/description it will be of great help.
    From Android 11 it's more explicit for the apps to specify what it queries for further security. And it's quite obvious to have this kind of call for checking any pre conditions.

    So, share the complete rejection reason so that others can have more details to look into.
     
  14. GiverDP

    GiverDP

    Joined:
    Jan 16, 2019
    Posts:
    34
    This txt file I referenced here(also above replies) is the reason, you can check the stack trace, Unity is calling queryIntentActivitiesAsUser method which is not allowed when start up through the nativeRender method.
     

    Attached Files:

  15. wuxiao

    wuxiao

    Joined:
    Aug 22, 2015
    Posts:
    6
    我在腾讯应用宝平台遇上与你同样的问题,持续关注解决方案!
     
  16. wuxiao

    wuxiao

    Joined:
    Aug 22, 2015
    Posts:
    6
    I also encountered the same problem, hope the Unity Technologies can help solve.
     

    Attached Files:

  17. JeffDUnity3D

    JeffDUnity3D

    Unity Technologies

    Joined:
    May 2, 2017
    Posts:
    14,446
    Can you share the rejection reason text from the store?
     
  18. GiverDP

    GiverDP

    Joined:
    Jan 16, 2019
    Posts:
    34
    ### 1. unity 3d
    #### 读取设备应用安装列表
    ```json
    {
    "stackTrace": [{
    "className": "libcore.util.Janus",
    "level": 0,
    "fileName": "Janus.java",
    "methodName": "getData",
    "lineNumber": 742
    },
    {
    "className": "android.app.ApplicationPackageManager",
    "level": 0,
    "fileName": "ApplicationPackageManager.java",
    "methodName": "queryIntentActivitiesAsUser",
    "lineNumber": 1007
    },
    {
    "className": "android.app.ApplicationPackageManager",
    "level": 0,
    "fileName": "ApplicationPackageManager.java",
    "methodName": "queryIntentActivities",
    "lineNumber": 991
    },
    {
    "className": "com.unity3d.player.UnityPlayer",
    "level": 0,
    "methodName": "nativeRender",
    "lineNumber": -2
    },
    {
    "className": "com.unity3d.player.UnityPlayer",
    "level": 0,
    "methodName": "access$300",
    "lineNumber": 0
    },
    {
    "className": "com.unity3d.player.UnityPlayer$e$1",
    "level": 0,
    "methodName": "handleMessage",
    "lineNumber": 95
    },
    {
    "className": "android.os.Handler",
    "level": 0,
    "fileName": "Handler.java",
    "methodName": "dispatchMessage",
    "lineNumber": 102
    },
    {
    "className": "android.os.Looper",
    "level": 0,
    "fileName": "Looper.java",
    "methodName": "loop",
    "lineNumber": 193
    },
    {
    "className": "com.unity3d.player.UnityPlayer$e",
    "level": 0,
    "methodName": "run",
    "lineNumber": 20
    },
    {
    "className": "java.lang.Thread",
    "fileName": "Thread.java",
    "methodName": "start",
    "parent": 1,
    "lineNumber": 729
    },
    {
    "className": "com.unity3d.player.UnityPlayer",
    "methodName": "<init>",
    "parent": 2,
    "lineNumber": 341
    },
    {
    "className": "com.unity3d.player.UnityPlayerActivity",
    "fileName": "UnityPlayerActivity.java",
    "methodName": "onCreate",
    "parent": 3,
    "lineNumber": 41
    },
    {
    "className": "com.drpanda.DPUnityPlayerActivity",
    "fileName": "DPUnityPlayerActivity.java",
    "methodName": "onCreate",
    "parent": 4,
    "lineNumber": 21
    },
    {
    "className": "android.app.Activity",
    "fileName": "Activity.java",
    "methodName": "performCreate",
    "parent": 5,
    "lineNumber": 7287
    },
    {
    "className": "android.app.Activity",
    "fileName": "Activity.java",
    "methodName": "performCreate",
    "parent": 6,
    "lineNumber": 7278
    },
    {
    "className": "android.app.Instrumentation",
    "fileName": "Instrumentation.java",
    "methodName": "callActivityOnCreate",
    "parent": 7,
    "lineNumber": 1272
    },
    {
    "className": "android.app.ActivityThread",
    "fileName": "ActivityThread.java",
    "methodName": "performLaunchActivity",
    "parent": 8,
    "lineNumber": 2932
    },
    {
    "className": "android.app.ActivityThread",
    "fileName": "ActivityThread.java",
    "methodName": "handleLaunchActivity",
    "parent": 9,
    "lineNumber": 3087
    },
    {
    "className": "android.app.servertransaction.LaunchActivityItem",
    "fileName": "LaunchActivityItem.java",
    "methodName": "execute",
    "parent": 10,
    "lineNumber": 78
    },
    {
    "className": "android.app.servertransaction.TransactionExecutor",
    "fileName": "TransactionExecutor.java",
    "methodName": "executeCallbacks",
    "parent": 11,
    "lineNumber": 108
    },
    {
    "className": "android.app.servertransaction.TransactionExecutor",
    "fileName": "TransactionExecutor.java",
    "methodName": "execute",
    "parent": 12,
    "lineNumber": 68
    },
    {
    "className": "android.app.ActivityThread$H",
    "fileName": "ActivityThread.java",
    "methodName": "handleMessage",
    "parent": 13,
    "lineNumber": 1817
    },
    {
    "className": "android.os.Handler",
    "fileName": "Handler.java",
    "methodName": "dispatchMessage",
    "parent": 14,
    "lineNumber": 106
    },
    {
    "className": "android.os.Looper",
    "fileName": "Looper.java",
    "methodName": "loop",
    "parent": 15,
    "lineNumber": 193
    },
    {
    "className": "android.app.ActivityThread",
    "fileName": "ActivityThread.java",
    "methodName": "main",
    "parent": 16,
    "lineNumber": 6719
    },
    {
    "className": "java.lang.reflect.Method",
    "fileName": "Method.java",
    "methodName": "invoke",
    "parent": 17,
    "lineNumber": -2
    },
    {
    "className": "com.android.internal.os.RuntimeInit$MethodAndArgsCaller",
    "fileName": "RuntimeInit.java",
    "methodName": "run",
    "parent": 18,
    "lineNumber": 506
    },
    {
    "className": "com.android.internal.os.ZygoteInit",
    "fileName": "ZygoteInit.java",
    "methodName": "main",
    "parent": 19,
    "lineNumber": 863
    }],
    "permisson_group": "",
    "permisson": "",
    "params": {
    "intent": "Intent { act=android.intent.action.MAIN cat=[com.oculus.intent.category.VR] flg=0x20 pkg=*** }",
    "flags": 32,
    "userId": 0
    },
    "result": {
    "List<ResolveInfo>": "[]"
    },
    "permisson_level": ""
    }
    ```
     
  19. GiverDP

    GiverDP

    Joined:
    Jan 16, 2019
    Posts:
    34
    This is from the government not the store
     
  20. JeffDUnity3D

    JeffDUnity3D

    Unity Technologies

    Joined:
    May 2, 2017
    Posts:
    14,446
    I believe you forgot to share the rejection text.
     
  21. JeffDUnity3D

    JeffDUnity3D

    Unity Technologies

    Joined:
    May 2, 2017
    Posts:
    14,446
    That is an activity list, not the rejection message. But thanks.
     
  22. wuxiao

    wuxiao

    Joined:
    Aug 22, 2015
    Posts:
    6
    I had the same problem, attachment is the store rejection message and the function stack.
     

    Attached Files:

  23. JeffDUnity3D

    JeffDUnity3D

    Unity Technologies

    Joined:
    May 2, 2017
    Posts:
    14,446
    Sorry, couldn't translate from an image
     
  24. GiverDP

    GiverDP

    Joined:
    Jan 16, 2019
    Posts:
    34
    尊敬的开发者: 经四川省通信管理局检测,您公司开发运营的应用存在未同意隐私政策前,违规获取应用列表问题,违反了《网络安全法》《电信条例》《电信和互联网用户个人信息保护规定》等法律法规,按照《关于开展纵深推进APP侵害用户权益专项整治行动的通知》(工信部信管【2020】164号)工作要求,请于2022年5月31日前改正上述违法行为,并将整改后的APK更新至华为应用市场。逾期未改正违法行为应用,管局将依法进行公告、下架或断接入等方式进行处理。

    This is the text and that txt file telling unity is collecting the installed app list with the stack trace.
     
  25. wuxiao

    wuxiao

    Joined:
    Aug 22, 2015
    Posts:
    6
    And after testing, the version before unity 2019.4.15 will not have this problem.
     

    Attached Files:

  26. ShenKang4181

    ShenKang4181

    Joined:
    Aug 13, 2019
    Posts:
    14
    I try to decompile unity class Jar remove the relevant code and compile unity class Jar solved the problem
     

    Attached Files:

  27. ShenKang4181

    ShenKang4181

    Joined:
    Aug 13, 2019
    Posts:
    14
    upload_2022-5-26_9-32-29.png
    I think he's avoiding the problem!
     
  28. GiverDP

    GiverDP

    Joined:
    Jan 16, 2019
    Posts:
    34
    We figured out another solution, we implemented an Android native activity to do the privacy policy flow with the Android native UI and instead of starting with Unity activity, we start with the privacy policy activity. And we start Unity activity after the user passed the privacy policy activity. This has been proved to be work. You guys can have a try.
     
    jorone_h and wuxiao like this.
  29. JeffDUnity3D

    JeffDUnity3D

    Unity Technologies

    Joined:
    May 2, 2017
    Posts:
    14,446
    We are trying to understand the problem, sorry for the confusion. I could not translate the message, I only know English, sorry. There is a difference between an API that collects information on the device only, and having the information sent over the network and stored off device. My focus has been on data sent over the wire, so I wanted to confirm.
     
    Voxel-Busters likes this.
  30. GiverDP

    GiverDP

    Joined:
    Jan 16, 2019
    Posts:
    34
    Recently we have a lot of privacy policy updated in China, so that's why a lot of developers are stressed. If we don't fix this in time(by the end of May), our apps will be removed from the store. The issue it not about sending data over the wire. It's mainly because Unity is collecting device information which is sensitive now before user agreed with the privacy policy. If you are still confused and if it's possible we can have a call to talk about the details.
     
  31. AcidArrow

    AcidArrow

    Joined:
    May 20, 2010
    Posts:
    11,001
    Slight tangent here and I understand that a lot of people really use analytics and stuff, and like Unity makes most of their money from ads and harvesting user data, but please consider having a clear option to make our games not read anything at all if we don’t want it to.

    Stores don’t like it, because why would be an app reaching for data if it’s not gonna use them? And maybe transmit them at some weird point 12 hours later or a week later or whatever?

    What are we supposed to tell them when they ask “why is your game reaching for X data?”?

    And I can’t really tell them the data is not being transmitted, because I did not write the code that reads that data so I don’t know if it also doesn’t like transmit the data later anyway. Sure I can run Charles proxy for a day or two, but I can’t really run it for month to make 100% nothing goes through.

    You’ve been saying in other threads that only we the developers know what data is being collected, but that’s not really true, is it?
     
  32. JeffDUnity3D

    JeffDUnity3D

    Unity Technologies

    Joined:
    May 2, 2017
    Posts:
    14,446
    Charles Proxy is only used for temporary troubleshooting, not to change any behavior or keep data from going through. You would use Charles Proxy only one time to confirm what is being sent over the wire. You use it for 2 minutes, then that's it and never use it again. But your point is taken, the stores are indeed looking at API calls that could be then used to send the data at a later time, exactly as you describe. I'm with you, but this particular issue is a bit outside my area of expertise
     
    AcidArrow likes this.
  33. Voxel-Busters

    Voxel-Busters

    Joined:
    Feb 25, 2015
    Posts:
    1,829
    Actually you can update the file shipped with unity (check screenshot) instead of decompiling every time you make a build. However there are other better alternatives to handle this scenario which goes beyond the scope of this thread.
     

    Attached Files:

  34. wuxiao

    wuxiao

    Joined:
    Aug 22, 2015
    Posts:
    6
    非常感谢您的建议!
     
  35. ShenKang4181

    ShenKang4181

    Joined:
    Aug 13, 2019
    Posts:
    14
    upload_2022-6-7_14-30-38.png
    I Find the root cause
    in 2020.3.35f1c2\Editor\Data\PlaybackEngines\AndroidPlayer\Variations\il2cpp\Release\Classes\classes.jar
    com->unity3d->player->UnityPlayer.java

    Delete this or don't execute this code as soon as it runs.
    please!
     
  36. ShenKang4181

    ShenKang4181

    Joined:
    Aug 13, 2019
    Posts:
    14
    Do you have any information about the next step?
     
  37. jj-unity

    jj-unity

    Unity Technologies

    Joined:
    Jan 4, 2017
    Posts:
    69
    First, I want to say that the code in question is not gathering a list of installed apps as stated. It queries for a very specific system activity that Unity uses on some devices, and returns an empty list in all other cases. That said, to avoid false positives as was happening here, we've changed the code in question to no longer use the intent filter querying technique. One other note is that the code that was causing issues with certification has actually been in place for almost 2 years, so it seems as if the certification rules likely changed at some point to be more stringent.

    The refactored code should be landing in these Unity versions once they become available:

    2020.3.37f1
    2021.3.6f1
    2022.1.8f1
    2022.2.0a19
     
    Last edited: Jun 29, 2022
  38. ShenKang4181

    ShenKang4181

    Joined:
    Aug 13, 2019
    Posts:
    14
    Thani Oruvan
    I updated the 2020.3.37f1
    This version did solve the problem for a period of time.
    All app stores no longer refuse.
    But in recent days
    Some app stores seem to have upgraded their detection mechanism.
    Has appeared because of privacy issues refused to shelves.
    The reason for rejection is that AndroidID was obtained before agreeing to the privacy policy.
     
  39. Voxel-Busters

    Voxel-Busters

    Joined:
    Feb 25, 2015
    Posts:
    1,829
    As mentioned earlier by another user, we suggest similar solution.
    Let me know if it works. Ideally, It should work in all scenarios.
    1. Create a new launch activity in java to show up your consent
    2. Once consent is agreed then launch the UnityPlayer activity or any of your custom activity.

    This ways, you can avoid decompiling and also in future if unity collects something else early, still this solution works.

    Also, you can automate adding the launch acitvity through post processing scripts. If I get time, will share a github repo.
     
    Last edited: Aug 10, 2022
    ShenKang4181 likes this.