3

I am developing an Android app with Unity. But I cannot connect to a internet server with it. Tho this gives false, which is good: Application.internetReachability == NetworkReachability.NotReachable

But when trying to execute this snippet:

IEnumerator testConnection() {
    Dictionary<string, string> header = new Dictionary<string, string>();
    string userAgent = "Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/55.0.2883.87 Safari/537.36";
    header.Add("User-Agent", userAgent);
    WWW www = new WWW("www.google.com", null, header);
    yield return www;
    // check for errors
    if (www.error == null) {
        util.debug("works");
    } else {
        // www.error and www.text both are empty
        util.debug("testing: WWW Error: " + www.error + www.text); 
    }
}

it works via unity editor and windows executable, but not on my android device (v 6) Is there a known solution to this?

Ping also seem to work:

IEnumerator PingGoogle() {
    Ping googPing  = new Ping("172.217.6.195");

    while (!googPing.isDone) {
        yield return googPing;
    }
    util.debug("ping works: " + googPing.time); //I reach this point with the app
}

So i think something is wrong with the WWW-class?

Android version: 6.0.1

OxygenOS-Version: 3.5.6

Unity version: 5.6.0b3 Personal (64bit)

Edit: I changed the PlayerSettings (which is the android manifest as far as i can tell) of Internet Access from Auto to Require. No success

Edit2: It appears that www.error wasnt empty at all. The Message just got truncated because it was too long for unitys-textelement (my fault). The error was java.net.MalformedURLException: Protocol not found: www.google.de. So the only thing that was missing was the protocoll, i.e.: http://. I found this problem when i tried a suggested solution from the comments.

InsOp
  • 2,425
  • 3
  • 27
  • 42
  • In your question there's nothing about permissions so I'll ask : Did you add the permission to use internet connection to your android manifest ? – mrogal.ski Mar 13 '17 at 11:39
  • This is likely a user-agent problem which is a duplicate. Please verify this by adding [user-agent](http://stackoverflow.com/a/41348855/3785314) to this. It will make the server think that you are making the request from a web browser. – Programmer Mar 13 '17 at 11:43
  • @m.rogalski thanks, I think since I can ping google its not related to that problem. I still changed the permission and added it to the question. – InsOp Mar 13 '17 at 11:59
  • @Programmer thanks, i added the useragent of your suggested link, but without success. Still i end up in the else-case with an empty www.error and empty www.text – InsOp Mar 13 '17 at 12:00
  • I don't think you internet permission. Unity should do that for you automatically. Are you even sure that your Android device is connected to an internet? Open a browser and check. Adding your Android and Unity version to your question would be helpful. – Programmer Mar 13 '17 at 12:06
  • @Programmer Unity does not add permissions automatically. I had to set up every permission inside unity configuration to be able to read/write files and gain acces to internet connection. – mrogal.ski Mar 13 '17 at 12:08
  • @Programmer well the ping code snippet does work, which prooves that there is a internet connection. But it seems that unitys `WWW`-class seems to be at fault – InsOp Mar 13 '17 at 12:11
  • Have you tried using just `new WWW("http://google.com");` ? From the documentation it seams that `new WWW("www.google.com", null, header);` sends `POST` request and not `GET` – mrogal.ski Mar 13 '17 at 12:11
  • @m.rogalski It **does** add permission autamitcally. This post is about the internet not about reading/writing files. If you use the `WWW` class, internet permission should be added. If you use the camera `class` camera permission should be added. The-same thing applies to the Accelerator and other sensor classes that requires permission.One exception is reading and writing to external storage which you can add the permission from the build settings. If you have been doing this manually then file for a bug report. – Programmer Mar 13 '17 at 12:16
  • @m.rogalski if the second parameter is empty, unity converts the request to a `GET`-request. But neverthe less the request works from unity-editor, so it wont make a difference. Having written that - i just tested it. And it works with your suggested change. But why does the `POST`-method work with the editor and not with the android device? – InsOp Mar 13 '17 at 12:17
  • @InsOp `GET` and `POST` are two different types of requests and are treated differently when reached server ( in most cases ). 2 years ago I was writing HTTP server and in there we were just dropping empty post requests. That can be the case in here. Another thing is that maybe from within editor and windows binaries the `WWW` class is using different http internals to send requests which is automatically converting empty `POST` requests into `GET` requests. – mrogal.ski Mar 13 '17 at 12:21
  • @m.rogalski I think youre right about the last part you wrote. I am just figuring this out with a server of mine. thank you! – InsOp Mar 13 '17 at 12:28
  • 1
    @m.rogalski it was the protocol which was missing. thank you for your help. Ill mark the question as duplicate – InsOp Mar 13 '17 at 12:47
  • Possible duplicate of ["java.net.MalformedURLException: Protocol not found" read to html file](http://stackoverflow.com/questions/12934621/java-net-malformedurlexception-protocol-not-found-read-to-html-file) – InsOp Mar 13 '17 at 12:47
  • No. This has nothing to do with GET/POST. I did experiment and found the problem and I think this post will help other Unity users. – Programmer Mar 13 '17 at 12:48
  • @Programmer So i sohuldnt mark it as duplicate? – InsOp Mar 13 '17 at 13:06
  • Nope. This is a Unity/Android based problem which works in the Editor but not on Android. Some new programmers that will have the-same problem won't even see that protocol error. All they know is that `WWW.text` is null. You should change the title to something that people can find in the future such as "WWW.text returning null" – Programmer Mar 13 '17 at 13:11

2 Answers2

3

I ran a quick test with your modified code that is still not working and got this run-time exception:

java.net.MalformedURLException: Protocol not found

It's always good to use Android Monitor when having such problems like this.

The problem is that you did not prefix the url with http:// or https://. Android does not support that so that's why it worked on the Editor but not on Android.

The-same thing happens also happens when you try to embed user name and password in a url. For example, http://username:password@example.com.

This will work on Windows and the Editor but will not work on Android but there is a fix for it.

This should work:

IEnumerator testConnection()
{
    Dictionary<string, string> header = new Dictionary<string, string>();
    string userAgent = "Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/55.0.2883.87 Safari/537.36";
    header.Add("User-Agent", userAgent);
    WWW www = new WWW("http://www.google.com", null, header);
    yield return www;
    // check for errors
    if (www.error == null)
    {
        util.debug("works");
    }
    else
    {
        // www.error and www.text both are empty
        util.debug("testing: WWW Error: " + www.error + www.text);
    }
}

Hint:

When making a web request from Unity app to a server that does not belong to you (http://www.google.com), it is always a good idea to add user-agent header or expect the request to fail on some devices when your app is released.

Community
  • 1
  • 1
Programmer
  • 121,791
  • 22
  • 236
  • 328
  • Thanks, i just came to that conclusion as well! You have mentioned to use Android Monitor? Can you provide further informations in your post? – InsOp Mar 13 '17 at 12:49
  • 1
    Download Android Studio. It comes with it. When your phone is connected to your computer, it will be showing everything that is happening in the Android Monitor. You will see all the logs and exceptions. – Programmer Mar 13 '17 at 12:50
0

If the android os version is greater than Oreo (Android 8, API level > 26) then you have to enable usesCleartextTraffic in the AndroidManifest.xml file. Also, ensure that internet permission is requested.

If you are using Unity Engine 2019+ versions,

You can enable the custom manifest file from File --> Build Settings --> Player Settings --> Publishing Settings --> Custom Main Manifest.

enter image description here

Now, you will get the AndroidManifest.xml file under the Assets/Plugins/Android folder.

Open the file and remove the following file from the file

<!-- GENERATED BY UNITY. REMOVE THIS COMMENT TO PREVENT OVERWRITING WHEN EXPORTING AGAIN-->

then add the internet permission request and usesCleartextTraffic attribute in that,

<?xml version="1.0" encoding="utf-8"?>
<manifest
    xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.unity3d.player"
    xmlns:tools="http://schemas.android.com/tools">
    <uses-permission android:name="android.permission.INTERNET" />
    <application android:usesCleartextTraffic="true">
        <activity android:name="com.unity3d.player.UnityPlayerActivity"
                  android:theme="@style/UnityThemeSelector">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />
                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
            <meta-data android:name="unityplayer.UnityActivity" android:value="true" />
        </activity>
    </application>
</manifest>

If you are using Unity Engine 2018 or previous versions,

You can create a file named AndroidManifest.xml using the text editor (Notepad) and paste the above manifest file contents into that file.

Then create a folder named Plugins under the Assets folder. Also, create a folder named Android under the Plugins folder. Finally, put the newly created AndroidManifest.xml file into the Android folder.

Codemaker2015
  • 12,190
  • 6
  • 97
  • 81