All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.androidquery.service.MarketService Maven / Gradle / Ivy

Go to download

Android-Query (AQuery) is a light-weight library for doing asynchronous tasks and manipulating UI elements in Android

The newest version!
/*
 * Copyright 2011 - AndroidQuery.com ([email protected])
 * 
 * Licensed under the Apache License, Version 2.0 (the "License"); you may not
 * use this file except in compliance with the License. You may obtain a copy of
 * the License at
 * 
 * http://www.apache.org/licenses/LICENSE-2.0
 * 
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
 * License for the specific language governing permissions and limitations under
 * the License.
 */

package com.androidquery.service;

import java.util.Locale;

import org.json.JSONObject;
import org.xml.sax.XMLReader;

import android.app.Activity;
import android.app.AlertDialog;
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import android.content.pm.ApplicationInfo;
import android.content.pm.PackageInfo;
import android.content.pm.PackageManager.NameNotFoundException;
import android.graphics.drawable.Drawable;
import android.net.Uri;
import android.preference.PreferenceManager;
import android.text.Editable;
import android.text.Html;
import android.text.Html.TagHandler;

import com.androidquery.AQuery;
import com.androidquery.callback.AjaxCallback;
import com.androidquery.callback.AjaxStatus;
import com.androidquery.util.AQUtility;

public class MarketService{

	private Activity act;
	private AQuery aq;
	private Handler handler;
	private String locale;
	private String rateUrl;
	private String updateUrl;
	private boolean force;
	private int progress;
	private long expire = 12 * 60 * 1000;
	
	private String version;
	private boolean fetch;
	private boolean completed;
	private int level = REVISION;
	
	/** Update check level REVISION. */
	public static final int REVISION = 0;
	
	/** Update check level MINOR. */
	public static final int MINOR = 1;
	
	/** Update check level MAJOR. */
	public static final int MAJOR = 2;
	
	/**
	 * Instantiates a new MarketService.
	 *
	 * @param act Current activity.
	 */
	
	public MarketService(Activity act) {
		this.act = act;
		this.aq = new AQuery(act);
		this.handler = new Handler();
		this.locale = Locale.getDefault().toString();
		this.rateUrl = getMarketUrl();
		this.updateUrl = rateUrl;
	}
	
	/**
	 * Set the destination url of the default rate/review button.
	 *
	 * @param url url
	 * @return self
	 */
	public MarketService rateUrl(String url){
		this.rateUrl = url;
		return this;
	}
	
	/**
	 * Set the update check granularity level. Default is REVISION.
	 * 
	 * 
* * Can be REVISION, MINOR, or MAJOR. * *
* * App version format: MAJOR.MINOR.REVISION * *
* * Example: * *
* Current app version: 3.1.2 *
* Newest app version: 3.1.4 *
* Update notice will show if level is REVISION, because the revision code is higher. *
* Update notice will NOT show if level is MINOR, because the minor code is equal (or higher). * * * @param level granularity level * @return self */ public MarketService level(int level){ this.level = level; return this; } /** * Set the destination url of the default update button. * * @param url url * @return self */ public MarketService updateUrl(String url){ this.updateUrl = url; return this; } /** * Force the update dialog to a specific locale. Example: en_US, ja_JP. * * @param locale interface locale * @return self */ public MarketService locale(String locale){ this.locale = locale; return this; } /** * Display a progress view during version check. * * @param id view id * @return self */ public MarketService progress(int id){ this.progress = id; return this; } /** * Force a version check against the AQuery server and show a dialog regardless of versions. * * @param force force an update check * @return self */ public MarketService force(boolean force){ this.force = force; return this; } /** * The time duration which last version check expires. Default is 10 hours. * * @param expire expire time in milliseconds * @return self */ public MarketService expire(long expire){ this.expire = expire; return this; } private static ApplicationInfo ai; private ApplicationInfo getApplicationInfo(){ if(ai == null){ ai = act.getApplicationInfo(); } return ai; } private static PackageInfo pi; private PackageInfo getPackageInfo(){ if(pi == null){ try { pi = act.getPackageManager().getPackageInfo(getAppId(), 0); } catch (NameNotFoundException e) { e.printStackTrace(); } } return pi; } private String getHost(){ return "https://androidquery.appspot.com"; } private String getQueryUrl(){ String appId = getAppId(); String url = getHost() + "/api/market?app=" + appId + "&locale=" + locale + "&version=" + getVersion() + "&code=" + getVersionCode() + "&aq=" + AQuery.VERSION; if(force){ url += "&force=true"; } return url; } private String getAppId(){ return getApplicationInfo().packageName; } private Drawable getAppIcon(){ Drawable d = getApplicationInfo().loadIcon(act.getPackageManager()); return d; } private String getVersion(){ return getPackageInfo().versionName; } private int getVersionCode(){ return getPackageInfo().versionCode; } /** * Perform a version check. * * */ public void checkVersion(){ String url = getQueryUrl(); AjaxCallback cb = new AjaxCallback(); cb.url(url).type(JSONObject.class).handler(handler, "marketCb").fileCache(!force).expire(expire); aq.progress(progress).ajax(cb); } private static boolean openUrl(Activity act, String url) { try{ if(url == null) return false; Uri uri = Uri.parse(url); Intent intent = new Intent(Intent.ACTION_VIEW, uri); act.startActivity(intent); return true; }catch(Exception e){ return false; } } private String getMarketUrl(){ String id = getAppId(); return "market://details?id=" + id; } protected void callback(String url, JSONObject jo, AjaxStatus status){ if(jo == null) return; String latestVer = jo.optString("version", "0"); int latestCode = jo.optInt("code", 0); AQUtility.debug("version", getVersion() + "->" + latestVer + ":" + getVersionCode() + "->" + latestCode); AQUtility.debug("outdated", outdated(latestVer, latestCode)); if(force || outdated(latestVer, latestCode)){ showUpdateDialog(jo); } } private boolean outdated(String latestVer, int latestCode){ String skip = getSkipVersion(act); if(latestVer.equals(skip)){ return false; } String version = getVersion(); int code = getVersionCode(); if(!version.equals(latestVer)){ if(code <= latestCode){ //return true; return requireUpdate(version, latestVer, level); } } return false; } private boolean requireUpdate(String existVer, String latestVer, int level){ if(existVer.equals(latestVer)) return false; try{ String[] evs = existVer.split("\\."); String[] lvs = latestVer.split("\\."); if(evs.length < 3 || lvs.length < 3) return true; switch(level){ case REVISION: if(!evs[evs.length - 1].equals(lvs[lvs.length - 1])){ return true; } case MINOR: if(!evs[evs.length - 2].equals(lvs[lvs.length - 2])){ return true; } case MAJOR: if(!evs[evs.length - 3].equals(lvs[lvs.length - 3])){ return true; } return false; default: return true; } }catch(Exception e){ AQUtility.report(e); return true; } } protected void showUpdateDialog(JSONObject jo){ if(jo == null || version != null) return; if(!isActive()) return; JSONObject dia = jo.optJSONObject("dialog"); String update = dia.optString("update", "Update"); String skip = dia.optString("skip", "Skip"); String rate = dia.optString("rate", "Rate"); //String message = dia.optString("body", ""); String body = dia.optString("wbody", ""); String title = dia.optString("title", "Update Available"); AQUtility.debug("wbody", body); version = jo.optString("version", null); Drawable icon = getAppIcon(); Context context = act; final AlertDialog dialog = new AlertDialog.Builder(context) .setIcon(icon) .setTitle(title) .setPositiveButton(rate, handler) .setNeutralButton(skip, handler) .setNegativeButton(update, handler) .create(); dialog.setMessage(Html.fromHtml(patchBody(body), null, handler)); aq.show(dialog); return; } private static String patchBody(String body){ return "" + body + ""; } private static final String SKIP_VERSION = "aqs.skip"; private static void setSkipVersion(Context context, String version){ PreferenceManager.getDefaultSharedPreferences(context).edit().putString(SKIP_VERSION, version).commit(); } private static String getSkipVersion(Context context){ return PreferenceManager.getDefaultSharedPreferences(context).getString(SKIP_VERSION, null); } private boolean isActive(){ if(act.isFinishing()) return false; return true; } private static final String BULLET = "•"; private class Handler implements DialogInterface.OnClickListener, TagHandler{ @SuppressWarnings("unused") public void marketCb(String url, JSONObject jo, AjaxStatus status){ if(act.isFinishing()) return; if(jo != null){ String s = jo.optString("status"); if("1".equals(s)){ if(jo.has("dialog")){ cb(url, jo, status); } if(!fetch && jo.optBoolean("fetch", false) && status.getSource() == AjaxStatus.NETWORK){ fetch = true; String marketUrl = jo.optString("marketUrl", null); AjaxCallback cb = new AjaxCallback(); cb.url(marketUrl).type(String.class).handler(this, "detailCb"); aq.progress(progress).ajax(cb); } }else if("0".equals(s)){ status.invalidate(); }else{ cb(url, jo, status); } }else{ cb(url, jo, status); } } private void cb(String url, JSONObject jo, AjaxStatus status){ if(!completed){ completed = true; progress = 0; callback(url, jo, status); } } @SuppressWarnings("unused") public void detailCb(String url, String html, AjaxStatus status){ if(html != null && html.length() > 1000){ String qurl = getQueryUrl(); AjaxCallback cb = new AjaxCallback(); cb.url(qurl).type(JSONObject.class).handler(this, "marketCb"); cb.param("html", html); aq.progress(progress).ajax(cb); } } @Override public void onClick(DialogInterface dialog, int which) { switch (which) { case AlertDialog.BUTTON_POSITIVE: openUrl(act, rateUrl); break; case AlertDialog.BUTTON_NEGATIVE: openUrl(act, updateUrl); break; case AlertDialog.BUTTON_NEUTRAL: setSkipVersion(act, version); break; } } @Override public void handleTag(boolean opening, String tag, Editable output, XMLReader xmlReader) { if("li".equals(tag)){ if(opening){ output.append(" "); output.append(BULLET); output.append(" "); }else{ output.append("\n"); } } } } }




© 2015 - 2025 Weber Informatics LLC | Privacy Policy