作者:某一句爱的搁浅- | 来源:互联网 | 2023-10-11 10:36
之前写过类似的博客,参见http:blog.csdn.netluzhenyuxfcyarticledetails43986297,现在这个版本添加些功能并优化代码结构。首先我们理
之前写过类似的博客,参见http://blog.csdn.net/luzhenyuxfcy/article/details/43986297,现在这个版本添加些功能并优化代码结构。
首先我们理一下思路:(参见下图)
思路图
1.新建一个工具类用于交互和一些固定的方法 BaseHelper
package com.lzy.demo;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import org.json.JSONObject;
import android.app.Activity;
import android.app.AlertDialog;
import android.app.ProgressDialog;
import android.content.Context;
import android.content.DialogInterface;
import android.content.DialogInterface.OnCancelListener;
/**
* @author luzhenyu
* @describe
* 工具类
*
*
*/
public class BaseHelper {
/**
* 流转字符串方法
*
* @param is
* @return
*/
public static String convertStreamToString(InputStream is) {
BufferedReader reader = new BufferedReader(new InputStreamReader(is));
StringBuilder sb = new StringBuilder();
String line = null;
try {
while ((line = reader.readLine()) != null) {
sb.append(line);
}
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
is.close();
} catch (IOException e) {
e.printStackTrace();
}
}
return sb.toString();
}
/**
* @describe
* 显示dialog
*
*
*
* @param context
* 环境
* @param strTitle
* 标题
* @param strText
* 内容
* @param icon
* 图标
*/
public static void showDialog(Activity context, String strTitle,
String strText, int icon) {
AlertDialog.Builder tDialog = new AlertDialog.Builder(context);
tDialog.setIcon(icon);
tDialog.setTitle(strTitle);
tDialog.setMessage(strText);
tDialog.setPositiveButton("取消", null);
tDialog.show();
}
/**
* @describe
* 获取权限
*
*
*
* @param permission
* 权限
* @param path
* 路径
*/
public static void chmod(String permission, String path) {
try {
String command = "chmod " + permission + " " + path;
Runtime runtime = Runtime.getRuntime();
runtime.exec(command);
} catch (IOException e) {
e.printStackTrace();
}
}
//
// show the progress bar.
/**
* @describe
* 显示进度条
*
*
*
* @param context
* 环境
* @param title
* 标题
* @param message
* 信息
* @param indeterminate
* 确定性
* @param cancelable
* 可撤销
* @return
*/
public static ProgressDialog showProgress(Context context,
CharSequence title, CharSequence message, boolean indeterminate,
boolean cancelable) {
ProgressDialog dialog = new ProgressDialog(context);
dialog.setTitle(title);
dialog.setMessage(message);
dialog.setIndeterminate(indeterminate);
dialog.setCancelable(false);
dialog.setOnCancelListener(new OnCancelListener() {
@Override
public void onCancel(DialogInterface dialog) {
}
});
dialog.show();
return dialog;
}
/**
* @describe
* 字符串转json对象
*
*
* @param str
* @param split
* @return
*/
public static JSONObject string2JSON(String str, String split) {
JSONObject json = new JSONObject();
try {
String[] arrStr = str.split(split);
for (int i = 0; i String[] arrKeyValue = arrStr[i].split("=");
json.put(arrKeyValue[0],
arrStr[i].substring(arrKeyValue[0].length() + 1));
}
}
catch (Exception e) {
e.printStackTrace();
}
return json;
}
}
2.网络交互类 NetworkManager
package com.lzy.demo;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.HttpURLConnection;
import java.net.InetSocketAddress;
import java.net.Proxy;
import java.net.URL;
import java.util.ArrayList;
import javax.net.ssl.HostnameVerifier;
import javax.net.ssl.HttpsURLConnection;
import javax.net.ssl.SSLSession;
import org.apache.http.client.entity.UrlEncodedFormEntity;
import org.apache.http.message.BasicNameValuePair;
import android.content.Context;
import android.net.ConnectivityManager;
import android.net.NetworkInfo;
/**
* @author luzhenyu
* @describe
* 网络连接工具类
*
*
*/
public class NetworkManager {
static final String TAG = "NetworkManager";
private int cOnnectTimeout= 30 * 1000;
private int readTimeout = 30 * 1000;
Proxy mProxy = null;
Context mContext;
public NetworkManager(Context context) {
this.mCOntext= context;
setDefaultHostnameVerifier();
}
/**
* @describe
* 检查代理,是否cnwap接入
*
*
*/
private void detectProxy() {
ConnectivityManager cm = (ConnectivityManager) mContext
.getSystemService(Context.CONNECTIVITY_SERVICE);
NetworkInfo ni = cm.getActiveNetworkInfo();
if (ni != null && ni.isAvailable()
&& ni.getType() == ConnectivityManager.TYPE_MOBILE) {
@SuppressWarnings("deprecation")
String proxyHost = android.net.Proxy.getDefaultHost();
@SuppressWarnings("deprecation")
int port = android.net.Proxy.getDefaultPort();
if (proxyHost != null) {
final InetSocketAddress sa = new InetSocketAddress(proxyHost,
port);
mProxy = new Proxy(Proxy.Type.HTTP, sa);
}
}
}
private void setDefaultHostnameVerifier() {
HostnameVerifier hv = new HostnameVerifier() {
public boolean verify(String hostname, SSLSession session) {
return true;
}
};
HttpsURLConnection.setDefaultHostnameVerifier(hv);
}
/**
* @describe
* 发送和接收数据
*
*
*
* @param strReqData
* 请求数据
* @param strUrl
* 请求地址
* @return
*/
public String SendAndWaitResponse(String strReqData, String strUrl) {
detectProxy();
String strRespOnse= null;
ArrayList pairs = new ArrayList();
pairs.add(new BasicNameValuePair("requestData", strReqData));
HttpURLConnection httpCOnnect= null;
UrlEncodedFormEntity p_entity;
try {
p_entity = new UrlEncodedFormEntity(pairs, "utf-8");
URL url = new URL(strUrl);
if (mProxy != null) {
httpCOnnect= (HttpURLConnection) url.openConnection(mProxy);
} else {
httpCOnnect= (HttpURLConnection) url.openConnection();
}
httpConnect.setConnectTimeout(connectTimeout);
httpConnect.setReadTimeout(readTimeout);
httpConnect.setDoOutput(true);
httpConnect.addRequestProperty("Content-type",
"application/x-www-form-urlencoded;charset=utf-8");
httpConnect.connect();
OutputStream os = httpConnect.getOutputStream();
p_entity.writeTo(os);
os.flush();
InputStream cOntent= httpConnect.getInputStream();
strRespOnse= BaseHelper.convertStreamToString(content);
} catch (IOException e) {
e.printStackTrace();
} finally {
httpConnect.disconnect();
}
return strResponse;
}
/**
* @describe
* 下载文件
*
*
*
* @param context
* 上下文环境
* @param strurl
* 下载地址
* @param path
* 下载路径
* @return
*/
public boolean urlDownloadToFile(Context context, String strurl, String path) {
boolean bRet = false;
detectProxy();
try {
URL url = new URL(strurl);
HttpURLConnection cOnn= null;
if (mProxy != null) {
cOnn= (HttpURLConnection) url.openConnection(mProxy);
} else {
cOnn= (HttpURLConnection) url.openConnection();
}
conn.setConnectTimeout(connectTimeout);
conn.setReadTimeout(readTimeout);
conn.setDoInput(true);
conn.connect();
InputStream is = conn.getInputStream();
File file = new File(path);
file.createNewFile();
FileOutputStream fos = new FileOutputStream(file);
byte[] temp = new byte[1024];
int i = 0;
while ((i = is.read(temp)) > 0) {
fos.write(temp, 0, i);
}
fos.close();
is.close();
bRet = true;
} catch (IOException e) {
e.printStackTrace();
}
return bRet;
}
}
3.对外调用方法汇合类 里面都设置了public访问权限,可以单独调用也可以使用混合调用,里面有些方法还是挺实用的
package com.lzy.demo;
import java.io.File;
import java.io.FileOutputStream;
import java.io.InputStream;
import java.util.List;
import org.json.JSONException;
import org.json.JSONObject;
import android.annotation.SuppressLint;
import android.app.AlertDialog;
import android.app.ProgressDialog;
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
import android.net.Uri;
import android.os.Handler;
import android.os.Message;
/**
* @author luzhenyu
* @version 1.0
* @describe
* 检测工具类
*
*
* */
public class DetectHelper {
@SuppressWarnings("unused")
private static final String TAG = "DetectHelper";
private ProgressDialog mProgress = null;
private Context mCOntext= null;
public DetectHelper() {
}
public DetectHelper(Context mContext) {
this.mCOntext= mContext;
}
/**
* @describe
* 检测手机是否安装,如果没有则先从assets文件下安装/网络上下载安装,并检测是否需要更新,汇总调用方法
*
*
* */
public void detectMobile() {
if (detectIsInstall(Constant.PACKAGENAME_STRING)) {// "com.lzy.appdemo"
// 采用文件或者一个静态类来管理
// 根据需要进行处理
startApplicationByPackageName(Constant.PACKAGENAME_STRING);
} else {
inStallAppFromAssets(Constant.APKNAME_STRING);
// 检测版本更新
// 对话框
mProgress = BaseHelper
.showProgress(mContext, null, "正在检测更新", false, true);
// 子线程进行检查更新耗时操作
new Thread(new Runnable() {
@Override
public void run() {
checkUpdate();
}
}).start();
}
}
public void checkUpdate() {
// 获取系统缓存目录
File cacheDir = mContext.getCacheDir();
final String cachePath = cacheDir.getAbsolutePath() + "/temp.apk";
// 检测是否有新的版本。
PackageInfo apkInfo = getApkInfo(mContext, cachePath);
String newApkdlUrl = checkNewUpdate(apkInfo);
//
// 动态下载
if (newApkdlUrl != null)
retrieveApkFromNet(mContext, newApkdlUrl, cachePath);
// 发送结果
Message msg = new Message();
msg.what = Constant.INSTALL_CHECK;
msg.obj = cachePath;
mHandler.sendMessage(msg);
}
/**
* @describe
* 从assets目录捆绑安装APP
*
*
* @param apkName
* - String
* @return true if assets file exist you need apk,or false
* */
public boolean inStallAppFromAssets(String apkName) {
boolean exist = false;
// 获取系统缓存目录
File cacheDir = mContext.getCacheDir();
final String cachePath = cacheDir.getAbsolutePath() + "/temp.apk";
try {
InputStream inputStream = mContext.getAssets().open(apkName);
File file = new File(cachePath);
file.createNewFile();
FileOutputStream fileOutputStream = new FileOutputStream(file);
byte[] temp = new byte[1024];
int i = 0;
while ((i = inputStream.read(temp)) > 0) {
fileOutputStream.write(temp, 0, i);
}
fileOutputStream.close();
inputStream.close();
exist = true;
} catch (Exception e) {
exist = false;
}
return exist;
}
/**
* @describe
* 根据报名启动应用程序
*
*
* @param packageName
* - String
* */
public void startApplicationByPackageName(String packageName) {
PackageManager packageManager = mContext.getPackageManager();
Intent intent = packageManager.getLaunchIntentForPackage(packageName);
mContext.startActivity(intent);
}
/**
* @describe
* 检测手机是否安装xxxxAPP
*
*
* @param packageName
* - String
* @return ture if install,or false
* */
public boolean detectIsInstall(String packageName) {
boolean isInstall = false;
PackageManager mPackageManager = mContext.getPackageManager();
List packageInfos = mPackageManager
.getInstalledPackages(0);
for (int i = 0, len = packageInfos.size(); i PackageInfo info = packageInfos.get(i);
if (info.packageName.equalsIgnoreCase(packageName)) {
isInstall = true;
} else {
isInstall = false;
}
}
return isInstall;
}
/**
* @describe 获取未安装的APK信息
* @param context
* @param archiveFilePath
* APK文件的路径。如:/sdcard/download/XX.apk
*/
public static PackageInfo getApkInfo(Context context, String archiveFilePath) {
PackageManager pm = context.getPackageManager();
PackageInfo apkInfo = pm.getPackageArchiveInfo(archiveFilePath,
PackageManager.GET_META_DATA);
return apkInfo;
}
/**
* @describe 检查是否有新版本,如果有,返回apk下载地址
* @param packageInfo
* {@link PackageInfo}
* @return
*/
public String checkNewUpdate(PackageInfo packageInfo) {
String url = null;
try {
JSONObject resp = sendCheckNewUpdate(packageInfo.versionName);
if (resp.getString("needUpdate").equalsIgnoreCase("true")) {
url = resp.getString("updateUrl");
}
} catch (Exception e) {
e.printStackTrace();
}
return url;
}
/**
* @describe 发送当前版本信息,返回是否需要升级 如果需要升级返回更新apk地址
* @param versionName
* 当前版本号
* @return
*/
public JSONObject sendCheckNewUpdate(String versionName) {
JSONObject objResp = null;
try {
JSONObject req = new JSONObject();
req.put(Constant.ACTION, Constant.ACTIONUPDATE);
JSONObject data = new JSONObject();
data.put(Constant.PLATFORM, "android");
data.put(Constant.VERSION, versionName);
data.put(Constant.PARTENER, "");
req.put(Constant.DATA, data);
objResp = sendRequest(req.toString());
} catch (JSONException e) {
e.printStackTrace();
}
return objResp;
}
/**
* @describe 发送json数据
* @param content
* @return
*/
public JSONObject sendRequest(final String content) {
NetworkManager nM = new NetworkManager(this.mContext);
JSONObject jsOnResponse= null;
try {
String respOnse= null;
synchronized (nM) {
respOnse= nM.SendAndWaitResponse(content, Constant.SERVER_STRING);
}
jsOnResponse= new JSONObject(response);
} catch (Exception e) {
e.printStackTrace();
}
return jsonResponse;
}
/**
* @describe 从网络上动态下载apk
* @param context
* 上下文环境
* @param strurl
* 下载地址
* @param filename
* 文件名称
* @return
*/
public boolean retrieveApkFromNet(Context context, String strurl,
String filename) {
boolean bRet = false;
try {
NetworkManager nM = new NetworkManager(this.mContext);
bRet = nM.urlDownloadToFile(context, strurl, filename);
} catch (Exception e) {
e.printStackTrace();
}
return bRet;
}
//
// close the progress bar
public void closeProgress() {
try {
if (mProgress != null) {
mProgress.dismiss();
mProgress = null;
}
} catch (Exception e) {
e.printStackTrace();
}
}
@SuppressLint("HandlerLeak")
private Handler mHandler = new Handler() {
public void handleMessage(Message msg) {
try {
switch (msg.what) {
case Constant.INSTALL_CHECK: {
closeProgress();
String cachePath = (String) msg.obj;
showInstallConfirmDialog(mContext, cachePath);
}
break;
}
super.handleMessage(msg);
} catch (Exception e) {
e.printStackTrace();
}
}
};
/**
* @describe 显示确认安装的提示
* @param context
* 上下文环境
* @param cachePath
* 安装文件路径
*/
public void showInstallConfirmDialog(final Context context,
final String cachePath) {
AlertDialog.Builder tDialog = new AlertDialog.Builder(context);
tDialog.setIcon(R.drawable.ic_launcher);
tDialog.setTitle("安装提示");
tDialog.setMessage("您还没有安装XXXX。\n\n点击确定,立即安装。");
tDialog.setPositiveButton("确定",
new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int which) {
//
// 修改apk权限
BaseHelper.chmod("777", cachePath);
//
// install the apk.
Intent intent = new Intent(Intent.ACTION_VIEW);
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
intent.setDataAndType(Uri.parse("file://" + cachePath),
"application/vnd.android.package-archive");
context.startActivity(intent);
}
});
tDialog.setNegativeButton("取消",
new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int which) {
}
});
tDialog.show();
}
}
4.为了便于管理一些常用的静态字段和上传服务器参数字段,采用一个静态类Constant 实现,对于以后的更新维护更方便。
package com.lzy.demo;
/**
* @author luzhenyu
* @describe 静态字段
* */
public class Constant
{
public final static int INSTALL_CHECK = 0x123;
//参数根据实际开发的需求定义和传递,这里采用的是阿里巴巴的
public final static String ACTION = "action";
public final static String ACTIOnUPDATE= "update";
public final static String DATA = "data";
public final static String PLATFORM = "platform";
public final static String VERSION = "version";
public final static String PARTENER = "partner";
public final static String APKNAME_STRING = "TransActionBarDemo.apk";//assets文件夹下apk名称
public final static String PACKAGENAME_STRING = "com.lzy.appdemo";//要安装的APP的包名
public final static String SERVER_STRING = "https://msp.alipay.com/x.htm";//获取更新服务器地址
}
5.最后别忘了在AndroidManifest.xml中添加权限
至此整个可以复用的功能完成了,当然,在具体的开发中可能会有不同,比如网络访问这块可能采用的第三方框架,基本思路就是这样,在开发中改动一下接口的访问方式和参数就可以转化为你的功能,这里使用的是阿里巴巴的接口,非常感谢阿里巴巴。
看到了一篇采用Xml方式更新的博客,在此也贴出飞机票:http://blog.csdn.net/furongkang/article/details/6886526
再次说明,实际开发中请根据需要,改动这几个文件的某些实现方法。
方便大家也是方便自己,分享让世界更美好。— — love hy.
【欢迎上码】
【微信公众号搜索 h2o2s2】