简体   繁体   中英

Flutter: http get request doesn't work on apk release

There are several similar questions about my problem, but the solution given in all of them doesn't work for me, so I try to open another question with the details for my problem. I hope somebody could help me.

Context: I am learning flutter & dart, and as a starter I would like to implement a simple app that consumes CRUD operations. I use REST API to access data on a MongoDB.

Problem: When I debug my code on web server as a web application it works fine. When I try to go on Android device with an apk, the server seems not to receive https get request, and client blocks on load indicator. As suggested in other questions, I made sure that the android uses_permissions for INTERNET were set in the AndroidManifest.xml.* I am pretty sure of this because the post http request to insert the data works fine also on the device. Further I use https as you can see below.

To build apk I use this command:

flutter build apk 

I also tried this one as suggested in other questions:

flutter build apk --no-shrink

This does not help.

This is the widget ViewStoricoRifornimenti for fetching data in background, (like demo on flutter dev):

Future<List<Rifornimento>> fetchWelcomes(http.Client client) async {
    final response = await client.get(
      Uri.parse('https://car-statistics.herokuapp.com/rifornimenti'),
      headers: <String, String>{
        'Content-Type': 'application/json; charset=UTF-8',
        'Access-Control-Allow-Origin': '*'
      },
    );

    // Use the compute function to run parsePhotos in a separate isolate.
    return compute(parseWelcomes, response.body);
  }

  List<Rifornimento> parseWelcomes(String responseBody) {
    final parsed = Welcome.fromRawJson(responseBody);
    return parsed.data;
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: FutureBuilder<List<Rifornimento>>(
        future: fetchWelcomes(http.Client()),
        builder: (context, snapshot) {
          if (snapshot.hasError) print(snapshot.error);

          return snapshot.hasData
              ? StoricoRifornimenti(items: snapshot.data!)
              : Center(child: CircularProgressIndicator());
        },
      ),
    );
  }
}

And here is the widget to display the results:

class _MyHomePageState extends State<MyHomePage> {

  ViewStoricoRifornimenti vsr = new ViewStoricoRifornimenti(title: "Wow");

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
      ),
      body: Center(
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: <Widget>[
      drawer: Drawer(
        child: ListView(
          padding: EdgeInsets.zero,
          children: <Widget>[
            DrawerHeader(
              decoration: BoxDecoration(
                color: Colors.blue,
              ),
              child: Text('Menu'),
            ),
            ListTile(
              title: Text('Storico Rifornimenti'),
              onTap: () {
                Navigator.push(
                  context,
                  MaterialPageRoute(builder: (context) => vsr),
                );
              },
            ),
          ],
        ),
      )
  }
}

Am I doing something wrong? Why in debug on the Web Application I have no errors while on device I can't get http response?

How could I debug this kind of problem?

Thanks to everybody will help me.

Make sure you add the below code to your manifest.

First, make sure you add internet permission to manifest

 <uses-permission android:name="android.permission.INTERNET" />

Seconds make sure you added usesCleartextTraffic true that will make sure if your API endpoint is not secure still you will able to call API.

<application
    android:usesCleartextTraffic="true">

Follow Official Migration Steps:

Official docs

I had to adjust the linting settings to enforce no implicit type castings. It seems to be handled differently in the release build.

I ran flutter pub add lints --dev to get cautioned about implicit type casts in the serialization line fromJson and toJson in my model classes this fixed the issues.

I started with adding a file to my project root called analysis_options.yaml with the following content:

analyzer:
  strong-mode:
    implicit-casts: false
    implicit-dynamic: false

The lints package seems to have this and even more rules.

I think your problem is that, from Android 9 you need to add a network_security_config.xml file in your xml directory in android/res/ folder.

The content for network_security_config.xml is as follows:

<domain-config cleartextTrafficPermitted="true">
  <domain includeSubdomains="true">yourdomain.com</domain>
  <domain includeSubdomains="true">yourdomain2.com</domain>
</domain-config>

For more information head to this article: Fix Clear Text Traffic

And in your AndroidManifest.xml file inside tag add these lines:

android:usesCleartextTraffic="true"
android:networkSecurityConfig="@xml/network_security_config"

That's what worked for me. Please correct me if I am wrong and also let me know that fixed your problem.

I have a similar problem, my app was working fine on web but not on android, I fix that by adding a null check to my class.fromMap():

class(id: json["id"] ?? '',);

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM