├── .gitattributes ├── .gitignore ├── README.md ├── image-old.png ├── image.png ├── jar ├── changelog.txt ├── wversionmanager-1.0.jar ├── wversionmanager-1.1.jar ├── wversionmanager-1.2.jar └── wversionmanager-1.3.jar ├── library ├── AndroidManifest.xml ├── gen │ └── com │ │ └── winsontan520 │ │ └── wversionmanager │ │ └── library │ │ ├── BuildConfig.java │ │ └── R.java ├── libs │ └── android-support-v4.jar ├── proguard-project.txt ├── project.properties ├── res │ ├── drawable-hdpi │ │ └── ic_launcher.png │ ├── drawable-mdpi │ │ └── ic_launcher.png │ ├── drawable-xhdpi │ │ └── ic_launcher.png │ ├── values-v11 │ │ └── styles.xml │ ├── values-v14 │ │ └── styles.xml │ └── values │ │ ├── strings.xml │ │ └── styles.xml └── src │ └── com │ └── winsontan520 │ └── wversionmanager │ └── library │ ├── CustomTagHandler.java │ ├── IWVersionManager.java │ ├── OnReceiveListener.java │ └── WVersionManager.java ├── phone-1.png ├── phone-2.png ├── phone-3.png ├── phone-4.png ├── sample ├── AndroidManifest.xml ├── ic_launcher-web.png ├── libs │ └── android-support-v4.jar ├── proguard-project.txt ├── project.properties ├── res │ ├── drawable-hdpi │ │ └── ic_launcher.png │ ├── drawable-ldpi │ │ └── ic_launcher.png │ ├── drawable-mdpi │ │ └── ic_launcher.png │ ├── drawable-xhdpi │ │ └── ic_launcher.png │ ├── layout │ │ ├── ask_for_rate.xml │ │ └── check_version.xml │ ├── menu │ │ └── activity_main.xml │ ├── values-v11 │ │ └── styles.xml │ ├── values-v14 │ │ └── styles.xml │ └── values │ │ ├── strings.xml │ │ └── styles.xml └── src │ └── com │ └── winsontan520 │ └── wversionmanager │ └── sample │ ├── AskForRateActivity.java │ ├── CheckVersionActivity.java │ └── ExampleListActivity.java ├── update_content_json_format.txt ├── version_2.txt └── version_3.txt /.gitattributes: -------------------------------------------------------------------------------- 1 | # Auto detect text files and perform LF normalization 2 | * text=auto 3 | 4 | # Custom for Visual Studio 5 | *.cs diff=csharp 6 | *.sln merge=union 7 | *.csproj merge=union 8 | *.vbproj merge=union 9 | *.fsproj merge=union 10 | *.dbproj merge=union 11 | 12 | # Standard to msysgit 13 | *.doc diff=astextplain 14 | *.DOC diff=astextplain 15 | *.docx diff=astextplain 16 | *.DOCX diff=astextplain 17 | *.dot diff=astextplain 18 | *.DOT diff=astextplain 19 | *.pdf diff=astextplain 20 | *.PDF diff=astextplain 21 | *.rtf diff=astextplain 22 | *.RTF diff=astextplain 23 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | ################# 2 | ## Eclipse 3 | ################# 4 | 5 | *.pydevproject 6 | .project 7 | .metadata 8 | gen/ 9 | bin/ 10 | tmp/ 11 | *.tmp 12 | *.bak 13 | *.swp 14 | *~.nib 15 | local.properties 16 | .classpath 17 | .settings/ 18 | .loadpath 19 | 20 | # External tool builders 21 | .externalToolBuilders/ 22 | 23 | # Locally stored "Eclipse launch configurations" 24 | *.launch 25 | 26 | # CDT-specific 27 | .cproject 28 | 29 | # PDT-specific 30 | .buildpath 31 | 32 | 33 | ################# 34 | ## Visual Studio 35 | ################# 36 | 37 | ## Ignore Visual Studio temporary files, build results, and 38 | ## files generated by popular Visual Studio add-ons. 39 | 40 | # User-specific files 41 | *.suo 42 | *.user 43 | *.sln.docstates 44 | 45 | # Build results 46 | [Dd]ebug/ 47 | [Rr]elease/ 48 | *_i.c 49 | *_p.c 50 | *.ilk 51 | *.meta 52 | *.obj 53 | *.pch 54 | *.pdb 55 | *.pgc 56 | *.pgd 57 | *.rsp 58 | *.sbr 59 | *.tlb 60 | *.tli 61 | *.tlh 62 | *.tmp 63 | *.vspscc 64 | .builds 65 | *.dotCover 66 | 67 | ## TODO: If you have NuGet Package Restore enabled, uncomment this 68 | #packages/ 69 | 70 | # Visual C++ cache files 71 | ipch/ 72 | *.aps 73 | *.ncb 74 | *.opensdf 75 | *.sdf 76 | 77 | # Visual Studio profiler 78 | *.psess 79 | *.vsp 80 | 81 | # ReSharper is a .NET coding add-in 82 | _ReSharper* 83 | 84 | # Installshield output folder 85 | [Ee]xpress 86 | 87 | # DocProject is a documentation generator add-in 88 | DocProject/buildhelp/ 89 | DocProject/Help/*.HxT 90 | DocProject/Help/*.HxC 91 | DocProject/Help/*.hhc 92 | DocProject/Help/*.hhk 93 | DocProject/Help/*.hhp 94 | DocProject/Help/Html2 95 | DocProject/Help/html 96 | 97 | # Click-Once directory 98 | publish 99 | 100 | # Others 101 | [Bb]in 102 | [Oo]bj 103 | sql 104 | TestResults 105 | *.Cache 106 | ClientBin 107 | stylecop.* 108 | ~$* 109 | *.dbmdl 110 | Generated_Code #added for RIA/Silverlight projects 111 | 112 | # Backup & report files from converting an old project file to a newer 113 | # Visual Studio version. Backup files are not needed, because we have git ;-) 114 | _UpgradeReport_Files/ 115 | Backup*/ 116 | UpgradeLog*.XML 117 | 118 | 119 | 120 | ############ 121 | ## Windows 122 | ############ 123 | 124 | # Windows image file caches 125 | Thumbs.db 126 | 127 | # Folder config file 128 | Desktop.ini 129 | 130 | 131 | ############# 132 | ## Python 133 | ############# 134 | 135 | *.py[co] 136 | 137 | # Packages 138 | *.egg 139 | *.egg-info 140 | dist 141 | build 142 | eggs 143 | parts 144 | bin 145 | var 146 | sdist 147 | develop-eggs 148 | .installed.cfg 149 | 150 | # Installer logs 151 | pip-log.txt 152 | 153 | # Unit test / coverage reports 154 | .coverage 155 | .tox 156 | 157 | #Translations 158 | *.mo 159 | 160 | #Mr Developer 161 | .mr.developer.cfg 162 | 163 | # Mac crap 164 | .DS_Store 165 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | PLEASE NOTE, THIS PROJECT IS NO LONGER BEING MAINTAINED 2 | ==================== 3 | ## PLEASE INFORM ME THE IMPROVED VERSION SO I CAN LINK IT FOR OTHER USERS 4 | 5 | Following links are the improved version by others: 6 | - [revanmj](https://github.com/revanmj/Android-WVersionManager) 7 | 8 | ## Objective 9 | - Save time to implement check new update available since Google play havent provide any API to check (written at Jan 2013) 10 | - Ask user for rate 11 | 12 | ## Features 13 | - Show Alert Dialog with new update content and 3 options button: update now, remind me later and ignore this version. 14 | - Callback to implement your own custom logic 15 | - Show Alert Dialog to prompt user ask for rating 16 | - Few lines of code to implement. 17 | 18 | ## Changelog 19 | - v1.1 Ask for rating 20 | - v1.2 Add OnReceive callback when response 21 | - v1.3 Fix error handling callback 22 | 23 | ## Screenshots 24 | ![Screenshot](https://github.com/winsontan520/Android-WVersionManager/raw/master/image.png) 25 | 26 | ## Demo 27 | [![Get it on Google Play](http://www.android.com/images/brand/get_it_on_play_logo_small.png)](http://play.google.com/store/apps/details?id=com.winsontan520.wversionmanager.sample) 28 | 29 | ## Usage - Check Version for latest update 30 | 1. Copy latest version of jarfile in folder JAR to your project libs folder. You may also check out src used as project library. 31 | 2. For check version, in your Activity, 32 | 33 | protected void onCreate(Bundle savedInstanceState) { 34 | super.onCreate(savedInstanceState); 35 | setContentView(R.layout.activity_main); 36 | 37 | WVersionManager versionManager = new WVersionManager(this); 38 | versionManager.setVersionContentUrl("http://bit.ly/11c7Pnb"); // your update content url, see the response format below 39 | versionManager.checkVersion(); 40 | } 41 | 42 | 3. The Version Content Url must return response with json format which follow this format. To save time for testing you may just put content in static text file. 43 | 44 | { 45 | "version_code": 2, 46 | "content": "Version 2.0

New features:

  • Added feature A
  • Added feature B
  • Added feature C
  • Added feature D
  • Added feature E
  • Added feature F
  • Added feature G
  • " 47 | } 48 | 49 | 4. You can also customize label and reminder time eg: 50 | 51 | versionManager.setUpdateNowLabel("Custom update now label"); 52 | versionManager.setRemindMeLaterLabel("Custom remind me later label"); 53 | versionManager.setIgnoreThisVersionLabel("Custom ignore this version"); 54 | versionManager.setUpdateUrl("http://your_app_url"); // this is the link will execute when update now clicked. default will go to google play based on your package name. 55 | versionManager.setReminderTimer(10); // this mean checkVersion() will not take effect within 10 minutes 56 | 57 | 5. Set callback for your own implementation: 58 | ``` 59 | versionManager.setOnReceiveListener(new OnReceiveListener() { 60 | @Override 61 | public boolean onReceive(int status, String result) { 62 | // implement your own compare logic here 63 | return false; // return true if you want to use library's default logic & dialog 64 | } 65 | }); 66 | ``` 67 | ## Usage - Ask user for rate 68 | 1. Copy latest version of jarfile in folder JAR to your project libs folder. You may also check out src used as project library. 69 | 2. Add following lines to prompt user dialog for rating 70 | 71 | WVersionManager versionManager = new WVersionManager(this); 72 | versionManager.askForRate(); 73 | 74 | 3. Customize label for ask for rate: 75 | 76 | versionManager.setTitle("Please rate us"); // optional 77 | versionManager.setMessage("We need your help to rate this app!"); // optional 78 | versionManager.setAskForRatePositiveLabel("OK"); // optional 79 | versionManager.setAskForRateNegativeLabel("Not now"); // optional 80 | 81 | ## License - Free to use 82 | Copyright 2013 Winson Tan 83 | 84 | Licensed under the Apache License, Version 2.0 (the "License"); 85 | you may not use this file except in compliance with the License. 86 | You may obtain a copy of the License at 87 | 88 | http://www.apache.org/licenses/LICENSE-2.0 89 | 90 | Unless required by applicable law or agreed to in writing, software 91 | distributed under the License is distributed on an "AS IS" BASIS, 92 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 93 | See the License for the specific language governing permissions and 94 | limitations under the License. 95 | -------------------------------------------------------------------------------- /image-old.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/winsontan520/Android-WVersionManager/a6e90bdb936169a4b0ac63debe2cfb8c7f61ac26/image-old.png -------------------------------------------------------------------------------- /image.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/winsontan520/Android-WVersionManager/a6e90bdb936169a4b0ac63debe2cfb8c7f61ac26/image.png -------------------------------------------------------------------------------- /jar/changelog.txt: -------------------------------------------------------------------------------- 1 | 2 | 1.1 3 | Add ask for rate feature 4 | 5 | 1.0 6 | Base version -------------------------------------------------------------------------------- /jar/wversionmanager-1.0.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/winsontan520/Android-WVersionManager/a6e90bdb936169a4b0ac63debe2cfb8c7f61ac26/jar/wversionmanager-1.0.jar -------------------------------------------------------------------------------- /jar/wversionmanager-1.1.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/winsontan520/Android-WVersionManager/a6e90bdb936169a4b0ac63debe2cfb8c7f61ac26/jar/wversionmanager-1.1.jar -------------------------------------------------------------------------------- /jar/wversionmanager-1.2.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/winsontan520/Android-WVersionManager/a6e90bdb936169a4b0ac63debe2cfb8c7f61ac26/jar/wversionmanager-1.2.jar -------------------------------------------------------------------------------- /jar/wversionmanager-1.3.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/winsontan520/Android-WVersionManager/a6e90bdb936169a4b0ac63debe2cfb8c7f61ac26/jar/wversionmanager-1.3.jar -------------------------------------------------------------------------------- /library/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 5 | 6 | 9 | 10 | 15 | 16 | 17 | -------------------------------------------------------------------------------- /library/gen/com/winsontan520/wversionmanager/library/BuildConfig.java: -------------------------------------------------------------------------------- 1 | /** Automatically generated file. DO NOT MODIFY */ 2 | package com.winsontan520.wversionmanager.library; 3 | 4 | public final class BuildConfig { 5 | public final static boolean DEBUG = true; 6 | } -------------------------------------------------------------------------------- /library/gen/com/winsontan520/wversionmanager/library/R.java: -------------------------------------------------------------------------------- 1 | /* AUTO-GENERATED FILE. DO NOT MODIFY. 2 | * 3 | * This class was automatically generated by the 4 | * aapt tool from the resource data it found. It 5 | * should not be modified by hand. 6 | */ 7 | 8 | package com.winsontan520.wversionmanager.library; 9 | 10 | public final class R { 11 | public static final class attr { 12 | } 13 | public static final class drawable { 14 | public static int ic_launcher=0x7f020000; 15 | } 16 | public static final class string { 17 | public static int app_name=0x7f030000; 18 | } 19 | public static final class style { 20 | /** 21 | Base application theme, dependent on API level. This theme is replaced 22 | by AppBaseTheme from res/values-vXX/styles.xml on newer devices. 23 | 24 | 25 | Theme customizations available in newer API levels can go in 26 | res/values-vXX/styles.xml, while customizations related to 27 | backward-compatibility can go here. 28 | 29 | 30 | Base application theme for API 11+. This theme completely replaces 31 | AppBaseTheme from res/values/styles.xml on API 11+ devices. 32 | 33 | API 11 theme customizations can go here. 34 | 35 | Base application theme for API 14+. This theme completely replaces 36 | AppBaseTheme from BOTH res/values/styles.xml and 37 | res/values-v11/styles.xml on API 14+ devices. 38 | 39 | API 14 theme customizations can go here. 40 | */ 41 | public static int AppBaseTheme=0x7f040000; 42 | /** Application theme. 43 | All customizations that are NOT specific to a particular API-level can go here. 44 | */ 45 | public static int AppTheme=0x7f040001; 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /library/libs/android-support-v4.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/winsontan520/Android-WVersionManager/a6e90bdb936169a4b0ac63debe2cfb8c7f61ac26/library/libs/android-support-v4.jar -------------------------------------------------------------------------------- /library/proguard-project.txt: -------------------------------------------------------------------------------- 1 | # To enable ProGuard in your project, edit project.properties 2 | # to define the proguard.config property as described in that file. 3 | # 4 | # Add project specific ProGuard rules here. 5 | # By default, the flags in this file are appended to flags specified 6 | # in ${sdk.dir}/tools/proguard/proguard-android.txt 7 | # You can edit the include path and order by changing the ProGuard 8 | # include property in project.properties. 9 | # 10 | # For more details, see 11 | # http://developer.android.com/guide/developing/tools/proguard.html 12 | 13 | # Add any project specific keep options here: 14 | 15 | # If your project uses WebView with JS, uncomment the following 16 | # and specify the fully qualified class name to the JavaScript interface 17 | # class: 18 | #-keepclassmembers class fqcn.of.javascript.interface.for.webview { 19 | # public *; 20 | #} 21 | -------------------------------------------------------------------------------- /library/project.properties: -------------------------------------------------------------------------------- 1 | # This file is automatically generated by Android Tools. 2 | # Do not modify this file -- YOUR CHANGES WILL BE ERASED! 3 | # 4 | # This file must be checked in Version Control Systems. 5 | # 6 | # To customize properties used by the Ant build system edit 7 | # "ant.properties", and override values to adapt the script to your 8 | # project structure. 9 | # 10 | # To enable ProGuard to shrink and obfuscate your code, uncomment this (available properties: sdk.dir, user.home): 11 | #proguard.config=${sdk.dir}/tools/proguard/proguard-android.txt:proguard-project.txt 12 | 13 | # Project target. 14 | target=android-14 15 | android.library=true 16 | -------------------------------------------------------------------------------- /library/res/drawable-hdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/winsontan520/Android-WVersionManager/a6e90bdb936169a4b0ac63debe2cfb8c7f61ac26/library/res/drawable-hdpi/ic_launcher.png -------------------------------------------------------------------------------- /library/res/drawable-mdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/winsontan520/Android-WVersionManager/a6e90bdb936169a4b0ac63debe2cfb8c7f61ac26/library/res/drawable-mdpi/ic_launcher.png -------------------------------------------------------------------------------- /library/res/drawable-xhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/winsontan520/Android-WVersionManager/a6e90bdb936169a4b0ac63debe2cfb8c7f61ac26/library/res/drawable-xhdpi/ic_launcher.png -------------------------------------------------------------------------------- /library/res/values-v11/styles.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 7 | 10 | 11 | -------------------------------------------------------------------------------- /library/res/values-v14/styles.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 8 | 11 | 12 | -------------------------------------------------------------------------------- /library/res/values/strings.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | WVersionManager 4 | 5 | -------------------------------------------------------------------------------- /library/res/values/styles.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 7 | 14 | 15 | 16 | 19 | 20 | -------------------------------------------------------------------------------- /library/src/com/winsontan520/wversionmanager/library/CustomTagHandler.java: -------------------------------------------------------------------------------- 1 | package com.winsontan520.wversionmanager.library; 2 | 3 | import org.xml.sax.XMLReader; 4 | 5 | import android.text.Editable; 6 | import android.text.Html.TagHandler; 7 | 8 | public class CustomTagHandler implements TagHandler{ 9 | 10 | @Override 11 | public void handleTag(boolean opening, String tag, Editable output, 12 | XMLReader xmlReader) { 13 | // you may add more tag handler which are not supported by android here 14 | if("li".equals(tag)){ 15 | if(opening){ 16 | output.append(" \u2022 "); 17 | }else{ 18 | output.append("\n"); 19 | } 20 | } 21 | } 22 | } -------------------------------------------------------------------------------- /library/src/com/winsontan520/wversionmanager/library/IWVersionManager.java: -------------------------------------------------------------------------------- 1 | package com.winsontan520.wversionmanager.library; 2 | 3 | import android.graphics.drawable.Drawable; 4 | 5 | public interface IWVersionManager { 6 | 7 | /** 8 | * @return Label of update now button 9 | */ 10 | public String getUpdateNowLabel(); 11 | 12 | 13 | /** 14 | * @param updateNowLabel Set the label for update now button 15 | */ 16 | public void setUpdateNowLabel(String updateNowLabel); 17 | 18 | /** 19 | * @return label of remind me later button 20 | */ 21 | public String getRemindMeLaterLabel(); 22 | 23 | /** 24 | * @param remindMeLaterLabel Set label of remind me later button 25 | */ 26 | public void setRemindMeLaterLabel(String remindMeLaterLabel); 27 | 28 | /** 29 | * @return label of ignore this version button 30 | */ 31 | public String getIgnoreThisVersionLabel(); 32 | 33 | /** 34 | * @param ignoreThisVersionLabel Set label of ignore this version button 35 | */ 36 | public void setIgnoreThisVersionLabel(String ignoreThisVersionLabel); 37 | 38 | /** 39 | * @param icon Set drawable of icon in dialog 40 | */ 41 | public void setIcon(Drawable icon); 42 | 43 | /** 44 | * @param title Set title of dialog 45 | */ 46 | public void setTitle(String title); 47 | 48 | /** 49 | * @param message Set message of dialog 50 | */ 51 | public void setMessage(String message); 52 | 53 | /** 54 | * @return message of dialog 55 | */ 56 | public String getMessage(); 57 | 58 | /** 59 | * @return title of dialog 60 | */ 61 | public String getTitle(); 62 | 63 | /** 64 | * @return drawable of icon 65 | */ 66 | public Drawable getIcon(); 67 | 68 | /** 69 | * @return url to execute when update now button clicked. Default value is the link in google play based on app package name. 70 | */ 71 | public String getUpdateUrl(); 72 | 73 | /** 74 | * @param updateUrl Set url to execute when update now button clicked 75 | */ 76 | public void setUpdateUrl(String updateUrl); 77 | 78 | /** 79 | * @return url which should return update content in json format 80 | */ 81 | public String getVersionContentUrl(); 82 | 83 | /** 84 | * @param versionContentUrl Set the update content url 85 | */ 86 | public void setVersionContentUrl(String versionContentUrl); 87 | 88 | /** 89 | * @param minutes Set reminder time in minutes when remind me later button clicked 90 | */ 91 | public void setReminderTimer(int minutes); 92 | 93 | /** 94 | * @return reminder timer in minutes 95 | */ 96 | public int getReminderTimer(); 97 | 98 | /** 99 | * @return current version code 100 | */ 101 | public int getCurrentVersionCode(); 102 | 103 | /** 104 | * @return version code which will be ignored 105 | */ 106 | public int getIgnoreVersionCode(); 107 | 108 | /** 109 | * @return CustomTagHandler object 110 | */ 111 | public CustomTagHandler getCustomTagHandler(); 112 | 113 | /** 114 | * @param customTagHandler Set your own custom tag handler 115 | */ 116 | public void setCustomTagHandler(CustomTagHandler customTagHandler); 117 | 118 | /** 119 | * @param OnReceiveListener Set your own callback listener when receiving response from server 120 | */ 121 | public void setOnReceiveListener(OnReceiveListener listener); 122 | 123 | } -------------------------------------------------------------------------------- /library/src/com/winsontan520/wversionmanager/library/OnReceiveListener.java: -------------------------------------------------------------------------------- 1 | package com.winsontan520.wversionmanager.library; 2 | 3 | public interface OnReceiveListener { 4 | 5 | /** 6 | * @param status response code from HTTP request 7 | * @param result response data from HTTP request 8 | * @return return true to show default library dialog 9 | */ 10 | boolean onReceive(int status, String result); 11 | } 12 | -------------------------------------------------------------------------------- /library/src/com/winsontan520/wversionmanager/library/WVersionManager.java: -------------------------------------------------------------------------------- 1 | package com.winsontan520.wversionmanager.library; 2 | 3 | import java.io.ByteArrayOutputStream; 4 | import java.io.IOException; 5 | import java.util.Calendar; 6 | 7 | import org.apache.http.HttpResponse; 8 | import org.apache.http.HttpStatus; 9 | import org.apache.http.client.methods.HttpGet; 10 | import org.apache.http.impl.client.DefaultHttpClient; 11 | import org.json.JSONException; 12 | import org.json.JSONObject; 13 | import org.json.JSONTokener; 14 | 15 | import android.app.Activity; 16 | import android.app.AlertDialog; 17 | import android.content.Context; 18 | import android.content.DialogInterface; 19 | import android.content.Intent; 20 | import android.content.pm.PackageInfo; 21 | import android.content.pm.PackageManager.NameNotFoundException; 22 | import android.graphics.drawable.Drawable; 23 | import android.net.Uri; 24 | import android.os.AsyncTask; 25 | import android.preference.PreferenceManager; 26 | import android.text.Html; 27 | import android.util.Log; 28 | 29 | public class WVersionManager implements IWVersionManager { 30 | private static final String TAG = "WVersionManager"; 31 | 32 | private static final int MODE_CHECK_VERSION = 100; 33 | private static final int MODE_ASK_FOR_RATE = 200; 34 | 35 | private CustomTagHandler customTagHandler; 36 | 37 | private String PREF_IGNORE_VERSION_CODE = "w.ignore.version.code"; 38 | private String PREF_REMINDER_TIME = "w.reminder.time"; 39 | 40 | private Activity activity; 41 | private Drawable icon; 42 | private String title; 43 | private String message; 44 | private String updateNowLabel; 45 | private String remindMeLaterLabel; 46 | private String ignoreThisVersionLabel; 47 | private String updateUrl; 48 | private String versionContentUrl; 49 | private int reminderTimer; 50 | private int mVersionCode; 51 | private AlertDialogButtonListener listener; 52 | private boolean mDialogCancelable = true; 53 | private boolean mIsAskForRate = false; 54 | private String mAskForRatePositiveLabel; 55 | private String mAskForRateNegativeLabel; 56 | private int mMode = 100; // default mode 57 | private OnReceiveListener mOnReceiveListener; 58 | private String mResult; 59 | 60 | public WVersionManager(Activity act) { 61 | this.activity = act; 62 | this.listener = new AlertDialogButtonListener(); 63 | this.customTagHandler = new CustomTagHandler(); 64 | } 65 | 66 | private Drawable getDefaultAppIcon() { 67 | Drawable d = activity.getApplicationInfo().loadIcon(activity.getPackageManager()); 68 | return d; 69 | } 70 | 71 | public void checkVersion() { 72 | mMode = MODE_CHECK_VERSION; 73 | String versionContentUrl = getVersionContentUrl(); 74 | if (versionContentUrl == null) { 75 | Log.e(TAG, "Please set versionContentUrl first"); 76 | return; 77 | } 78 | 79 | Calendar c = Calendar.getInstance(); 80 | long currentTimeStamp = c.getTimeInMillis(); 81 | long reminderTimeStamp = getReminderTime(); 82 | if (BuildConfig.DEBUG) { 83 | Log.v(TAG, "currentTimeStamp=" + currentTimeStamp); 84 | Log.v(TAG, "reminderTimeStamp=" + reminderTimeStamp); 85 | } 86 | 87 | if (currentTimeStamp > reminderTimeStamp) { 88 | // fire request to get update version content 89 | if (BuildConfig.DEBUG) { 90 | Log.v(TAG, "getting update content..."); 91 | } 92 | VersionContentRequest request = new VersionContentRequest(activity); 93 | request.execute(getVersionContentUrl()); 94 | } 95 | } 96 | 97 | private void showDialog() { 98 | AlertDialog.Builder builder = new AlertDialog.Builder(activity); 99 | 100 | builder.setIcon(getIcon()); 101 | builder.setTitle(getTitle()); 102 | builder.setMessage(Html.fromHtml(getMessage(), null, getCustomTagHandler())); 103 | 104 | switch (mMode) { 105 | case MODE_CHECK_VERSION: 106 | builder.setPositiveButton(getUpdateNowLabel(), listener); 107 | builder.setNeutralButton(getRemindMeLaterLabel(), listener); 108 | builder.setNegativeButton(getIgnoreThisVersionLabel(), listener); 109 | break; 110 | case MODE_ASK_FOR_RATE: 111 | builder.setPositiveButton(getAskForRatePositiveLabel(), listener); 112 | builder.setNegativeButton(getAskForRateNegativeLabel(), listener); 113 | break; 114 | default: 115 | return; 116 | } 117 | 118 | builder.setCancelable(isDialogCancelable()); 119 | 120 | AlertDialog dialog = builder.create(); 121 | if (activity != null && !activity.isFinishing()) { 122 | dialog.show(); 123 | } 124 | } 125 | 126 | /* 127 | * (non-Javadoc) 128 | * 129 | * @see 130 | * com.winsontan520.wversionmanagertest.IWVersionManager#getUpdateNowLabel() 131 | */ 132 | @Override 133 | public String getUpdateNowLabel() { 134 | return updateNowLabel != null ? updateNowLabel : "Update now"; 135 | } 136 | 137 | /* 138 | * (non-Javadoc) 139 | * 140 | * @see 141 | * com.winsontan520.wversionmanagertest.IWVersionManager#setUpdateNowLabel 142 | * (java.lang.String) 143 | */ 144 | @Override 145 | public void setUpdateNowLabel(String updateNowLabel) { 146 | this.updateNowLabel = updateNowLabel; 147 | } 148 | 149 | /* 150 | * (non-Javadoc) 151 | * 152 | * @see 153 | * com.winsontan520.wversionmanagertest.IWVersionManager#getRemindMeLaterLabel 154 | * () 155 | */ 156 | @Override 157 | public String getRemindMeLaterLabel() { 158 | return remindMeLaterLabel != null ? remindMeLaterLabel : "Remind me later"; 159 | } 160 | 161 | /* 162 | * (non-Javadoc) 163 | * 164 | * @see 165 | * com.winsontan520.wversionmanagertest.IWVersionManager#setRemindMeLaterLabel 166 | * (java.lang.String) 167 | */ 168 | @Override 169 | public void setRemindMeLaterLabel(String remindMeLaterLabel) { 170 | this.remindMeLaterLabel = remindMeLaterLabel; 171 | } 172 | 173 | /* 174 | * (non-Javadoc) 175 | * 176 | * @see com.winsontan520.wversionmanagertest.IWVersionManager# 177 | * getIgnoreThisVersionLabel() 178 | */ 179 | @Override 180 | public String getIgnoreThisVersionLabel() { 181 | return ignoreThisVersionLabel != null ? ignoreThisVersionLabel : "Ignore this version"; 182 | } 183 | 184 | /* 185 | * (non-Javadoc) 186 | * 187 | * @see com.winsontan520.wversionmanagertest.IWVersionManager# 188 | * setIgnoreThisVersionLabel(java.lang.String) 189 | */ 190 | @Override 191 | public void setIgnoreThisVersionLabel(String ignoreThisVersionLabel) { 192 | this.ignoreThisVersionLabel = ignoreThisVersionLabel; 193 | } 194 | 195 | /* 196 | * (non-Javadoc) 197 | * 198 | * @see 199 | * com.winsontan520.wversionmanagertest.IWVersionManager#setIcon(android 200 | * .graphics.drawable.Drawable) 201 | */ 202 | @Override 203 | public void setIcon(Drawable icon) { 204 | this.icon = icon; 205 | } 206 | 207 | /* 208 | * (non-Javadoc) 209 | * 210 | * @see 211 | * com.winsontan520.wversionmanagertest.IWVersionManager#setTitle(java.lang 212 | * .String) 213 | */ 214 | @Override 215 | public void setTitle(String title) { 216 | this.title = title; 217 | } 218 | 219 | /* 220 | * (non-Javadoc) 221 | * 222 | * @see 223 | * com.winsontan520.wversionmanagertest.IWVersionManager#setMessage(java 224 | * .lang.String) 225 | */ 226 | @Override 227 | public void setMessage(String message) { 228 | this.message = message; 229 | } 230 | 231 | /* 232 | * (non-Javadoc) 233 | * 234 | * @see com.winsontan520.wversionmanagertest.IWVersionManager#getMessage() 235 | */ 236 | @Override 237 | public String getMessage() { 238 | String defaultMessage = null; 239 | switch (mMode) { 240 | case MODE_CHECK_VERSION: 241 | defaultMessage = "What's new in this version"; 242 | break; 243 | case MODE_ASK_FOR_RATE: 244 | defaultMessage = "Please rate us!"; 245 | break; 246 | } 247 | 248 | return message != null ? message : defaultMessage; 249 | } 250 | 251 | /* 252 | * (non-Javadoc) 253 | * 254 | * @see com.winsontan520.wversionmanagertest.IWVersionManager#getTitle() 255 | */ 256 | @Override 257 | public String getTitle() { 258 | String defaultTitle = null; 259 | switch (mMode) { 260 | case MODE_CHECK_VERSION: 261 | defaultTitle = "New Update Available"; 262 | break; 263 | case MODE_ASK_FOR_RATE: 264 | defaultTitle = "Rate this app"; 265 | break; 266 | } 267 | return title != null ? title : defaultTitle; 268 | } 269 | 270 | /* 271 | * (non-Javadoc) 272 | * 273 | * @see com.winsontan520.wversionmanagertest.IWVersionManager#getIcon() 274 | */ 275 | @Override 276 | public Drawable getIcon() { 277 | return icon != null ? icon : getDefaultAppIcon(); 278 | } 279 | 280 | /* 281 | * (non-Javadoc) 282 | * 283 | * @see com.winsontan520.wversionmanagertest.IWVersionManager#getUpdateUrl() 284 | */ 285 | @Override 286 | public String getUpdateUrl() { 287 | return updateUrl != null ? updateUrl : getGooglePlayStoreUrl(); 288 | } 289 | 290 | /* 291 | * (non-Javadoc) 292 | * 293 | * @see 294 | * com.winsontan520.wversionmanagertest.IWVersionManager#setUpdateUrl(java 295 | * .lang.String) 296 | */ 297 | @Override 298 | public void setUpdateUrl(String updateUrl) { 299 | this.updateUrl = updateUrl; 300 | } 301 | 302 | /* 303 | * (non-Javadoc) 304 | * 305 | * @see 306 | * com.winsontan520.wversionmanagertest.IWVersionManager#getVersionContentUrl 307 | * () 308 | */ 309 | @Override 310 | public String getVersionContentUrl() { 311 | return versionContentUrl; 312 | } 313 | 314 | /* 315 | * (non-Javadoc) 316 | * 317 | * @see 318 | * com.winsontan520.wversionmanagertest.IWVersionManager#setVersionContentUrl 319 | * (java.lang.String) 320 | */ 321 | @Override 322 | public void setVersionContentUrl(String versionContentUrl) { 323 | this.versionContentUrl = versionContentUrl; 324 | } 325 | 326 | /* 327 | * (non-Javadoc) 328 | * 329 | * @see 330 | * com.winsontan520.wversionmanagertest.IWVersionManager#setVersionContentUrl 331 | * (java.lang.String) 332 | */ 333 | @Override 334 | public int getReminderTimer() { 335 | return reminderTimer > 0 ? reminderTimer : (1 * 60); // default value 60 336 | // minutes 337 | } 338 | 339 | /* 340 | * (non-Javadoc) 341 | * 342 | * @see 343 | * com.winsontan520.wversionmanagertest.IWVersionManager#setReminderTimer 344 | * (int) 345 | */ 346 | @Override 347 | public void setReminderTimer(int minutes) { 348 | if (minutes > 0) { 349 | reminderTimer = minutes; 350 | } 351 | } 352 | 353 | private void updateNow(String url) { 354 | if (url != null) { 355 | try { 356 | Uri uri = Uri.parse(url); 357 | Intent intent = new Intent(Intent.ACTION_VIEW, uri); 358 | activity.startActivity(intent); 359 | } catch (Exception e) { 360 | Log.e(TAG, "is update url correct?" + e); 361 | } 362 | } 363 | 364 | } 365 | 366 | private void remindMeLater(int reminderTimer) { 367 | Calendar c = Calendar.getInstance(); 368 | long currentTimeStamp = c.getTimeInMillis(); 369 | 370 | c.add(Calendar.MINUTE, reminderTimer); 371 | long reminderTimeStamp = c.getTimeInMillis(); 372 | 373 | if (BuildConfig.DEBUG) { 374 | Log.v(TAG, "currentTimeStamp=" + currentTimeStamp); 375 | Log.v(TAG, "reminderTimeStamp=" + reminderTimeStamp); 376 | } 377 | 378 | setReminderTime(reminderTimeStamp); 379 | } 380 | 381 | private void setReminderTime(long reminderTimeStamp) { 382 | PreferenceManager.getDefaultSharedPreferences(activity).edit().putLong(PREF_REMINDER_TIME, reminderTimeStamp) 383 | .commit(); 384 | } 385 | 386 | private long getReminderTime() { 387 | return PreferenceManager.getDefaultSharedPreferences(activity).getLong(PREF_REMINDER_TIME, 0); 388 | } 389 | 390 | private void ignoreThisVersion() { 391 | PreferenceManager.getDefaultSharedPreferences(activity).edit().putInt(PREF_IGNORE_VERSION_CODE, mVersionCode) 392 | .commit(); 393 | } 394 | 395 | private String getGooglePlayStoreUrl() { 396 | String id = activity.getApplicationInfo().packageName; // current google 397 | // play is using 398 | // package name 399 | // as id 400 | return "market://details?id=" + id; 401 | } 402 | 403 | private class AlertDialogButtonListener implements DialogInterface.OnClickListener { 404 | 405 | @Override 406 | public void onClick(DialogInterface dialog, int which) { 407 | switch (which) { 408 | case AlertDialog.BUTTON_POSITIVE: 409 | updateNow(getUpdateUrl()); 410 | break; 411 | case AlertDialog.BUTTON_NEUTRAL: 412 | remindMeLater(getReminderTimer()); 413 | break; 414 | case AlertDialog.BUTTON_NEGATIVE: 415 | ignoreThisVersion(); 416 | break; 417 | } 418 | } 419 | } 420 | 421 | class VersionContentRequest extends AsyncTask { 422 | Context context; 423 | int statusCode; 424 | 425 | public VersionContentRequest(Context context) { 426 | this.context = context; 427 | } 428 | 429 | @Override 430 | protected String doInBackground(String... uri) { 431 | DefaultHttpClient client = new DefaultHttpClient(); 432 | String responseBody = null; 433 | HttpResponse httpResponse = null; 434 | ByteArrayOutputStream out = null; 435 | 436 | try { 437 | HttpGet httpget = new HttpGet(uri[0]); 438 | httpResponse = client.execute(httpget); 439 | statusCode = httpResponse.getStatusLine().getStatusCode(); 440 | 441 | if (statusCode == HttpStatus.SC_OK) { 442 | out = new ByteArrayOutputStream(); 443 | httpResponse.getEntity().writeTo(out); 444 | responseBody = out.toString(); 445 | } 446 | 447 | } catch (Exception e) { 448 | Log.e(TAG, e.toString()); 449 | } finally { 450 | if (out != null) { 451 | try { 452 | out.close(); 453 | } catch (IOException e) { 454 | Log.e(TAG, e.toString()); 455 | } 456 | } 457 | } 458 | return responseBody; 459 | } 460 | 461 | @Override 462 | protected void onPostExecute(String result) { 463 | mVersionCode = 0; 464 | String content = null; 465 | if (statusCode != HttpStatus.SC_OK) { 466 | Log.e(TAG, "Response invalid. status code = " + statusCode); 467 | if (mOnReceiveListener != null) { 468 | mOnReceiveListener.onReceive(statusCode, result); 469 | } 470 | } else { 471 | try { 472 | if (!result.startsWith("{")) { // for response who append 473 | // with unknown char 474 | result = result.substring(1); 475 | } 476 | mResult = result; 477 | if (BuildConfig.DEBUG) { 478 | Log.d(TAG, "status = " + statusCode); 479 | Log.d(TAG, "result = " + mResult); 480 | } 481 | 482 | // show default dialog if no listener is set OR return true 483 | if (mOnReceiveListener == null || mOnReceiveListener.onReceive(statusCode, result)) { 484 | // json format from server: 485 | JSONObject json = (JSONObject) new JSONTokener(mResult).nextValue(); 486 | mVersionCode = json.optInt("version_code"); 487 | content = json.optString("content"); 488 | 489 | int currentVersionCode = getCurrentVersionCode(); 490 | if (currentVersionCode < mVersionCode) { 491 | // new versionCode will always higher than 492 | // currentVersionCode 493 | if (mVersionCode != getIgnoreVersionCode()) { 494 | // set dialog message 495 | setMessage(content); 496 | 497 | // show update dialog 498 | showDialog(); 499 | } 500 | } 501 | } 502 | 503 | } catch (JSONException e) { 504 | Log.e(TAG, "is your server response have valid json format?"); 505 | } catch (Exception e) { 506 | Log.e(TAG, e.toString()); 507 | } 508 | } 509 | } 510 | } 511 | 512 | /* 513 | * (non-Javadoc) 514 | * 515 | * @see 516 | * com.winsontan520.wversionmanagertest.IWVersionManager#getCurrentVersionCode 517 | * () 518 | */ 519 | @Override 520 | public int getCurrentVersionCode() { 521 | int currentVersionCode = 0; 522 | PackageInfo pInfo; 523 | try { 524 | pInfo = activity.getPackageManager().getPackageInfo(activity.getPackageName(), 0); 525 | currentVersionCode = pInfo.versionCode; 526 | } catch (NameNotFoundException e) { 527 | // return 0 528 | } 529 | return currentVersionCode; 530 | } 531 | 532 | @Override 533 | public int getIgnoreVersionCode() { 534 | return PreferenceManager.getDefaultSharedPreferences(activity).getInt(PREF_IGNORE_VERSION_CODE, 1); 535 | } 536 | 537 | @Override 538 | public CustomTagHandler getCustomTagHandler() { 539 | return customTagHandler; 540 | } 541 | 542 | /* 543 | * (non-Javadoc) 544 | * 545 | * @see 546 | * com.winsontan520.wversionmanagertest.IWVersionManager#setCustomTagHandler 547 | * (com.winsontan520.wversionmanagertest.WVersionManager.CustomTagHandler) 548 | */ 549 | @Override 550 | public void setCustomTagHandler(CustomTagHandler customTagHandler) { 551 | this.customTagHandler = customTagHandler; 552 | } 553 | 554 | public boolean isDialogCancelable() { 555 | return mDialogCancelable; 556 | } 557 | 558 | public void setDialogCancelable(boolean dialogCancelable) { 559 | mDialogCancelable = dialogCancelable; 560 | } 561 | 562 | public void askForRate() { 563 | mMode = MODE_ASK_FOR_RATE; 564 | showDialog(); 565 | } 566 | 567 | public String getAskForRatePositiveLabel() { 568 | return mAskForRatePositiveLabel == null ? "OK" : mAskForRatePositiveLabel; 569 | } 570 | 571 | public void setAskForRatePositiveLabel(String askForRatePositiveLabel) { 572 | mAskForRatePositiveLabel = askForRatePositiveLabel; 573 | } 574 | 575 | public String getAskForRateNegativeLabel() { 576 | return mAskForRateNegativeLabel == null ? "Not now" : mAskForRateNegativeLabel; 577 | } 578 | 579 | public void setAskForRateNegativeLabel(String askForRateNegativeLabel) { 580 | mAskForRateNegativeLabel = askForRateNegativeLabel; 581 | } 582 | 583 | @Override 584 | public void setOnReceiveListener(OnReceiveListener listener) { 585 | this.mOnReceiveListener = listener; 586 | } 587 | 588 | } 589 | -------------------------------------------------------------------------------- /phone-1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/winsontan520/Android-WVersionManager/a6e90bdb936169a4b0ac63debe2cfb8c7f61ac26/phone-1.png -------------------------------------------------------------------------------- /phone-2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/winsontan520/Android-WVersionManager/a6e90bdb936169a4b0ac63debe2cfb8c7f61ac26/phone-2.png -------------------------------------------------------------------------------- /phone-3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/winsontan520/Android-WVersionManager/a6e90bdb936169a4b0ac63debe2cfb8c7f61ac26/phone-3.png -------------------------------------------------------------------------------- /phone-4.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/winsontan520/Android-WVersionManager/a6e90bdb936169a4b0ac63debe2cfb8c7f61ac26/phone-4.png -------------------------------------------------------------------------------- /sample/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 2 | 6 | 7 | 10 | 11 | 12 | 13 | 18 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 31 | 32 | 35 | 36 | 37 | 38 | -------------------------------------------------------------------------------- /sample/ic_launcher-web.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/winsontan520/Android-WVersionManager/a6e90bdb936169a4b0ac63debe2cfb8c7f61ac26/sample/ic_launcher-web.png -------------------------------------------------------------------------------- /sample/libs/android-support-v4.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/winsontan520/Android-WVersionManager/a6e90bdb936169a4b0ac63debe2cfb8c7f61ac26/sample/libs/android-support-v4.jar -------------------------------------------------------------------------------- /sample/proguard-project.txt: -------------------------------------------------------------------------------- 1 | # To enable ProGuard in your project, edit project.properties 2 | # to define the proguard.config property as described in that file. 3 | # 4 | # Add project specific ProGuard rules here. 5 | # By default, the flags in this file are appended to flags specified 6 | # in ${sdk.dir}/tools/proguard/proguard-android.txt 7 | # You can edit the include path and order by changing the ProGuard 8 | # include property in project.properties. 9 | # 10 | # For more details, see 11 | # http://developer.android.com/guide/developing/tools/proguard.html 12 | 13 | # Add any project specific keep options here: 14 | 15 | # If your project uses WebView with JS, uncomment the following 16 | # and specify the fully qualified class name to the JavaScript interface 17 | # class: 18 | #-keepclassmembers class fqcn.of.javascript.interface.for.webview { 19 | # public *; 20 | #} 21 | -------------------------------------------------------------------------------- /sample/project.properties: -------------------------------------------------------------------------------- 1 | # This file is automatically generated by Android Tools. 2 | # Do not modify this file -- YOUR CHANGES WILL BE ERASED! 3 | # 4 | # This file must be checked in Version Control Systems. 5 | # 6 | # To customize properties used by the Ant build system edit 7 | # "ant.properties", and override values to adapt the script to your 8 | # project structure. 9 | # 10 | # To enable ProGuard to shrink and obfuscate your code, uncomment this (available properties: sdk.dir, user.home): 11 | #proguard.config=${sdk.dir}/tools/proguard/proguard-android.txt:proguard-project.txt 12 | 13 | # Project target. 14 | target=android-14 15 | android.library.reference.1=../library 16 | -------------------------------------------------------------------------------- /sample/res/drawable-hdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/winsontan520/Android-WVersionManager/a6e90bdb936169a4b0ac63debe2cfb8c7f61ac26/sample/res/drawable-hdpi/ic_launcher.png -------------------------------------------------------------------------------- /sample/res/drawable-ldpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/winsontan520/Android-WVersionManager/a6e90bdb936169a4b0ac63debe2cfb8c7f61ac26/sample/res/drawable-ldpi/ic_launcher.png -------------------------------------------------------------------------------- /sample/res/drawable-mdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/winsontan520/Android-WVersionManager/a6e90bdb936169a4b0ac63debe2cfb8c7f61ac26/sample/res/drawable-mdpi/ic_launcher.png -------------------------------------------------------------------------------- /sample/res/drawable-xhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/winsontan520/Android-WVersionManager/a6e90bdb936169a4b0ac63debe2cfb8c7f61ac26/sample/res/drawable-xhdpi/ic_launcher.png -------------------------------------------------------------------------------- /sample/res/layout/ask_for_rate.xml: -------------------------------------------------------------------------------- 1 | 6 | 7 | 12 | 13 |