Flutter - Insecure socket connections are disallowed by platform: 10.0.2.2 - flutter

Since today whenever I try to login my application I get the following error thrown by the Dio package: SocketException: Insecure socket connections are disallowed by platform: 10.0.2.2
I use the following settings to connect:
static BaseOptions options = new BaseOptions(
baseUrl: "http://10.0.2.2:3000", // on android emulator
connectTimeout: 5000,
receiveTimeout: 3000)
And consequently something along the lines of (where I have authentication set-up and functioning properly at /user/login):
var apiLogin = api.dio;
try {
Response response = await apiLogin.post("/user/login",
options: Options(contentType: "application/json"),
data: {"email": email, "password": password});
} on DioError catch (e) {
throw Exception([e]);
}
I have a Node server running on port 3000 which is connected to (containerized) mongodb. When trying the authentication, it immediately has the DioError and I haven't been able to find the cause anywhere online.
Does anyone know what this error is related to?
EDIT [ANSWER]
Thanks to #lyrics for pointing me in the right direction:
From API level 27 and higher, usesCleartextTraffic defaults to false, consequently blocking outgoing http requests, requiring HTTPS.
The solution was to add the following to AndroidManifest.xml:
<?xml version="1.0" encoding="utf-8"?>
<manifest ...>
<uses-permission android:name="android.permission.INTERNET" />
<application
...
android:usesCleartextTraffic="true"
...>
...
</application>
</manifest>
as stated in stackoverflow answer
source: https://developer.android.com/guide/topics/manifest/application-element#usesCleartextTraffic

I have a similar issue with Flutter running on ios Simulator and Android emulator:
SocketException: Insecure socket connections are disallowed by platform:
Inside the Flutter project go to :
To enable in Ios:
ios folder -> runner folder -> info.plist
Then add the following lines to enable HTTP requests:
<key>NSAppTransportSecurity</key>
<dict>
<key>NSAllowsArbitraryLoads</key>
<true/>
</dict>
To enable in Android:
Android folder -> app -> src -> main -> AndroidManifest.xml
Add this permission:
<uses-permission android:name="android.permission.INTERNET"/>
then add the following line inside application tag:
android:usesCleartextTraffic="true"

First add-in AndroidManifest file
add this line in the end before closing tag
<uses-permission android:name="android.permission.INTERNET" />
add this line in the beginning
find this tag and add it first in it
<application
android:usesCleartextTraffic="true"

It seems you newly upgraded to Android 10, Well you probably didn't know that HTTPS is the default connection protocol starting with Android 9 and that all connection not using Https will fail.
Read more https://developer.android.com/training/articles/security-config.html
See this answer here
https://stackoverflow.com/a/50834600/6467637

I was making a call to-
Response response = await get('http://worldtimeapi.org/api/timezone/Asia/Kolkata');
Instead of http I simply replaced it to https and it was fixed.
The new request was-
Response response = await get('https://worldtimeapi.org/api/timezone/Asia/Kolkata');
This fixed the issue for me.

Related

flutter: cant access non ssl api after set proxy

i need to set proxy globally in my project, i did that with flutter_socks_proxy package.
void main() {
WidgetsFlutterBinding.ensureInitialized();
SocksProxy.initProxy(
proxy: 'SOCKS5 192.111.139.165:4145',
onCreate: (client) {
client.badCertificateCallback =
(X509Certificate cert, String host, int port) => true;
});
runApp(MyApp());
}
it works but i have a problem, i can't access http (non ssl) api after set the proxy.
final url = Uri.parse('http://worldtimeapi.org/api/timezone/Europe/London');
final response = await http.get(url);
print(response.body);
this is the error
[ERROR:flutter/lib/ui/ui_dart_state.cc(198)] Unhandled Exception: Connection reset by peer
it works fine with https apis.
I think the problem is related to the allowance of Clear Text Traffic, which in this case is the HTTP, you can allow it by the following steps:
For Android:
Navigate to the this file: ./android/app/src/main/AndroidManifest.xml
In the proprites of the application tag, add this property: android:usesCleartextTraffic="true"
The final file should be something like:
<?xml version="1.0" encoding="utf-8"?>
<manifest ...>
<uses-permission android:name="android.permission.INTERNET" />
<application
...
android:usesCleartextTraffic="true"
...>
...
</application>
</manifest>
For IOS:
Navigate to the this file: ./ios/Runner/info.plist
Add the following key-value pair:
<key>NSAppTransportSecurity</key>
<dict>
<key>NSAllowsArbitraryLoads</key>
<true/>
</dict>
Note:
You may need to run flutter clean after applying the above changes to ensure that the native files compiles again with a fresh run.

Flutter App Rejected for External Storage Request for Android API level 30 and above. Below is the code:

My app needs storage permission to access and pick pdf files on the device storage. For Android API level 30 I used and wrote the code as below:
Future<void> askPermission() async {
if (androidInfo != null) {
if (androidInfo!.version.sdkInt! >= 30 && Platform.isAndroid) {
await Permission.manageExternalStorage.request();
} else if (androidInfo!.version.sdkInt! < 30 && Platform.isAndroid) {
await Permission.storage.request();
}
}
}
FilePickerResult? result = await FilePicker.platform.pickFiles(
type: FileType.custom,
allowedExtensions: ['pdf'],
);
In android manifest:
<uses-permission android:name="android.permission.INTERNET"/>
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.MANAGE_EXTERNAL_STORAGE" />
android:requestLegacyExternalStorage="true">
But the App was rejected saying:
Issue: Access to device storage not required
The feature you identified does not require unrestricted access to device storage. There are other privacy friendly options for accessing files in shared storage, such as using the system file picker, or, depending on the use case, you can follow the recommendations for receiving data from other apps listed here.
Please update your app so that the feature uses a privacy friendly alternative and remove All Files Access (MANAGE_EXTERNAL_STORAGE) permission...
What changes should I make for the app to be compliant and access storage for Android API level 30. User needs to pick PDF files from Storage and after the task completes new PDF files will be saved in the Storage.
In the Android Manifest you have to define upto which sdk you want to request permission
Replace
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
with
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" android:maxSdkVersion="28"/>

SocketException: Failed host lookup: 'methods.abc.com' (OS Error: No address associated with hostname, errno = 7), StackTrace :

I store the API error logs in my DB. I found so many errors on my DB. the log message is the same.
SocketException: Failed host lookup: 'xxx.abc.com' (OS Error: No address associated with hostname, errno = 7), StackTrace :
BTW, This error only occurs to random users. Not for all users.
function
Future<dynamic> abc() async {
var responseJson;
try {
final response = await http.post('${env.url}/xxx/xxx/xxx', headers: {'Authorization': 'Bearer xxx'});
responseJson = _response(response, _errorMap);
return responseJson;
}
catch (e, s) {
errorLog.store('$e, StackTrace : $s', _errorMap);
throw FetchDataException('message');
}
}
env.url looks like this, https://xxx.abc.com
xml
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
package="xxx">
<uses-permission android:name="android.permission.INTERNET"/>
<uses-permission android:name="android.permission.VIBRATE"/>
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION"/>
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
<application ...
package
http: ^0.12.2
This may not be a Flutter problem. Instead, that is OS Error which is far more low level.
Firstly, have a check at this: Unable to resolve host "<url here>"; No address associated with hostname.
For example, if your user closed his Wifi and mobile network, then you will see this error.
Usually it is not caused by a bug in your code, but just because the user has no network - if he has no network, how can he resolve the domain name!
Thus, for me, personally, I just ignore such type of error. In other words, I do not report these errors to my backend.
Make Sure that you have active internet connection along with permission defined in AndroidManifest.xml
In my case, I restarted my laptop and it was fine. Most of the times restarting computer will solve the problems like this.
First thing we should have a active internet connection.
Second thing we should enable the wifi in our android emulator.
Next thing we should add permissions correctly in AndroidManifest.xml
[Flutter Networking]
: https://docs.flutter.dev/development/data-and-backend/networking
<manifest xmlns:android...>
...
<uses-permission android:name="android.permission.INTERNET" />
<application ...
</manifest>
Then after we do those steps we should restart the emulator and run the app.
In My case I opened the emulator and after that I connected to the WIFI. So, wifi connected to my system but unable to connect to emulator .
Solutions:
I Closed the emulator and re-open it. And Finally works..

unknown error with the unitywebrequest function

I'm doing an apk which when I run it on my cell phone gives me the following error
"Unknow error"
but the strangest thing is that if it works normally when I run it from unity, I used the following code to show me what the error was when I executed it on my cell phone because in unity works perfectly
IEnumerator logIn(WWWForm form)
{
using (UnityWebRequest webRequest = UnityWebRequest.Post("http://localhost:3000/login", form))
{
yield return webRequest.SendWebRequest();
if (webRequest.isNetworkError )
{
Debug.Log(webRequest.error);
advertencia.SetActive(true);
advertencia.GetComponent<Text>().text=webRequest.error+"1";
}
else if (webRequest.isHttpError)
{
advertencia.SetActive(true);
advertencia.SetActive(true);
advertencia.GetComponent<Text>().text = webRequest.error+"2";
}
else
{
SceneManager.LoadScene("Principal");
}
}
}
check if my apk was connected to the internet with the following code that shows a text if it connects to the internet
private void Update()
{
if (Application.internetReachability == NetworkReachability.NotReachable)
{
advertencia.SetActive(true);
Debug.Log("Error. Check internet connection!");
}
}
The code a little more complete:
private Text userText;
private InputField password;
public GameObject advertencia;
private void Start()
{
userText = GameObject.Find("UserInput").GetComponent<Text>();
password = GameObject.Find("PasswordInput").GetComponent<InputField>();
advertencia = GameObject.Find("Advertencia");
advertencia.SetActive(false);
}
//the function with which the corrutina invoked
public void Log()
{
Debug.Log("Usuario : " + userText.text + "\nContraseña : " + password.text);
WWWForm form = new WWWForm();
form.AddField("codigo", userText.text);
form.AddField("contrasena", password.text);
StartCoroutine(logIn(form));
}
Problem
You use the URL
http://localhost:3000/login
You are trying to send the web request to the host localhost. This works on your PC in Unity since the PC is the server you a trying to contact.
The server isn't running on your phone but your phone is trying to send the request to itself at port 3000 which will fail obviously.
Read more on What is a localhost?
Solution
Replace the localhost by the IP or network address your server/PC actually has and you should be fine.
To find out your PC's IP use e.g.
Linux/Unix: In a terminal call ifconfig
Windows: In the CMD call ipconfig
Ofcourse your PC and phone then also have to be in the same network or at least be routed so your phone can reach the server/PC at the given IP/network address.
Possible that you also have to configure your PC's firewall to allow incoming traffic on that port.
If you are running this code on your mobile device then you should change the hostname. You can't use localhost in the edge device. So, instead of localhost you have to put the IP address of the computer where the backend server is running.
For getting the IP address,
Take command prompt/terminal then type the following command,
For Windows machine
ipconfig
For Linux / Mac machine
ifconfig
Then take the IPv4 address and replace the localhost with this IP like this,
using (UnityWebRequest webRequest = UnityWebRequest.Post("http://192.168.1.9:3000/login", form))
You must ensure that you have connected the computer (in which the server is running) and the mobile device to the same network. You can do it by simply connecting all devices via wifi network.
If you are using a mobile device that is running on Android 9, Pie (API level 27+) or later version of the operating system then you have to specify the android:usesCleartextTraffic="true" in the AndroidManifest.xml file.
So, Click on Player Settings --> Publishing Settings --> Check custom manifest template. You can add the android:usesCleartextTraffic="true" in the manifest file like this,
<?xml version="1.0" encoding="utf-8"?>
<manifest ...>
<uses-permission android:name="android.permission.INTERNET" />
<application
...
android:usesCleartextTraffic="true"
...>
...
</application>
</manifest>
AndroidManifest.xml
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android" package="com.unity3d.player" android:installLocation="preferExternal" android:versionCode="1" android:versionName="1.0">
<supports-screens android:smallScreens="true" android:normalScreens="true" android:largeScreens="true" android:xlargeScreens="true" android:anyDensity="true" />
<uses-permission android:name="android.permission.INTERNET" />
<application android:theme="#style/UnityThemeSelector" android:icon="#drawable/app_icon" android:label="#string/app_name" android:debuggable="true" android:usesCleartextTraffic="true">
<activity android:name="com.unity3d.player.UnityPlayerActivity" android:label="#string/app_name">
<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>

Ionic 2 communicating with HTTPS server

I have an working ionic 2 app (running on 2.0.0-beta.4), which communicate with my server using HTTP POST.
loginService(userID, pwd, userIpAddress){
var body = 'userID=' +userID+"&pwd="+pwd+"&userIpAddress="+userIpAddress+'';
var headers = new Headers();
headers.append('Content-Type', 'application/x-www-form-urlencoded');
var url = 'http://localhost/WS/login.asmx';
return this.http.post(url,body, {headers: headers}).map(res => res.json());
}
How would I go around converting it into HTTPS POST,
if the server would only accepts HTTPS POST requests?
How do I insert my self-signed certificates?
The closest I can find is Node.JS HTTPS API
To insert your self-signed certificate, you need to mark your app as debuggable. However, this will enable the user to view the console logs.
To mark your app as debuggable, inside manifest file add this line android:debuggable="true"
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
<application android:icon="#drawable/icon"
android:debuggable="true">
...
</application>
</manifest