flutter_in_app_update icon indicating copy to clipboard operation
flutter_in_app_update copied to clipboard

How to force update and not to let user to use app?

Open NTMS2017 opened this issue 5 years ago • 16 comments

Hi,

I need to force user to update app always. If they not going to update I should block user not to use app. Also I created a example app and try to use your example, but it didn't work and I guess there was no app that I am running in Google Play.

Later I update my app package name which is already in app store and I keep getting error as shown below.

I/flutter ( 7751): PlatformException(Failed to bind to the service., null, null)

Last, your example uses a button to check for update how to use this without button but in initState? Thanks

Note: I all need is to check for Update initial app initialization than force to make performImmediateUpdate().

My original app:

void main() async {
  WidgetsFlutterBinding.ensureInitialized();
  await SystemChrome.setEnabledSystemUIOverlays([]);
  await SystemChrome.setPreferredOrientations([DeviceOrientation.portraitUp]);
  runApp(new MyApp());
}

class MyApp extends StatelessWidget {
  // This widget is the root of your application.
  @override
  Widget build(BuildContext context) {
    SystemChrome.setEnabledSystemUIOverlays([]);
    SystemChrome.setPreferredOrientations([DeviceOrientation.portraitUp]);

    return new MaterialApp(
      // TODO: SUPPORTED LOCALE
      localizationsDelegates: [
        const LangDelegate(),
        GlobalMaterialLocalizations.delegate,
        GlobalMaterialLocalizations.delegate,
        GlobalMaterialLocalizations.delegate,
        const FallbackCupertinoLocalisationsDelegate(),
      ],
      supportedLocales: [
        const Locale('tr', 'TR'),
        const Locale('en', 'US'),
        const Locale('ru', 'RU'),
      ],

      debugShowCheckedModeBanner: false,
      title: 'My Cep',
      theme: new ThemeData(
        primaryColor: capitalDarkGreen,
        fontFamily: "Roboto",
      ),
      home: new MyMainHomePage(),
    );
  }
}

And in MyMainHomePage I have PackageInfo and Connectivity in initState. So where I code the android app update?

Here is the full code (I am not sure where I am making mistake):

import 'package:flutter/material.dart';
import 'package:upgrader/upgrader.dart';
import 'dart:io' show Platform;
import 'dart:async';
import 'package:in_app_update/in_app_update.dart';

void main() => runApp(MyApp());

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Flutter Demo',
      theme: ThemeData(
        primarySwatch: Colors.blue,
      ),
      home: MyHomePage(title: 'Flutter Demo Home Page'),
    );
  }
}

class MyHomePage extends StatefulWidget {
  MyHomePage({Key key, this.title}) : super(key: key);

  final String title;

  @override
  _MyHomePageState createState() => _MyHomePageState();
}

class _MyHomePageState extends State<MyHomePage> {
  AppUpdateInfo _updateInfo;
  GlobalKey<ScaffoldState> _scaffoldKey = new GlobalKey();
  bool _flexibleUpdateAvailable = false;

  @override
  void initState() {
    // TODO: implement initState
    super.initState();
    checkForUpdate();
    //InAppUpdate.performImmediateUpdate().catchError((e) => _showError(e));
  }

  // Platform messages are asynchronous, so we initialize in an async method.
  Future<void> checkForUpdate() async {
    InAppUpdate.checkForUpdate().then((info) {
      setState(() {
        _updateInfo = info;
      });
    }).catchError((e) => _showError(e));
  }

  void _showError(dynamic exception) {
    _scaffoldKey.currentState.showSnackBar(SnackBar(content: Text(exception.toString())));
    print(exception.toString());
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
        key: _scaffoldKey,
        appBar: AppBar(
          title: const Text('In App Update Example App'),
        ),
        body: _updateInfo?.updateAvailable == false
            ? new CircularProgressIndicator()
            : Platform.isAndroid == true
                ? Padding(
                    padding: const EdgeInsets.all(8.0),
                    child: Column(
                      children: <Widget>[
                        Center(
                          child: Text('Update info: $_updateInfo'),
                        ),
                        RaisedButton(
                          child: Text('Check for Update'),
                          onPressed: () => checkForUpdate(),
                        ),
                        RaisedButton(
                          child: Text('Perform immediate update'),
                          onPressed: _updateInfo?.updateAvailable == true
                              ? () {
                                  InAppUpdate.performImmediateUpdate().catchError((e) => _showError(e));
                                }
                              : null,
                        ),
                        RaisedButton(
                          child: Text('Start flexible update'),
                          onPressed: _updateInfo?.updateAvailable == true
                              ? () {
                                  InAppUpdate.startFlexibleUpdate().then((_) {
                                    setState(() {
                                      _flexibleUpdateAvailable = true;
                                    });
                                  }).catchError((e) => _showError(e));
                                }
                              : null,
                        ),
                        RaisedButton(
                          child: Text('Complete flexible update'),
                          onPressed: !_flexibleUpdateAvailable
                              ? null
                              : () {
                                  InAppUpdate.completeFlexibleUpdate().then((_) {
                                    _scaffoldKey.currentState.showSnackBar(SnackBar(content: Text('Success!')));
                                  }).catchError((e) => _showError(e));
                                },
                        )
                      ],
                    ),
                  )
                : UpgradeAlert(
                    child: Center(child: Text('Checking...')),
                  ));
  }
}

NTMS2017 avatar Jan 14 '20 13:01 NTMS2017

After few days of searching it doesn't work on emulator. I install on my android phone and it worked. But I can see only availableVersionCode as 30. But my actual version is version: 2.3.4+34 on Google Play store. I try to make Perform immediate update and I can see the update page which has x on right hand corner which is close button. I press there to close it before update. And second time I try to run it I am keep getting MissingPluginExeption.

My question is how to force user to update and not to cancel it? Thanks

NTMS2017 avatar Jan 17 '20 08:01 NTMS2017

In Google Play Store my App Release: 2.3.4 and version code: 34

I open my project and change the version to: 2.3.3+33

When I run the app I got error that shown below. Any idea why I am getting this error

error info: InAppUpdateState{updateAvailable: false, immediateUpdateAllowed: false, flexibleUpdateAllowed: false, availableVersionCode: null}

NTMS2017 avatar Jan 17 '20 11:01 NTMS2017

Please read https://developer.android.com/guide/playcore/in-app-updates#troubleshoot carefully. I'm pretty sure it won't work with your debug certificates in debug mode.

jonasbark avatar Jan 17 '20 11:01 jonasbark

What do you mean in debug mode? I install app from Android Studio to my phone.

NTMS2017 avatar Jan 17 '20 11:01 NTMS2017

ok, it means:

Make sure that the app that you are testing in-app updates with has the same application ID and is signed with the same signing key as the one available from Google Play.

So I need to update my app with this plugin. Than later (1 day later in example) I have to update my again with new version code on Google play than I can test. ???

Problem is that If I use version as 1.2.0+5 it goes and finds the new update. but if I change version code lower than but closer to currently that available in App Store it doesn't update.

NTMS2017 avatar Jan 17 '20 12:01 NTMS2017

I reduce my app versions to version: 1.2.4+10 and Now I got this:

info: InAppUpdateState{updateAvailable: true, immediateUpdateAllowed: false, flexibleUpdateAllowed: false, availableVersionCode: 30}

also it shows updateAvailable: true but both immediateUpdateAllowed and flexibleUpdateAllowed shows as a false what do you mean availableVersionCode: 30? My app version code: 34 in Google Play. Next update should I have to incease the version code to 30 to 40 and than 50, 60 so on?

NTMS2017 avatar Jan 17 '20 12:01 NTMS2017

I reduce my app versions to version: 1.2.4+10 and Now I got this:

info: InAppUpdateState{updateAvailable: true, immediateUpdateAllowed: false, flexibleUpdateAllowed: false, availableVersionCode: 30}

also it shows updateAvailable: true but both immediateUpdateAllowed and flexibleUpdateAllowed shows as a false what do you mean availableVersionCode: 30? My app version code: 34 in Google Play. Next update should I have to incease the version code to 30 to 40 and than 50, 60 so on?

Same issue with me..... It's issue on google side not this plugin. If you clear play store cache and open play store and go to my apps and then open app it will show update.

rahuldange09 avatar May 15 '20 11:05 rahuldange09

I reduce my app versions to version: 1.2.4+10 and Now I got this:

info: InAppUpdateState{updateAvailable: true, immediateUpdateAllowed: false, flexibleUpdateAllowed: false, availableVersionCode: 30}

also it shows updateAvailable: true but both immediateUpdateAllowed and flexibleUpdateAllowed shows as a false what do you mean availableVersionCode: 30? My app version code: 34 in Google Play. Next update should I have to incease the version code to 30 to 40 and than 50, 60 so on?

I am also seeing this. Though this happens only when I open app after clearing cache on play store. When I close the app and open again, it shows true for both update type.

azhar1038 avatar Jun 02 '20 13:06 azhar1038

To add to @mdazharuddin1011999, forcing an update check in the play store worked for me, even if I was just on internal testing. For that I followed the steps listed in the explanation of how to do alpha track in-app updates (even though I was on internal): https://stackoverflow.com/questions/56087064/how-can-i-test-in-app-updates-in-android

rubenvereecken avatar Aug 26 '20 11:08 rubenvereecken

Yeah it works. If you are seeing "update available" for your app in My apps and games section of Play store, this package works like charm, doesn't matter if you are in internal or beta or production!

azhar1038 avatar Aug 26 '20 11:08 azhar1038

And that is exactly my problem. I have to go to PlayStore, I have to find "My apps and games" and I have to check upgrades BEFORE this plugin will find the upgraded version, which is actually already exists on the PlayStore. Need that feature, which make this concept meaningless and check for upgrade directly in the Play Store and not in the device's PlayStore app's chache/memory/stored-datas, ...

fehernyul avatar Oct 12 '20 10:10 fehernyul

@fehernyul Nonsense. The play store update list is cached and auto updates itself - something that nobody has control of. So you'll just have to wait until the update information arrives to this plugin as well.

jonasbark avatar Oct 12 '20 10:10 jonasbark

Did you find a solution to force the app update? I mean users could not use the app unless they update to the latest version.

zjamshidi avatar Oct 31 '20 06:10 zjamshidi

@zjamshidi I store a "latest version" online somewhere (actually I use Firebase Remote Config but you could store it on your own server). On startup it fetches the version and if it's breaking with respect to the app's current version (Semver semantics), then the app routes to a captive screen.

If you're worried about your app not being able to start up without a connection because it would hang on fetching the version, just fetch the version when you do have a connection during the lifetime of the app.

rubenvereecken avatar Nov 03 '20 10:11 rubenvereecken

I do the the same for the "Latest Version". I was wondering if the library provides any solution for forcing users. I ended up calling "performUpdate" method in a loop :/

zjamshidi avatar Nov 03 '20 10:11 zjamshidi

Aren't "immediate" updates forced anyway? For flexible ones you'd have to loop though yeah if the user does say no, but that probably defeats the point. https://developer.android.com/guide/playcore/in-app-updates

rubenvereecken avatar Nov 03 '20 10:11 rubenvereecken