Umieściłem moją aplikację w sklepie Google Play. Zainstalowało go wielu klientów mojej firmy. Rozumiem mechanizm aktualizacji aplikacji.
Użytkownicy powinni zaznaczyć pole wyboru automatycznej aktualizacji w aplikacji playstore dla każdej aplikacji, którą chcą automatycznie zaktualizować. Jednak niektórzy użytkownicy odznaczyli ją lub nie zaznaczyli w pierwszej kolejności.
Napisana przeze mnie aplikacja jest przeznaczona dla branży opieki i jest używana przez opiekunów do zapewniania opieki domowej. Niektórzy z naszych klientów mają 1200 opiekunów. Musieliby wezwać wszystkich opiekunów do biura, aby indywidualnie zaktualizowali telefony. Jest to oczywiście niedopuszczalne.
Czy istnieje sposób na programowe sprawdzenie, czy w Sklepie Play jest zaktualizowana wersja mojej aplikacji?
Czy mogę mieć kod uruchamiany za każdym razem, gdy użytkownik uruchamia aplikację, która sprawdza Sklep Play? Jeśli istnieje zaktualizowana wersja, użytkownik może zostać skierowany do sklepu playstore. Oznacza to, że sprawdzanie automatycznej aktualizacji nie jest konieczne.
Z góry dziękuję
Matt
Odpowiedzi:
Aktualizacja 17 października 2019 r
https://developer.android.com/guide/app-bundle/in-app-updates
Aktualizacja 24 kwietnia 2019:
Android ogłosił funkcję, która prawdopodobnie rozwiąże ten problem. Korzystanie z interfejsu API aktualizacji w aplikacji: https://android-developers.googleblog.com/2018/11/unfolding-right-now-at-androiddevsummit.html
Oryginał:
O ile wiem, nie ma oficjalnego interfejsu API Google, który to obsługuje.
Należy rozważyć pobranie numeru wersji z interfejsu API.
Zamiast łączyć się z zewnętrznymi interfejsami API lub stronami internetowymi (takimi jak Sklep Google Play). Istnieje ryzyko, że coś może się zmienić w interfejsie API lub na stronie internetowej, dlatego należy rozważyć sprawdzenie, czy kod wersji bieżącej aplikacji jest poniżej numeru wersji otrzymanego z własnego interfejsu API.
Pamiętaj tylko, że jeśli zaktualizujesz aplikację, musisz zmienić wersję we własnym interfejsie API z numerem wersji aplikacji.
Poleciłbym zrobić plik we własnej witrynie lub API, z numerem wersji. (W końcu wykonaj cronjob i zaktualizuj wersję automatycznie i wyślij powiadomienie, gdy coś pójdzie nie tak)
Musisz pobrać tę wartość ze swojej strony Sklepu Google Play (jest w międzyczasie zmieniona, już nie działa):
<div class="content" itemprop="softwareVersion"> x.x.x </div>
Sprawdź w swojej aplikacji, czy wersja używana na telefonie komórkowym jest poniżej numeru wersji wyświetlanego w Twoim interfejsie API.
Pokaż wskazanie, że ona / on potrzebuje aktualizacji za pomocą powiadomienia, najlepiej.
Rzeczy, które możesz zrobić
Numer wersji przy użyciu własnego interfejsu API
Plusy:
Cons:
Numer wersji na stronie internetowej Sklep Google Play
Plusy:
Cons:
źródło
Current Version
wymieniony jakoVaries with device
pomysł, jak można to rozwiązać lub czy jest dostępna inna alternatywa?Uwzględnij JSoup w pliku build.gradle aplikacji:
dependencies { compile 'org.jsoup:jsoup:1.8.3' }
i pobierz aktualną wersję, taką jak:
currentVersion = getPackageManager().getPackageInfo(getPackageName(), 0).versionName;
I wykonaj następujący wątek:
private class GetVersionCode extends AsyncTask<Void, String, String> { @Override protected String doInBackground(Void... voids) { String newVersion = null; try { newVersion = Jsoup.connect("https://play.google.com/store/apps/details?id=" + MainActivity.this.getPackageName() + "&hl=it") .timeout(30000) .userAgent("Mozilla/5.0 (Windows; U; WindowsNT 5.1; en-US; rv1.8.1.6) Gecko/20070725 Firefox/2.0.0.6") .referrer("http://www.google.com") .get() .select(".hAyfc .htlgb") .get(7) .ownText(); return newVersion; } catch (Exception e) { return newVersion; } } @Override protected void onPostExecute(String onlineVersion) { super.onPostExecute(onlineVersion); Log.d("update", "Current version " + currentVersion + "playstore version " + onlineVersion); if (onlineVersion != null && !onlineVersion.isEmpty()) { if (Float.valueOf(currentVersion) < Float.valueOf(onlineVersion)) { //show dialog } } }
Aby uzyskać więcej informacji, odwiedź: http://revisitingandroid.blogspot.in/2016/12/programmatically-check-play-store-for.html
źródło
getPackageManager().getPackageInfo(getPackageName(), 0).versionName
Możesz po prostu użyćBuildConfig.VERSION_NAME
:)Zdalna konfiguracja Firebase może być na razie możliwym i niezawodnym rozwiązaniem, ponieważ Google nie udostępniło mu żadnego interfejsu API.
Sprawdź dokumenty zdalnej konfiguracji Firebase
Kroki 1 Utwórz projekt Firebase i dodaj google_play_service.json do swojego projektu
2. Utwórz klucze, takie jak „android_latest_version_code” i „android_latest_version_name” w konsoli Firebase-> Zdalna konfiguracja
3. Kod Androida
public void initializeFirebase() { if (FirebaseApp.getApps(mContext).isEmpty()) { FirebaseApp.initializeApp(mContext, FirebaseOptions.fromResource(mContext)); } final FirebaseRemoteConfig config = FirebaseRemoteConfig.getInstance(); FirebaseRemoteConfigSettings configSettings = new FirebaseRemoteConfigSettings.Builder() .setDeveloperModeEnabled(BuildConfig.DEBUG) .build(); config.setConfigSettings(configSettings); }
Pobierz nazwę i kod aktualnej wersji
int playStoreVersionCode = FirebaseRemoteConfig.getInstance().getString( "android_latest_version_code"); PackageInfo pInfo = this.getPackageManager().getPackageInfo(getPackageName(), 0); int currentAppVersionCode = pInfo.versionCode; if(playStoreVersionCode>currentAppVersionCode){ //Show update popup or whatever best for you }
4. I aktualizuj firebase „android_latest_version_code” i „android_latest_version_name”, podając nazwę i kod bieżącej wersji produkcyjnej.
Zdalna konfiguracja Firebase działa zarówno na Androidzie, jak i na iPhonie.
źródło
Caused by: com.android.tools.r8.utils.AbortException: Error: null, Cannot fit requested classes in a single dex file (# methods: 68703 > 65536)
. W takim przypadku należy dodać MultiDex do swojej aplikacji.Możesz pobrać aktualną wersję Playstore za
JSoup
pomocą pewnych modyfikacji, jak poniżej:@Override protected String doInBackground(Void... voids) { String newVersion = null; try { newVersion = Jsoup.connect("https://play.google.com/store/apps/details?id=" + MainActivity.this.getPackageName() + "&hl=it") .timeout(30000) .userAgent("Mozilla/5.0 (Windows; U; WindowsNT 5.1; en-US; rv1.8.1.6) Gecko/20070725 Firefox/2.0.0.6") .referrer("http://www.google.com") .get() .select(".hAyfc .htlgb") .get(7) .ownText(); return newVersion; } catch (Exception e) { return newVersion; } } @Override protected void onPostExecute(String onlineVersion) { super.onPostExecute(onlineVersion); Log.d("update", "playstore version " + onlineVersion); }
odpowiedź @Tarun już nie działa.
źródło
Odpowiedź @Tarun działała idealnie, ale teraz nie jest, ze względu na ostatnie zmiany od Google w witrynie Google Play.
Po prostu zmień je z odpowiedzi @Tarun ..
class GetVersionCode extends AsyncTask<Void, String, String> { @Override protected String doInBackground(Void... voids) { String newVersion = null; try { Document document = Jsoup.connect("https://play.google.com/store/apps/details?id=" + MainActivity.this.getPackageName() + "&hl=en") .timeout(30000) .userAgent("Mozilla/5.0 (Windows; U; WindowsNT 5.1; en-US; rv1.8.1.6) Gecko/20070725 Firefox/2.0.0.6") .referrer("http://www.google.com") .get(); if (document != null) { Elements element = document.getElementsContainingOwnText("Current Version"); for (Element ele : element) { if (ele.siblingElements() != null) { Elements sibElemets = ele.siblingElements(); for (Element sibElemet : sibElemets) { newVersion = sibElemet.text(); } } } } } catch (IOException e) { e.printStackTrace(); } return newVersion; } @Override protected void onPostExecute(String onlineVersion) { super.onPostExecute(onlineVersion); if (onlineVersion != null && !onlineVersion.isEmpty()) { if (Float.valueOf(currentVersion) < Float.valueOf(onlineVersion)) { //show anything } } Log.d("update", "Current version " + currentVersion + "playstore version " + onlineVersion); } }
i nie zapomnij dodać biblioteki JSoup
dependencies { compile 'org.jsoup:jsoup:1.8.3'}
i Oncreate ()
@Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); String currentVersion; try { currentVersion = getPackageManager().getPackageInfo(getPackageName(), 0).versionName; } catch (PackageManager.NameNotFoundException e) { e.printStackTrace(); } new GetVersionCode().execute(); }
to wszystko… Dzięki temu linkowi
źródło
Google wprowadził interfejs API aktualizacji w aplikacji
API obsługuje obecnie dwa przepływy:
źródło
Jest biblioteka AppUpdater . Jak dołączyć:
źródło
Pochodzące z punktu widzenia aplikacji hybrydowej. To jest przykład javascript, mam stopkę dostępną do aktualizacji w moim menu głównym. Jeśli aktualizacja jest dostępna (tj. Mój numer wersji w pliku konfiguracyjnym jest mniejszy niż wersja pobrana, wyświetl stopkę) Spowoduje to skierowanie użytkownika do sklepu z aplikacjami / Play, gdzie użytkownik może kliknąć przycisk aktualizacji.
Otrzymuję również informacje o nowościach (tj. Informacje o wydaniu) i wyświetlam je w trybie modalnym podczas logowania, jeśli jest to pierwszy raz w tej wersji.
Na urządzeniu gotowe - ustaw adres URL sklepu
if (device.platform == 'iOS') storeURL = 'https://itunes.apple.com/lookup?bundleId=BUNDLEID'; else storeURL = 'https://play.google.com/store/apps/details?id=BUNDLEID';
Metodę Dostępna aktualizacja można uruchamiać tak często, jak chcesz. Mój jest uruchamiany za każdym razem, gdy użytkownik przejdzie do ekranu głównego.
function isUpdateAvailable() { if (device.platform == 'iOS') { $.ajax(storeURL, { type: "GET", cache: false, dataType: 'json' }).done(function (data) { isUpdateAvailable_iOS(data.results[0]); }).fail(function (jqXHR, textStatus, errorThrown) { commsErrorHandler(jqXHR, textStatus, false); }); } else { $.ajax(storeURL, { type: "GET", cache: false }).done(function (data) { isUpdateAvailable_Android(data); }).fail(function (jqXHR, textStatus, errorThrown) { commsErrorHandler(jqXHR, textStatus, false); }); } }
iOS Callback: Apple ma API, więc bardzo łatwe do uzyskania
function isUpdateAvailable_iOS (data) { var storeVersion = data.version; var releaseNotes = data.releaseNotes; // Check store Version Against My App Version ('1.14.3' -> 1143) var _storeV = parseInt(storeVersion.replace(/\./g, '')); var _appV = parseInt(appVersion.substring(1).replace(/\./g, '')); $('#ft-main-menu-btn').off(); if (_storeV > _appV) { // Update Available $('#ft-main-menu-btn').text('Update Available'); $('#ft-main-menu-btn').click(function () { openStore(); }); } else { $('#ft-main-menu-btn').html(' '); // Release Notes settings.updateReleaseNotes('v' + storeVersion, releaseNotes); } }
Android Callback: PlayStore musisz zeskrobać, ponieważ widzisz, że wersja jest stosunkowo łatwa do pobrania, a co nowego biorę html zamiast tekstu, ponieważ w ten sposób mogę użyć ich formatowania (tj. Nowe linie itp.)
function isUpdateAvailable_Android(data) { var html = $(data); var storeVersion = html.find('div[itemprop=softwareVersion]').text().trim(); var releaseNotes = html.find('.whatsnew')[0].innerHTML; // Check store Version Against My App Version ('1.14.3' -> 1143) var _storeV = parseInt(storeVersion.replace(/\./g, '')); var _appV = parseInt(appVersion.substring(1).replace(/\./g, '')); $('#ft-main-menu-btn').off(); if (_storeV > _appV) { // Update Available $('#ft-main-menu-btn').text('Update Available'); $('#ft-main-menu-btn').click(function () { openStore(); }); } else { $('#ft-main-menu-btn').html(' '); // Release Notes settings.updateReleaseNotes('v' + storeVersion, releaseNotes); } }
Logika otwartego sklepu jest prosta, ale dla kompletności
function openStore() { var url = 'https://itunes.apple.com/us/app/appname/idUniqueID'; if (device.platform != 'iOS') url = 'https://play.google.com/store/apps/details?id=appid' window.open(url, '_system') }
Upewnij się, że Sklep Play i App Store zostały umieszczone na białej liście:
<access origin="https://itunes.apple.com"/> <access origin="https://play.google.com"/>
źródło
Zdalna konfiguracja Firebase jest lepsza.
Wdrażanie Remote Config na Androidzie
Dodawanie zależności Remote Config
compile 'com.google.firebase:firebase-config:9.6.0'
Po zakończeniu możemy w razie potrzeby uzyskać dostęp do instancji FirebaseRemoteConfig w całej naszej aplikacji:
Pobieranie wartości Remote Config
boolean someBoolean = firebaseRemoteConfig.getBoolean("some_boolean"); byte[] someArray = firebaseRemoteConfig.getByteArray("some_array"); double someDouble = firebaseRemoteConfig.getDouble("some_double"); long someLong = firebaseRemoteConfig.getLong("some_long"); String appVersion = firebaseRemoteConfig.getString("appVersion");
Pobierz wartości po stronie serwera
firebaseRemoteConfig.fetch(cacheExpiration) .addOnCompleteListener(new OnCompleteListener<Void>() { @Override public void onComplete(@NonNull Task<Void> task) { if (task.isSuccessful()) { mFirebaseRemoteConfig.activateFetched(); // We got our config, let's do something with it! if(appVersion < CurrentVersion){ //show update dialog } } else { // Looks like there was a problem getting the config... } } });
Teraz, po przesłaniu nowej wersji do sklepu playstore, musimy zaktualizować numer wersji w firebase. Teraz, jeśli jest to nowa wersja, zostanie wyświetlone okno dialogowe aktualizacji
źródło
Wewnątrz metody OnCreate napisz poniższy kod.
VersionChecker versionChecker = new VersionChecker(); try { latestVersion = versionChecker.execute().get(); Toast.makeText(getBaseContext(), latestVersion , Toast.LENGTH_SHORT).show(); } catch (InterruptedException | ExecutionException e) { e.printStackTrace(); }
daje to wersję aplikacji w Sklepie Play.
następnie musisz sprawdzić wersję aplikacji, jak poniżej
PackageManager manager = getPackageManager(); PackageInfo info = null; try { info = manager.getPackageInfo(getPackageName(), 0); } catch (PackageManager.NameNotFoundException e) { e.printStackTrace(); } assert info != null; version = info.versionName;
potem możesz porównać go z wersją sklepu i skonfigurować własne ekrany aktualizacji
if(version.equals(latestVersion)){ Toast.makeText(getBaseContext(), "No Update" , Toast.LENGTH_SHORT).show(); }else { Toast.makeText(getBaseContext(), "Update" , Toast.LENGTH_SHORT).show(); }
I dodaj VersionChecker.class, jak poniżej
public class VersionChecker extends AsyncTask<String, String, String> { private String newVersion; @Override protected String doInBackground(String... params) { try { newVersion = Jsoup.connect("https://play.google.com/store/apps/details?id=" + "package name" + "&hl=en") .timeout(30000) .userAgent("Mozilla/5.0 (Windows; U; WindowsNT 5.1; en-US; rv1.8.1.6) Gecko/20070725 Firefox/2.0.0.6") .referrer("http://www.google.com") .get() .select(".hAyfc .htlgb") .get(7) .ownText(); } catch (IOException e) { e.printStackTrace(); } return newVersion; } }
źródło
Skonfiguruj serwer, który ujawnia adres URL HTTP, który zgłasza najnowszą wersję, a następnie użyj narzędzia AlarmManager, aby wywołać ten adres URL i sprawdzić, czy wersja na urządzeniu jest taka sama jak najnowsza wersja. Jeśli to nie jest, wyskakuje wiadomość lub powiadomienie i wyślij je na rynek w celu aktualizacji.
Jest kilka przykładów kodu: Jak umożliwić użytkownikom sprawdzanie najnowszej wersji aplikacji z poziomu aplikacji?
źródło
Oprócz korzystania z JSoup, możemy alternatywnie wykonać dopasowanie wzorców w celu pobrania wersji aplikacji z playStore.
Aby dopasować najnowszy wzorzec z google playstore, czyli
<div class="BgcNfc">Current Version</div><span class="htlgb"><div><span class="htlgb">X.X.X</span></div>
najpierw musimy dopasować powyższą sekwencję węzłów, a następnie z powyższej sekwencji pobrać wartość wersji. Poniżej znajduje się fragment kodu dla tego samego:private String getAppVersion(String patternString, String inputString) { try{ //Create a pattern Pattern pattern = Pattern.compile(patternString); if (null == pattern) { return null; } //Match the pattern string in provided string Matcher matcher = pattern.matcher(inputString); if (null != matcher && matcher.find()) { return matcher.group(1); } }catch (PatternSyntaxException ex) { ex.printStackTrace(); } return null; } private String getPlayStoreAppVersion(String appUrlString) { final String currentVersion_PatternSeq = "<div[^>]*?>Current\\sVersion</div><span[^>]*?>(.*?)><div[^>]*?>(.*?)><span[^>]*?>(.*?)</span>"; final String appVersion_PatternSeq = "htlgb\">([^<]*)</s"; String playStoreAppVersion = null; BufferedReader inReader = null; URLConnection uc = null; StringBuilder urlData = new StringBuilder(); final URL url = new URL(appUrlString); uc = url.openConnection(); if(uc == null) { return null; } uc.setRequestProperty("User-Agent", "Mozilla/5.0 (Windows; U; WindowsNT 5.1; en-US; rv1.8.1.6) Gecko/20070725 Firefox/2.0.0.6"); inReader = new BufferedReader(new InputStreamReader(uc.getInputStream())); if (null != inReader) { String str = ""; while ((str = inReader.readLine()) != null) { urlData.append(str); } } // Get the current version pattern sequence String versionString = getAppVersion (currentVersion_PatternSeq, urlData.toString()); if(null == versionString){ return null; }else{ // get version from "htlgb">X.X.X</span> playStoreAppVersion = getAppVersion (appVersion_PatternSeq, versionString); } return playStoreAppVersion; }
Udało mi się to rozwiązać, ponieważ działa to również w przypadku najnowszych zmian w sklepie Google Play. Mam nadzieję, że to pomoże.
źródło
private void CheckUPdate() { VersionChecker versionChecker = new VersionChecker(); try { String appVersionName = BuildConfig.VERSION_NAME; String mLatestVersionName = versionChecker.execute().get(); if(!appVersionName.equals(mLatestVersionName)){ AlertDialog.Builder alertDialog = new AlertDialog.Builder(Activity.this); alertDialog.setTitle("Please update your app"); alertDialog.setMessage("This app version is no longer supported. Please update your app from the Play Store."); alertDialog.setPositiveButton("UPDATE NOW", new DialogInterface.OnClickListener() { public void onClick(DialogInterface dialog, int which) { final String appPackageName = getPackageName(); try { startActivity(new Intent(Intent.ACTION_VIEW, Uri.parse("market://details?id=" + appPackageName))); } catch (android.content.ActivityNotFoundException anfe) { startActivity(new Intent(Intent.ACTION_VIEW, Uri.parse("https://play.google.com/store/apps/details?id=" + appPackageName))); } } }); alertDialog.show(); } } catch (InterruptedException | ExecutionException e) { e.printStackTrace(); } } @SuppressLint("StaticFieldLeak") public class VersionChecker extends AsyncTask<String, String, String> { private String newVersion; @Override protected String doInBackground(String... params) { try { newVersion = Jsoup.connect("https://play.google.com/store/apps/details?id="+getPackageName()) .timeout(30000) .userAgent("Mozilla/5.0 (Windows; U; WindowsNT 5.1; en-US; rv1.8.1.6) Gecko/20070725 Firefox/2.0.0.6") .referrer("http://www.google.com") .get() .select(".hAyfc .htlgb") .get(7) .ownText(); } catch (IOException e) { e.printStackTrace(); } return newVersion; } }
źródło
Nie ma oficjalnego interfejsu API GooglePlay, który mógłby to zrobić.
Ale możesz użyć tej nieoficjalnej biblioteki, aby uzyskać dane o wersji aplikacji.
A jeśli powyższe nie działa, zawsze możesz połączyć się za pomocą protokołu http ze stroną swojej aplikacji (np. Https://play.google.com/store/apps/details?id=com.shots.android&hl=en ) i przeanalizuj pole „Aktualna wersja”.
źródło
Możesz spróbować wykonać następujący kod za pomocą Jsoup
String latestVersion = doc.getElementsContainingOwnText("Current Version").parents().first().getAllElements().last().text();
źródło
Google wprowadził interfejs API aktualizacji w aplikacji. Korzystając z tego, możemy poprosić użytkownika o aktualizację aplikacji w aplikacji. jeśli użytkownik zaakceptuje, możemy bezpośrednio pobrać najnowszą aplikację i zainstalować ją bez przekierowywania do sklepu playstore. Aby uzyskać więcej informacji, zapoznaj się z poniższym linkiem
link1 link2
źródło
potwierdził tylko, że metoda działa teraz:
newVersion = Jsoup.connect("https://play.google.com/store/apps/details?id=" + AcMainPage.this.getPackageName() + "&hl=it") .timeout(30000) .userAgent("Mozilla/5.0 (Windows; U; WindowsNT 5.1; en-US; rv1.8.1.6) Gecko/20070725 Firefox/2.0.0.6") .referrer("http://www.google.com") .get() .select(".hAyfc .htlgb") .get(5) .ownText();
źródło
Google wprowadził funkcję aktualizacji w aplikacji ( https://developer.android.com/guide/app-bundle/in-app-updates ), działa na Lollipop + i daje możliwość poproszenia użytkownika o aktualizację z ładnym dialog (ELASTYCZNY) lub z obowiązkowym komunikatem pełnoekranowym (NATYCHMIAST).
Oto jak będzie wyglądać aktualizacja elastyczna :
a oto przepływ natychmiastowej aktualizacji:
Możesz sprawdzić moją odpowiedź tutaj https://stackoverflow.com/a/56808529/5502121, aby uzyskać pełny przykładowy kod implementacji przepływów aktualizacji elastycznej i natychmiastowej . Mam nadzieję, że to pomoże!
źródło