516 lines
14 KiB
Plaintext
516 lines
14 KiB
Plaintext
|
package com.novelbook.android.upgrade;
|
|||
|
|
|||
|
import java.io.ByteArrayInputStream;
|
|||
|
import java.io.File;
|
|||
|
import java.io.FileOutputStream;
|
|||
|
import java.io.IOException;
|
|||
|
import java.io.InputStream;
|
|||
|
import java.net.HttpURLConnection;
|
|||
|
import java.net.MalformedURLException;
|
|||
|
import java.net.URL;
|
|||
|
import java.util.HashMap;
|
|||
|
|
|||
|
|
|||
|
import android.Manifest;
|
|||
|
import android.app.Activity;
|
|||
|
import android.app.AlertDialog;
|
|||
|
import android.app.AlertDialog.Builder;
|
|||
|
import android.app.Dialog;
|
|||
|
import android.content.Context;
|
|||
|
import android.content.DialogInterface;
|
|||
|
import android.content.DialogInterface.OnClickListener;
|
|||
|
import android.content.Intent;
|
|||
|
import android.content.pm.PackageManager.NameNotFoundException;
|
|||
|
import android.net.Uri;
|
|||
|
import android.os.Build;
|
|||
|
import android.os.Environment;
|
|||
|
import android.os.Handler;
|
|||
|
import android.os.Message;
|
|||
|
import android.support.v4.content.FileProvider;
|
|||
|
import android.text.TextUtils;
|
|||
|
import android.util.Log;
|
|||
|
import android.view.LayoutInflater;
|
|||
|
import android.view.View;
|
|||
|
import android.widget.ProgressBar;
|
|||
|
import android.widget.Toast;
|
|||
|
|
|||
|
import com.novelbook.android.Activity_base;
|
|||
|
import com.novelbook.android.BookActivity;
|
|||
|
import com.novelbook.android.BuildConfig;
|
|||
|
import com.novelbook.android.MyApp;
|
|||
|
import com.novelbook.android.R;
|
|||
|
import com.novelbook.android.ReadActivity;
|
|||
|
import com.novelbook.android.db.Novel;
|
|||
|
import com.novelbook.android.netsubscribe.BookSubscribe;
|
|||
|
import com.novelbook.android.netutils.HttpMethods;
|
|||
|
import com.novelbook.android.netutils.OnSuccessAndFaultListener;
|
|||
|
import com.novelbook.android.netutils.OnSuccessAndFaultSub;
|
|||
|
import com.novelbook.android.utils.CommonUtil;
|
|||
|
import com.novelbook.android.utils.Constants;
|
|||
|
import com.novelbook.android.utils.GsonUtil;
|
|||
|
|
|||
|
import okhttp3.Call;
|
|||
|
import okhttp3.Callback;
|
|||
|
import okhttp3.Request;
|
|||
|
import okhttp3.Response;
|
|||
|
import okhttp3.ResponseBody;
|
|||
|
|
|||
|
import static com.novelbook.android.FileActivity.EXTERNAL_STORAGE_REQ_CODE;
|
|||
|
import static com.novelbook.android.netapi.URLConstant.getRootUrl;
|
|||
|
import static java.lang.System.exit;
|
|||
|
|
|||
|
|
|||
|
public class UpdateManager {
|
|||
|
|
|||
|
public static final String TAG =UpdateManager.class.getSimpleName();
|
|||
|
|
|||
|
private static final int DOWNLOAD = 1;
|
|||
|
private static final int DOWNLOAD_FINISH = 2;
|
|||
|
private static final int showDialog =3;
|
|||
|
HashMap<String, String> mHashMap;
|
|||
|
HashMap<String, HashMap<String,String>> multiHashMap;
|
|||
|
private String mSavePath;
|
|||
|
private int progress;
|
|||
|
private boolean cancelUpdate = false;
|
|||
|
private Activity_base mContext;
|
|||
|
private ProgressBar mProgress;
|
|||
|
private Dialog mDownloadDialog;
|
|||
|
private boolean isForceRefresh;
|
|||
|
int serviceCode;
|
|||
|
private Handler mHandler = new Handler()
|
|||
|
{
|
|||
|
@Override
|
|||
|
public void handleMessage(Message msg)
|
|||
|
{
|
|||
|
switch (msg.what)
|
|||
|
{
|
|||
|
case DOWNLOAD:
|
|||
|
mProgress.setProgress(progress);
|
|||
|
break;
|
|||
|
case DOWNLOAD_FINISH:
|
|||
|
installApk();
|
|||
|
break;
|
|||
|
case showDialog:
|
|||
|
showNoticeDialog();
|
|||
|
break;
|
|||
|
default:
|
|||
|
break;
|
|||
|
}
|
|||
|
};
|
|||
|
};
|
|||
|
|
|||
|
public UpdateManager(Activity_base context)
|
|||
|
{
|
|||
|
this.mContext = context;
|
|||
|
// app =(QiYouApplication)context;
|
|||
|
}
|
|||
|
|
|||
|
/**
|
|||
|
* 濡拷绁存潪顖欐閺囧瓨鏌<E793A8>
|
|||
|
*/
|
|||
|
public void checkUpdate()
|
|||
|
{
|
|||
|
String urlStr = getRootUrl()+ Constants.VERSION_ADDRESS;
|
|||
|
urlStr = Constants.updateUrl;//"http://xiaoshuofenxiang.com/version.xml";
|
|||
|
if(!TextUtils.isEmpty(urlStr))
|
|||
|
checkUpdate(urlStr);
|
|||
|
/*if (isUpdate())
|
|||
|
{
|
|||
|
showNoticeDialog();
|
|||
|
} else
|
|||
|
{
|
|||
|
Toast.makeText(mContext, R.string.soft_update_no, Toast.LENGTH_LONG).show();
|
|||
|
}*/
|
|||
|
}
|
|||
|
boolean isSilence =false;
|
|||
|
public void checkUpdateSilence()
|
|||
|
{
|
|||
|
isSilence=true;
|
|||
|
checkUpdate();
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
|
|||
|
|
|||
|
|
|||
|
|
|||
|
|
|||
|
void checkUpdate(String url){
|
|||
|
Request request = new Request.Builder()
|
|||
|
.url(url).build();
|
|||
|
|
|||
|
|
|||
|
HttpMethods.getOkClient().newCall(request).enqueue(new Callback() {
|
|||
|
@Override
|
|||
|
public void onFailure(Call call, IOException e) {
|
|||
|
Log.d(TAG, " 版本检查错误 onFailure(int, Header[],byte[], Throwable ) was received");
|
|||
|
if(!isSilence)
|
|||
|
Toast.makeText(mContext, "版本检查出错了", Toast.LENGTH_LONG).show();
|
|||
|
}
|
|||
|
|
|||
|
@Override
|
|||
|
public void onResponse(Call call, Response response) throws IOException {
|
|||
|
if(response.code()!=200) {
|
|||
|
Log.e(TAG, "check update onResponse:return code" +response.code() );
|
|||
|
}
|
|||
|
ResponseBody body = response.body();
|
|||
|
|
|||
|
|
|||
|
try {
|
|||
|
byte[] bytes = body.bytes();
|
|||
|
// String s = body.string();
|
|||
|
// Log.d(TAG, "onSuccess: response is " + s);
|
|||
|
if (bytes != null) {
|
|||
|
// processTxtOnSuccess(bytes);
|
|||
|
processMultiTxtOnSuccess(bytes);
|
|||
|
}
|
|||
|
// body.close();
|
|||
|
}catch (Exception e){
|
|||
|
Log.e(TAG, "onResponse: ",e );
|
|||
|
}finally {
|
|||
|
|
|||
|
}
|
|||
|
}
|
|||
|
});
|
|||
|
|
|||
|
|
|||
|
|
|||
|
|
|||
|
|
|||
|
|
|||
|
|
|||
|
}
|
|||
|
void processMultiTxtOnSuccess(byte[] paramArrayOfByte) {
|
|||
|
|
|||
|
boolean isUpdate=false;
|
|||
|
int versionCode = getVersionCode(mContext);
|
|||
|
InputStream inputStream = null;
|
|||
|
inputStream =new ByteArrayInputStream(paramArrayOfByte);
|
|||
|
ParseXmlService service = new ParseXmlService();
|
|||
|
try
|
|||
|
{
|
|||
|
if(inputStream!=null)
|
|||
|
multiHashMap = service.parseMultiXml(inputStream);
|
|||
|
|
|||
|
} catch (Exception e)
|
|||
|
{
|
|||
|
e.printStackTrace();
|
|||
|
}
|
|||
|
if (null != multiHashMap) {
|
|||
|
String packgename = mContext.getPackageName();
|
|||
|
mHashMap = multiHashMap.get(packgename);
|
|||
|
if (mHashMap != null) {
|
|||
|
serviceCode = Integer.valueOf(mHashMap.get("version"));
|
|||
|
Constants.serverVersion = serviceCode;
|
|||
|
if(mHashMap.containsKey("minVersion"))
|
|||
|
Constants.minVersion = Integer.valueOf(mHashMap.get("minVersion"));
|
|||
|
// need update or not
|
|||
|
isUpdate = serviceCode > versionCode;
|
|||
|
isForceRefresh = versionCode <Constants.minVersion;
|
|||
|
|
|||
|
Log.d(TAG, String.format("processMultiTxtOnSuccess : isUpdate %s, serviceCode %s,minVersion %s,versionCode %s,isForceRefresh %s"
|
|||
|
,isUpdate,serviceCode,Constants.minVersion,Constants.version,isForceRefresh));
|
|||
|
|
|||
|
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
if (isUpdate )
|
|||
|
{
|
|||
|
mHandler.sendEmptyMessage(showDialog);
|
|||
|
|
|||
|
} else
|
|||
|
{
|
|||
|
if(!isSilence)
|
|||
|
Toast.makeText(mContext, R.string.soft_update_no, Toast.LENGTH_LONG).show();
|
|||
|
}
|
|||
|
|
|||
|
}
|
|||
|
void processTxtOnSuccess(byte[] paramArrayOfByte) {
|
|||
|
|
|||
|
boolean isUpdate=false;
|
|||
|
int versionCode = getVersionCode(mContext);
|
|||
|
InputStream inputStream = null;
|
|||
|
inputStream =new ByteArrayInputStream(paramArrayOfByte);
|
|||
|
ParseXmlService service = new ParseXmlService();
|
|||
|
try
|
|||
|
{
|
|||
|
|
|||
|
if(inputStream!=null)
|
|||
|
mHashMap = service.parseXml(inputStream);
|
|||
|
|
|||
|
} catch (Exception e)
|
|||
|
{
|
|||
|
e.printStackTrace();
|
|||
|
}
|
|||
|
if (null != mHashMap)
|
|||
|
{
|
|||
|
int serviceCode = Integer.valueOf(mHashMap.get("version"));
|
|||
|
// need update or not
|
|||
|
isUpdate =serviceCode > versionCode;
|
|||
|
}
|
|||
|
|
|||
|
if (isUpdate)
|
|||
|
{
|
|||
|
mHandler.sendEmptyMessage(showDialog);
|
|||
|
|
|||
|
} else
|
|||
|
{
|
|||
|
if(!isSilence)
|
|||
|
Toast.makeText(mContext, R.string.soft_update_no, Toast.LENGTH_LONG).show();
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
|
|||
|
|
|||
|
/**
|
|||
|
* 閼惧嘲褰囨潪顖欐閻楀牊婀伴崣锟<E5B4A3> *
|
|||
|
* @param context
|
|||
|
* @return
|
|||
|
*/
|
|||
|
public int getVersionCode(Context context)
|
|||
|
{
|
|||
|
|
|||
|
int versionCode = 0;
|
|||
|
try
|
|||
|
{
|
|||
|
// 閼惧嘲褰囨潪顖欐閻楀牊婀伴崣鍑ょ礉鐎电懓绨睞ndroidManifest.xml娑撳獘ndroid:versionCode
|
|||
|
versionCode =(int)CommonUtil.getVersionCodeLong(context);// context.getPackageManager().getPackageInfo("com.novelbook.android", 0).versionCode;
|
|||
|
|
|||
|
/*int versionCode2 = CommonUtil.getVersionCode(context);
|
|||
|
long versioncode3 = CommonUtil.getVersionCodeLong(context);
|
|||
|
|
|||
|
String versionname = CommonUtil.getVersion(context);
|
|||
|
String v = CommonUtil.getVersionName(context);
|
|||
|
String packnm = context.getPackageName();
|
|||
|
String p ="A";*/
|
|||
|
} catch ( Exception e)
|
|||
|
{
|
|||
|
|
|||
|
Log.e(TAG, "getVersionCode: ",e);
|
|||
|
}
|
|||
|
return versionCode;
|
|||
|
}
|
|||
|
|
|||
|
/**
|
|||
|
* 閼惧嘲褰囨潪顖欐閻楀牊婀伴崣锟<E5B4A3> *
|
|||
|
* @param context
|
|||
|
* @return
|
|||
|
*/
|
|||
|
public static String getVersionName(Context context)
|
|||
|
{
|
|||
|
String versionName = "";
|
|||
|
try
|
|||
|
{
|
|||
|
// 閼惧嘲褰囨潪顖欐閻楀牊婀伴崣鍑ょ礉鐎电懓绨睞ndroidManifest.xml娑撳獘ndroid:versionCode
|
|||
|
versionName = context.getPackageManager().getPackageInfo("com.qiyou.mb.android", 0).versionName;
|
|||
|
} catch (NameNotFoundException e)
|
|||
|
{
|
|||
|
Log.e(TAG, "getVersionCode: ",e);
|
|||
|
}
|
|||
|
return versionName;
|
|||
|
}
|
|||
|
|
|||
|
/**
|
|||
|
* 閺勫墽銇氭潪顖欐閺囧瓨鏌婄<E98F8C>纭呯樈濡楋拷
|
|||
|
*/
|
|||
|
private void showNoticeDialog()
|
|||
|
{
|
|||
|
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
|
|||
|
CommonUtil.checkPermission(mContext, Manifest.permission.WRITE_EXTERNAL_STORAGE, EXTERNAL_STORAGE_REQ_CODE, "下载更新需要此权限,请允许");
|
|||
|
CommonUtil.checkPermission(mContext, Manifest.permission.INSTALL_PACKAGES, 1024, "下载更新需要此权限,请允许");
|
|||
|
}
|
|||
|
|
|||
|
// 閺嬪嫰锟界<E9949F>纭呯樈濡楋拷
|
|||
|
Builder builder = new Builder(mContext);
|
|||
|
|
|||
|
if(isForceRefresh) {
|
|||
|
builder.setTitle(R.string.soft_force_update_title);
|
|||
|
}else {
|
|||
|
builder.setTitle(R.string.soft_update_title);
|
|||
|
}
|
|||
|
String upgradeDetails=mHashMap.get("details");
|
|||
|
String forceRefresh =isForceRefresh? "本地版本过低,请升级新版本":"";
|
|||
|
builder.setMessage( forceRefresh +/*mContext.getPackageName() +*/ "\n当前版本:"+getVersionCode(mContext) +"\n"
|
|||
|
+"最新版本:"+ serviceCode +"\n"
|
|||
|
+ mContext.getString(R.string.soft_update_info) + upgradeDetails );
|
|||
|
builder.setPositiveButton(R.string.soft_update_updatebtn, new OnClickListener()
|
|||
|
{
|
|||
|
@Override
|
|||
|
public void onClick(DialogInterface dialog, int which)
|
|||
|
{
|
|||
|
dialog.dismiss();
|
|||
|
showDownloadDialog();
|
|||
|
}
|
|||
|
});
|
|||
|
// 缁嬪秴鎮楅弴瀛樻煀
|
|||
|
builder.setNegativeButton(R.string.soft_update_later, new OnClickListener()
|
|||
|
{
|
|||
|
@Override
|
|||
|
public void onClick(DialogInterface dialog, int which)
|
|||
|
{
|
|||
|
dialog.dismiss();
|
|||
|
if(isForceRefresh){
|
|||
|
exit(-1);
|
|||
|
}
|
|||
|
}
|
|||
|
});
|
|||
|
Dialog noticeDialog = builder.create();
|
|||
|
noticeDialog.setCancelable(false);
|
|||
|
noticeDialog.show();
|
|||
|
|
|||
|
|
|||
|
}
|
|||
|
|
|||
|
/**
|
|||
|
* 閺勫墽銇氭潪顖欐娑撳娴囩<E5A8B4>纭呯樈濡楋拷
|
|||
|
*/
|
|||
|
private void showDownloadDialog()
|
|||
|
{
|
|||
|
// 閺嬪嫰锟芥潪顖欐娑撳娴囩<E5A8B4>纭呯樈濡楋拷
|
|||
|
Builder builder = new Builder(mContext);
|
|||
|
builder.setTitle(R.string.soft_updating);
|
|||
|
// 缂佹瑤绗呮潪钘夘嚠鐠囨繃顢嬫晶鐐插鏉╂稑瀹抽弶锟<E5BCB6>
|
|||
|
final LayoutInflater inflater = LayoutInflater.from(mContext);
|
|||
|
View v = inflater.inflate(R.layout.softupgrade_progress, null);
|
|||
|
mProgress = (ProgressBar) v.findViewById(R.id.update_progress);
|
|||
|
builder.setView(v);
|
|||
|
// 閸欐牗绉烽弴瀛樻煀
|
|||
|
builder.setNegativeButton(R.string.soft_update_cancel, new OnClickListener()
|
|||
|
{
|
|||
|
@Override
|
|||
|
public void onClick(DialogInterface dialog, int which)
|
|||
|
{
|
|||
|
dialog.dismiss();
|
|||
|
// 鐠佸墽鐤嗛崣鏍ㄧХ閻樿埖锟<E59F96>
|
|||
|
cancelUpdate = true;
|
|||
|
if(isForceRefresh){
|
|||
|
exit(-1);
|
|||
|
}
|
|||
|
}
|
|||
|
});
|
|||
|
mDownloadDialog = builder.create();
|
|||
|
mDownloadDialog.setCancelable(true);
|
|||
|
mDownloadDialog.show();
|
|||
|
// 閻滄澘婀弬鍥︽
|
|||
|
downloadApk();
|
|||
|
}
|
|||
|
|
|||
|
/**
|
|||
|
* 娑撳娴嘺pk閺傚洣娆<E6B4A3>
|
|||
|
*/
|
|||
|
private void downloadApk()
|
|||
|
{
|
|||
|
|
|||
|
// 閸氼垰濮╅弬鎵殠缁嬪绗呮潪鍊熻拫娴狅拷
|
|||
|
new downloadApkThread().start();
|
|||
|
}
|
|||
|
|
|||
|
/**
|
|||
|
* 娑撳娴囬弬鍥︽缁捐法鈻<E6B395>
|
|||
|
*/
|
|||
|
private class downloadApkThread extends Thread
|
|||
|
{
|
|||
|
@Override
|
|||
|
public void run()
|
|||
|
{
|
|||
|
try
|
|||
|
{
|
|||
|
// 閸掋倖鏌嘢D閸椻剝妲搁崥锕<E5B4A5>摠閸︻煉绱濋獮鏈电瑬閺勵垰鎯侀崗閿嬫箒鐠囪鍟撻弶鍐
|
|||
|
if (Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED))
|
|||
|
{
|
|||
|
// 閼惧嘲绶辩<E7BBB6>妯哄亶閸楋紕娈戠捄顖氱窞
|
|||
|
String sdpath = Environment.getExternalStorageDirectory() + "/" +"GDTDOWNLOAD/";
|
|||
|
mSavePath = sdpath + "download";
|
|||
|
URL url = new URL(mHashMap.get("url"));
|
|||
|
// 閸掓稑缂撴潻鐐村复
|
|||
|
HttpURLConnection conn = (HttpURLConnection) url.openConnection();
|
|||
|
conn.connect();
|
|||
|
// 閼惧嘲褰囬弬鍥︽婢堆冪毈
|
|||
|
int length = conn.getContentLength();
|
|||
|
// 閸掓稑缂撴潏鎾冲弳濞达拷
|
|||
|
InputStream is = conn.getInputStream();
|
|||
|
|
|||
|
File file = new File(mSavePath);
|
|||
|
// 閸掋倖鏌囬弬鍥︽閻╊喖缍嶉弰顖氭儊鐎涙ê婀<C3AA>
|
|||
|
if (!file.exists())
|
|||
|
{
|
|||
|
file.mkdir();
|
|||
|
}
|
|||
|
File apkFile = new File(mSavePath, mHashMap.get("name"));
|
|||
|
FileOutputStream fos = new FileOutputStream(apkFile);
|
|||
|
int count = 0;
|
|||
|
// 缂傛挸鐡<E68CB8>
|
|||
|
byte buf[] = new byte[1024];
|
|||
|
// 閸愭瑥鍙嗛崚鐗堟瀮娴犳湹鑵<E6B9B9>
|
|||
|
do
|
|||
|
{
|
|||
|
int numread = is.read(buf);
|
|||
|
count += numread;
|
|||
|
// 鐠侊紕鐣绘潻娑樺閺夆<E996BA>缍呯純锟<E7B494>
|
|||
|
progress = (int) (((float) count / length) * 100);
|
|||
|
// 閺囧瓨鏌婃潻娑樺
|
|||
|
mHandler.sendEmptyMessage(DOWNLOAD);
|
|||
|
if (numread <= 0)
|
|||
|
{
|
|||
|
// 娑撳娴囩<E5A8B4>灞惧灇
|
|||
|
mHandler.sendEmptyMessage(DOWNLOAD_FINISH);
|
|||
|
break;
|
|||
|
}
|
|||
|
// 閸愭瑥鍙嗛弬鍥︽
|
|||
|
fos.write(buf, 0, numread);
|
|||
|
} while (!cancelUpdate);// 閻愮懓鍤崣鏍ㄧХ鐏忓崬浠犲顤嶇瑓鏉烇拷
|
|||
|
fos.close();
|
|||
|
is.close();
|
|||
|
}
|
|||
|
} catch (MalformedURLException e)
|
|||
|
{
|
|||
|
if(isForceRefresh){
|
|||
|
exit(-1);
|
|||
|
}
|
|||
|
Log.e(TAG, "run: ", e);
|
|||
|
} catch (IOException e)
|
|||
|
{
|
|||
|
mContext.checkAndRequestPermission();
|
|||
|
if(isForceRefresh){
|
|||
|
// exit(-1);
|
|||
|
}
|
|||
|
Log.e(TAG, "run: ", e);
|
|||
|
}
|
|||
|
// 閸欐牗绉锋稉瀣祰鐎电鐦藉鍡樻▔缁<E29694>拷
|
|||
|
mDownloadDialog.dismiss();
|
|||
|
}
|
|||
|
};
|
|||
|
|
|||
|
/**
|
|||
|
* 鐎瑰顥朅PK閺傚洣娆<E6B4A3>
|
|||
|
*/
|
|||
|
private void installApk()
|
|||
|
{
|
|||
|
File apkfile = new File(mSavePath, mHashMap.get("name"));
|
|||
|
if (!apkfile.exists())
|
|||
|
{
|
|||
|
return;
|
|||
|
}
|
|||
|
// 闁俺绻僆ntent鐎瑰顥朅PK閺傚洣娆<E6B4A3>
|
|||
|
Intent i = new Intent(Intent.ACTION_VIEW);
|
|||
|
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.N) {
|
|||
|
i.setDataAndType(Uri.parse("file://" + apkfile.toString()), "application/vnd.android.package-archive");
|
|||
|
i.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
|
|||
|
} else {
|
|||
|
// 声明需要的临时权限
|
|||
|
// 第二个参数,即第一步中配置的authorities
|
|||
|
Uri contentUri = FileProvider.getUriForFile(MyApp.applicationContext, BuildConfig.APPLICATION_ID + ".fileprovider", apkfile);
|
|||
|
i.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
|
|||
|
i.setDataAndType(contentUri, "application/vnd.android.package-archive");
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
mContext.startActivity(i);
|
|||
|
exit(-1);
|
|||
|
}
|
|||
|
}
|