GithubHelp home page GithubHelp logo

eggheadgames / siren Goto Github PK

View Code? Open in Web Editor NEW
134.0 11.0 44.0 1.17 MB

Notify users when a new version of your Android app is available, and prompt them with the Play Store link. A port of the iOS library of the same name.

License: MIT License

Java 100.00%
android version-check siren notify-users

siren's Introduction

Android Arsenal Circle CI Release

Siren for Android

Notify users when a new version of your Android app is available, and prompt them with the Play Store link.

This is a port of the iOS library of the same name: https://github.com/ArtSabintsev/Siren

About

Siren checks a user's currently installed version of your Android app against the latest version information stored in a JSON file on a server URL you provide. (Unfortunately, the Google public API for version checking requires a token, and due to logistics and rate limiting, it's not feasible to use the API from an Android app).

If a new version is available, an alert can be presented to the user informing them of the newer version, and giving them the option to update the application. Alternatively, Siren can notify your app programmatically, enabling you to inform the user through alternative means, such as a custom interface.

  • Siren is built to work with semantic version numbering to provide a range of update suggestions for your customers
  • Siren is a Java language port of a Siren, an iOS Swift library that achieves the same functionality
  • Siren is actively maintained by Egghead Games for their cross-platform mobile/tablet apps (great mind puzzles with no ads!)

Features

  • Gradle support (using JitPack)
  • Localized for 20+ languages (See Localization Section)
  • Three types of alerts (see Screenshots & Alert Types)
  • Optional override methods (see Optional Override section)
  • Accompanying sample Android app

Similar Android libraries

Choose what works best for your scenario. We chose not to "screenscrape" the Google Play Listing. We've kept the prompt & update scenarios simple. We kept close to the iOS Siren library to keep our iOS & Android apps similar. Other Android solutions: AppUpdater (the most comprehensive and feature rich library, including support for checks at Amazon and FDroid), Gandalf (also has a "companion" iOS solution), Update Checker, Fit (callback framework, no UI),

Screenshots & Alert Types

  • The left picture forces the user to update the app.
  • The center picture gives the user the option to update the app.
  • The right picture gives the user the option to skip the current update.
  • These options are controlled by the SirenAlertType enum.

Force update Optional update Skip update

Setup

A minimal usage is to add the following to the onCreate of your main activity. This will check at most once a day for a new version and give the user the option to choose "Update" or "Next time".

private static final String SIREN_JSON_URL = "https://example.com/com.mycompany.myapp/version.json";

Siren siren = Siren.getInstance(getApplicationContext());
siren.checkVersion(this, SirenVersionCheckType.DAILY, SIREN_JSON_URL);

Installation Instructions

Add the JitPack.io repository to your root build.gradle:

allprojects {
    repositories {
        maven { url "https://jitpack.io" }
    }
}

Add a dependency to your application related build.gradle

dependencies {
    compile 'com.github.eggheadgames:Siren:1.4.+'
}

Host a Json document with a public access that will describe your application package name and current application version.

{ "com.example.app": { "minVersionName": "1.12.2" } }

OR

{ "com.example.app": { "minVersionCode": 7 } }

Parameters supported on the JSON document:

  • minVersionName: The minimum version name required.
  • minVersionCode: The minimum version code required, minVersionName will take precendence if both specified.
  • enable: A boolean flag to remotely toggle the version check feature.
  • force: A boolean flag to remotely set alertType as FORCE on every type of update.

Example:

{ "com.example.app": { "minVersionCode": 7, "enable": true, "force": false } }

Options

The SirenVersionCheckType controls how often the server is checked for a new version, and hence how often the user will be prompted. You can set it to IMMEDIATELY, DAILY or WEEKLY.

You can also define the dialog appearance and behaviour by setting SirenAlertType to react according to your version increment per Semantic Versioning. The default is SirenAlertType.OPTION. This generates a 2 button "Next Time" or "Update" alert. Other values are FORCE, SKIP and NONE. NONE will not display an alert, but will call your listener with appropriate text to display. See Example below.

You can combine these options to have different behaviour for different version changes. For example, you might will force a user to upgrade for a major version change (e.g. 1.x.x to 2.x.x), give them a "Next time" option for a minor version change (e.g. 1.2.x to 1.3.x) and add a 3rd "Skip this version" option for a 3rd or 4th level change (e.g. 1.2.5 to 1.2.6).

As well as the levels: Major, Minor, Patch and Revision, you can also set messages based on the versionCode of your app by using a minVersionCode field instead of minVersionName.

The following code shows how you can display "stricter" dialogs based on the version severity, with no dialog displayed for a versionCode change:

        Siren siren = Siren.getInstance(getApplicationContext());
        siren.setMajorUpdateAlertType(SirenAlertType.FORCE);
        siren.setMinorUpdateAlertType(SirenAlertType.OPTION);
        siren.setPatchUpdateAlertType(SirenAlertType.SKIP);
        siren.setRevisionUpdateAlertType(SirenAlertType.NONE);
        siren.checkVersion(this, SirenVersionCheckType.IMMEDIATELY, SIREN_JSON_DOCUMENT_URL);

If you'd like to just use versionCode for changes, you could check every time and force an update using code like this:

        Siren siren = Siren.getInstance(getApplicationContext());
        siren.setVersionCodeUpdateAlertType(SirenAlertType.FORCE);
        siren.checkVersion(this, SirenVersionCheckType.IMMEDIATELY, SIREN_JSON_DOCUMENT_URL);

Example

Some developers may want to display a less obtrusive custom interface, like a banner or small icon. You may also wish to control which level of update to force a user to update vs deferring to later.

You can find a fully functional sample project at https://github.com/eggheadgames/SirenSample.

Here is a code sample that shows how to handle all the alerts yourself:

    private void checkCurrentAppVersion() {
        Siren siren = Siren.getInstance(getApplicationContext());
        siren.setSirenListener(sirenListener);
        siren.setMajorUpdateAlertType(SirenAlertType.NONE);
        siren.setMinorUpdateAlertType(SirenAlertType.NONE);
        siren.setPatchUpdateAlertType(SirenAlertType.NONE);
        siren.setRevisionUpdateAlertType(SirenAlertType.NONE);
        siren.setVersionCodeUpdateAlertType(SirenAlertType.NONE);
        siren.checkVersion(this, SirenVersionCheckType.IMMEDIATELY, SIREN_JSON_DOCUMENT_URL);
    }

    ISirenListener sirenListener = new ISirenListener() {
        @Override
        public void onShowUpdateDialog() {
            Log.d(TAG, "onShowUpdateDialog");
        }

        @Override
        public void onLaunchGooglePlay() {
            Log.d(TAG, "onLaunchGooglePlay");
        }

        @Override
        public void onSkipVersion() {
            Log.d(TAG, "onSkipVersion");
        }

        @Override
        public void onCancel() {
            Log.d(TAG, "onCancel");
        }

        @Override
        public void onDetectNewVersionWithoutAlert(String message) {
            Log.d(TAG, "onDetectNewVersionWithoutAlert: " + message);
        }

        @Override
        public void onError(Exception e) {
            Log.d(TAG, "onError");
            e.printStackTrace();
        }
    };

Localization

Siren is localized for Arabic, Armenian, Basque, Chinese (Simplified), Chinese (Traditional), Danish, Dutch, English, Estonian, French, German, Greek, Hebrew, Hungarian, Italian, Japanese, Korean, Latvian, Lithuanian, Malay, Polish, Portuguese (Brazil), Portuguese (Portugal), Russian, Slovenian, Swedish, Spanish, Thai, and Turkish.

You may want the update dialog to always appear in a certain language, ignoring Android's language setting. This is supported with the setLanguageLocalization method. For example, you can force a French update dialog by setting the locale as follows:

    Siren.setLanguageLocalization(SirenSupportedLocales.FR)

Testing Siren

Change the url in your app to point to a test location (e.g. http://myjson.com/ is a convenient test site). Create an appropriate file and run your app with the temporary url.

For example, if my app's current version is 2.1.0.0 and the applicationId is com.eggheadgames.sirensample, I could create a json file with contents:

{"com.eggheadgames.sirensample":{"minVersionName":"2.2.1.1"}}

Then, add code like the following in the onCreate() of my app's home page:

    private Siren siren = Siren.getInstance(getApplicationContext());
    siren.checkVersion(this, SirenVersionCheckType.IMMEDIATELY, "https://api.myjson.com/bins/198mf");

Running this should show an update dialog when I start the app. Of course using a value other than IMMEDIATELY may not bring an immediate prompt, unless your SharedPreferences are being deleted between attempts.

siren's People

Contributors

alexdibrivnyy avatar apisov avatar bre7 avatar eggheadgames avatar mikemee avatar ntsparis avatar pirishd avatar yurii-diachenko avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

siren's Issues

Getting tons of SSL timeout

I've implemented this to my React Native app for a while now but I've just recently added logs on the SirenListener to monitor user conversion. I was surprised by tons of SSL handshake / connection timeout errors.

I couldn't reproduce the issue on my device, however, and I'm certain that my JSON endpoint has a valid SSL cert. (We have other endpoints on the same server and we've been using it without issue on the RN side).

It's possible that our CA might not be trusted by the Android system, because this is among the logs:
java.security.cert.CertPathValidatorException: Trust anchor for certification path not found.

Is there anyway I can load the cert and set a custom SSLSocketFactory? Or is there anything else I should look at?

Tidy up remaining default lint issues

Choosing Analyze -> Inspect Code shows a few lint issues that can tidied up, or tagged to be ignored (e.g. because they're not relevant for a ilbrary - such as unused code).

TBD: get a CI server running that will test for these on commit/PR...

Feature: Match strings with iOS version for better i18n

It would be great to leverage all the localisations available in the iOS Siren, and the easier we make it, the more likely it is to happen.

So, to make this easier for everyone, please use the same / similar names. E.g. iOS English is:

/* Update alert message: A new version of {APP NAME} is available. Please update to version {NEW VERSION} now.*/
"A new version of %@ is available. Please update to version %@ now." = "A new version of %@ is available. Please update to version %@ now.";

/* Update alert title */
"Update Available" = "Update Available";

/* Update alert dismiss button title */
"Next time" = "Next time";

/* Update alert skip button title */
"Skip this version" = "Skip this version";

/* Update alert skip button title */
"Update" = "Update";

So for strings.xml let's create a separate file with these names (note that app_name and fallback_app_name should go somewhere else):

<resources>
    <string name="update_alert_message">A new version of %s is available. Please update to version %s now.</string>
    <string name="update_available">Update available</string>
    <string name="next_time">Next time</string>
    <string name="skip_this_version">Skip this version</string>
    <string name="update">Update</string>
</resources>

Please add another couple of languages at the same time, just to "keep us honest" as we go forward.

Bug when customizing the Siren standard UI

I'm trying to display a custom UI when the app is out of date instead of the standard dialog provided in this library. I do this by following the README from the "Example"-section. When I follow that exact code (create my own ISirenListener and add my own UI in the onShowUpdateDialog-method) and set all Siren Alert-types to NONE, I get this error:

I open the app (I have a lower version number hard coded for testing so it will always be called) and my own custom UI is displayed. However, the standard Siren UI is still displayed underneath my own UI. When I close my own UI I can then see the Siren UI. I tried this for a custom dialog and standard snackbar and I get the same result for both.

I don't understand, if I set the Alert-types to NONE, then why does the standard Siren UI still appear? I only want my own UI to show.

Google Play Version Check

Any reason why this library hasn't implemented the ability to check against google play similar to this library (https://github.com/javiersantos/AppUpdater)? If this was added it would match the iOS like library (Harpy and Siren - Swift). Having a json file on my server and having to update that just for the Android version doesn't seem ideal when the iOS version just works out of the box. Just curious thanks.

Crash caused when json file is access via http (instead of https)

If the JSON version file is stored on an http server and is not available via https, then the library will cause a crash like this:

01-24 11:36:58.578 28106-28297/com.example E/AndroidRuntime: FATAL EXCEPTION: AsyncTask #2
     Process: com.example, PID: 28106
     java.lang.RuntimeException: An error occurred while executing doInBackground()
         at android.os.AsyncTask$3.done(AsyncTask.java:325)
         at java.util.concurrent.FutureTask.finishCompletion(FutureTask.java:354)
         at java.util.concurrent.FutureTask.setException(FutureTask.java:223)
         at java.util.concurrent.FutureTask.run(FutureTask.java:242)
         at android.os.AsyncTask$SerialExecutor$1.run(AsyncTask.java:243)
         at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1133)
         at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:607)
         at java.lang.Thread.run(Thread.java:761)
      Caused by: java.lang.ClassCastException: com.android.okhttp.internal.huc.HttpURLConnectionImpl cannot be cast to javax.net.ssl.HttpsURLConnection
         at com.eggheadgames.siren.Siren$LoadJsonTask.doInBackground(Siren.java:266)
         at com.eggheadgames.siren.Siren$LoadJsonTask.doInBackground(Siren.java:258)
         at android.os.AsyncTask$2.call(AsyncTask.java:305)
         at java.util.concurrent.FutureTask.run(FutureTask.java:237)
         at android.os.AsyncTask$SerialExecutor$1.run(AsyncTask.java:243) 
         at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1133) 
         at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:607) 
         at java.lang.Thread.run(Thread.java:761) 

This seems to have been introduced by #10 / #11 whereby the code now only works if the JSON file is fetched via https.

We should make two fixes:

  • allow an http url to be fetched (not just https)
  • silently fail, except for a debug log message, instead of crashing, if there is an error fetching the json file

Dialog Title "Update Available"

Dialog title is only showing on Android 5 device.
I have run the code on:
Samsung Note 3, Android 5.0.1 (Shows title)
Nexus 7, Android 6.0.1 (No title)
Samsung S6, Android 7.0.1 (No title)

How to i ensure that the title is showing on all devices?

just a question about frequency of .DAILY

I just want to know exactly how often the .DAILY checks (or WHEN it checks).

My issue is the following:

I have the checker set to .IMMEDIATELY right now. I store the version.json file on my github in /docs folder and commit it to the repo when I'm ready to release the update. The problem with this is that it causes people in my app to get the update message before the update is approved by Google Play (takes a few hours).

SO I thought .DAILY would be better. But, when I had it set to .DAILY, not matter how often I opened the app, it never seemed to notify me that there was an update. (this is why I set it to .IMMEDIATELY).

So what exactly is the frequency that triggers the .DAILY setting to display the dialog to the users of the app?

Additional method in ISirenListener

Is it possible to add another method to the ISirenListener? This method would be along the lines of "onNoAction" or "onNoUpdateAvailable".

I am hoping to check my app's version while in the splash screen. After the version has been checked, I would like to verify my stored api token's validity and take the user to 1 of 2 possible activities. With the current listener methods, I am not seeing a clear way to get this behavior when the user already has the most up to date version available. Maybe I am missing something though?

Thanks!

[solved]custom configurations ignored...cant set dialog to "force"

I tried multiple ways & even followed the sample to the letter, but I can't set my dialog to "force" so I can finally "force" my users to install the latest updates....it keeps using the default settings...the two button dismiss & update!
this is the only library that worked for me & its the simplest...but it just won't let me set my own configurations what so ever

I also even changed my json file from version name to versioncode just to be sure...but its still the same problem

request: check and show "You have the latest" dialog

its me again...annoying...right?
So I was wondering since I am able to check if my app has an update & if there is show an update dialog...but if there isn't an update then a no update dialog pops up saying "you have the latest update....blah blah"
it will be cool if this was an extra option...
could you also add this in the next update?

Buttons layout with long translated strings

For languages with long strings in buttons (like French or Russian), text is cut.

See attached screenshot for the French translation of "Next Time" ("La prochaine fois")

screenshot

Support parsing of additional parameters on the JSON file

Hello,

I'm using this library alongside with the iOS counterpart, and I'm planning on using the same JSON file for both. Other than setting minVersionCode, I would also like to toggle version check and set alertType from that. While I can do parsing manually on iOS, I wonder if there's a way to retrieve the additional parameters on Android, since I don't have to handle download & parsing here?

Thank you!

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.