android应用版本更新功能---完整版
源码下载地址:csdn下载地址:http://download.csdn.net/download/csdn576038874/9526085
博客园下载地址:http://files.cnblogs.com/files/wenjie123/updateversion.rar
1、检测是否有新版本
public class MainActivity extends Activity {private Button button;@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);button = (Button) findViewById(R.id.button1);button.setOnClickListener(new OnClickListener() {@Overridepublic void onClick(View v) {//本地测试检测是否有新版本发布UpdateVersionUtil.localCheckedVersion(MainActivity.this,new UpdateListener() {@Overridepublic void onUpdateReturned(int updateStatus, VersionInfo versionInfo) {//判断回调过来的版本检测状态switch (updateStatus) {case UpdateStatus.YES://弹出更新提示UpdateVersionUtil.showDialog(MainActivity.this,versionInfo);break;case UpdateStatus.NO://没有新版本ToastUtils.showToast(getApplicationContext(), "已经是最新版本了!");break;case UpdateStatus.NOWIFI://当前是非wifi网络ToastUtils.showToast(getApplicationContext(), "只有在wifi下更新!"); // DialogUtils.showDialog(MainActivity.this, "温馨提示","当前非wifi网络,下载会消耗手机流量!", "确定", "取消",new DialogOnClickListenner() { // @Override // public void btnConfirmClick(Dialog dialog) { // dialog.dismiss(); // //点击确定之后弹出更新对话框 // UpdateVersionUtil.showDialog(SystemActivity.this,versionInfo); // } // // @Override // public void btnCancelClick(Dialog dialog) { // dialog.dismiss(); // } // });break;case UpdateStatus.ERROR://检测失败ToastUtils.showToast(getApplicationContext(), "检测失败,请稍后重试!");break;case UpdateStatus.TIMEOUT://链接超时ToastUtils.showToast(getApplicationContext(), "链接超时,请检查网络设置!");break;}}});/*** //访问服务器 试检测是否有新版本发布UpdateVersionUtil.localCheckedVersion(MainActivity.this,new UpdateListener() {@Overridepublic void onUpdateReturned(int updateStatus, VersionInfo versionInfo) {//判断回调过来的版本检测状态switch (updateStatus) {case UpdateStatus.YES://弹出更新提示UpdateVersionUtil.showDialog(MainActivity.this,versionInfo);break;case UpdateStatus.NO://没有新版本ToastUtils.showToast(getApplicationContext(), "已经是最新版本了!");break;case UpdateStatus.NOWIFI://当前是非wifi网络ToastUtils.showToast(getApplicationContext(), "只有在wifi下更新!"); // DialogUtils.showDialog(MainActivity.this, "温馨提示","当前非wifi网络,下载会消耗手机流量!", "确定", "取消",new DialogOnClickListenner() { // @Override // public void btnConfirmClick(Dialog dialog) { // dialog.dismiss(); // //点击确定之后弹出更新对话框 // UpdateVersionUtil.showDialog(SystemActivity.this,versionInfo); // } // // @Override // public void btnCancelClick(Dialog dialog) { // dialog.dismiss(); // } // });break;case UpdateStatus.ERROR://检测失败ToastUtils.showToast(getApplicationContext(), "检测失败,请稍后重试!");break;case UpdateStatus.TIMEOUT://链接超时ToastUtils.showToast(getApplicationContext(), "链接超时,请检查网络设置!");break;}}});*/}});} }
2、版本检测的工具类
/*** * @author wenjie* 版本更新的工具类*/ public class UpdateVersionUtil{/*** 接口回调* @author wenjie**/public interface UpdateListener{void onUpdateReturned(int updateStatus,VersionInfo versionInfo);}public UpdateListener updateListener;public void setUpdateListener(UpdateListener updateListener) {this.updateListener = updateListener;}/*** 网络测试 检测版本* @param context 上下文*/public static void checkVersion(final Context context,final UpdateListener updateListener){HttpRequest.get(ServerReqAddress.UPDATA_VERSION_REQ, new RequestCallBackListener() {@Overridepublic void onSuccess(String resultData) {try {JSONObject jsonObject = JsonUtil.stringToJson(resultData);JSONArray array = jsonObject.getJSONArray("data");VersionInfo mVersionInfo = JsonUtil.jsonToBean(array.getJSONObject(0).toString(), VersionInfo.class);int clientVersionCode = ApkUtils.getVersionCode(context);int serverVersionCode = mVersionInfo.getVersionCode();//有新版本if(clientVersionCode < serverVersionCode){int i = NetworkUtil.checkedNetWorkType(context);if(i == NetworkUtil.NOWIFI){updateListener.onUpdateReturned(UpdateStatus.NOWIFI,mVersionInfo);}else if(i == NetworkUtil.WIFI){updateListener.onUpdateReturned(UpdateStatus.YES,mVersionInfo);}}else{//无新本updateListener.onUpdateReturned(UpdateStatus.NO,null);}} catch (Exception e) {e.printStackTrace();updateListener.onUpdateReturned(UpdateStatus.ERROR,null);}}@Overridepublic void onFailure(String error) {updateListener.onUpdateReturned(UpdateStatus.TIMEOUT,null);}});}/*** 本地测试*/public static void localCheckedVersion(final Context context,final UpdateListener updateListener){try { // JSONObject jsonObject = JsonUtil.stringToJson(resultData); // JSONArray array = jsonObject.getJSONArray("data"); // VersionInfo mVersionInfo = JsonUtil.jsonToBean(array.getJSONObject(0).toString(), VersionInfo.class);VersionInfo mVersionInfo = new VersionInfo();mVersionInfo.setDownloadUrl("http://gdown.baidu.com/data/wisegame/57a788487345e938/QQ_358.apk");mVersionInfo.setVersionDesc("\n更新内容:\n1、增加xxxxxxxxx功能\n2、增加xxxxxxxxx显示!\n3、用户界面优化!\n4、处理了xxxxxxxxBUG!");mVersionInfo.setVersionCode(2);mVersionInfo.setVersionName("v2020");mVersionInfo.setVersionSize("20.1M");mVersionInfo.setId("1");int clientVersionCode = ApkUtils.getVersionCode(context);int serverVersionCode = mVersionInfo.getVersionCode();//有新版本if(clientVersionCode < serverVersionCode){int i = NetworkUtil.checkedNetWorkType(context);if(i == NetworkUtil.NOWIFI){updateListener.onUpdateReturned(UpdateStatus.NOWIFI,mVersionInfo);}else if(i == NetworkUtil.WIFI){updateListener.onUpdateReturned(UpdateStatus.YES,mVersionInfo);}}else{//无新本updateListener.onUpdateReturned(UpdateStatus.NO,null);}} catch (Exception e) {e.printStackTrace();updateListener.onUpdateReturned(UpdateStatus.ERROR,null);}}/*** 弹出新版本提示* @param context 上下文* @param versionInfo 更新内容*/public static void showDialog(final Context context,final VersionInfo versionInfo){final Dialog dialog = new AlertDialog.Builder(context).create();final File file = new File(SDCardUtils.getRootDirectory()+"/updateVersion/gdmsaec-app.apk");dialog.setCancelable(true);// 可以用“返回键”取消 dialog.setCanceledOnTouchOutside(false);// dialog.show();View view = LayoutInflater.from(context).inflate(R.layout.version_update_dialog, null);dialog.setContentView(view);final Button btnOk = (Button) view.findViewById(R.id.btn_update_id_ok);Button btnCancel = (Button) view.findViewById(R.id.btn_update_id_cancel);TextView tvContent = (TextView) view.findViewById(R.id.tv_update_content);TextView tvUpdateTile = (TextView) view.findViewById(R.id.tv_update_title);final TextView tvUpdateMsgSize = (TextView) view.findViewById(R.id.tv_update_msg_size);tvContent.setText(versionInfo.getVersionDesc());tvUpdateTile.setText("最新版本:"+versionInfo.getVersionName());if(file.exists() && file.getName().equals("gdmsaec-app.apk")){tvUpdateMsgSize.setText("新版本已经下载,是否安装?");}else{tvUpdateMsgSize.setText("新版本大小:"+versionInfo.getVersionSize());}btnOk.setOnClickListener(new OnClickListener() {@Overridepublic void onClick(View v) {dialog.dismiss();if(v.getId() == R.id.btn_update_id_ok){//新版本已经下载if(file.exists() && file.getName().equals("gdmsaec-app.apk")){Intent intent = ApkUtils.getInstallIntent(file);context.startActivity(intent);}else{//没有下载,则开启服务下载新版本Intent intent = new Intent(context,UpdateVersionService.class);intent.putExtra("downloadUrl", versionInfo.getDownloadUrl());context.startService(intent);}}}});btnCancel.setOnClickListener(new OnClickListener() {@Overridepublic void onClick(View v) {dialog.dismiss();}});}/*** 收起通知栏* @param context*/public static void collapseStatusBar(Context context) { try{Object statusBarManager = context.getSystemService("statusbar"); Method collapse;if (Build.VERSION.SDK_INT <= 16){collapse = statusBarManager.getClass().getMethod("collapse"); }else{ collapse = statusBarManager.getClass().getMethod("collapsePanels"); } collapse.invoke(statusBarManager);}catch (Exception localException){ localException.printStackTrace();} } }
3、版本检测的状态类
/*** * @author wenjie* 检测版本的状态类*/ public interface UpdateStatus {/*** 没有新版本*/public static int NO = 1;/*** 有新版本*/public static int YES = 2;/*** 链接超时*/public static int TIMEOUT = 3;/*** 没有wifi*/public static int NOWIFI = 4;/*** 数据解析出错*/public static int ERROR = -1; }
4、版本更新的service
/*** * @author wenjie* 下载新版本的服务类*/ public class UpdateVersionService extends Service {private NotificationManager nm;private Notification notification;//标题标识private int titleId = 0;//安装文件private File updateFile;private static HttpHandler<File> httpHandler;private HttpUtils httpUtils;private long initTotal = 0;//文件的总长度 @Overridepublic void onCreate() {super.onCreate();httpUtils = new HttpUtils();updateFile = new File(SDCardUtils.getRootDirectory()+"/updateVersion/gdmsaec-app.apk");nm = (NotificationManager) getSystemService(NOTIFICATION_SERVICE);notification = new Notification();notification.icon = R.drawable.ic_launcher;notification.tickerText = "开始下载";notification.when = System.currentTimeMillis();notification.contentView = new RemoteViews(getPackageName(), R.layout.notifycation);}@Overridepublic int onStartCommand(Intent intent, int flags, int startId) {// VersionInfo versionInfo = (VersionInfo) intent.getSerializableExtra("versionInfo"); // String url = versionInfo.getDownloadUrl();Bundle bundle = intent.getExtras();String url = bundle.getString("downloadUrl");PreferenceUtils.setString(UpdateVersionService.this, "apkDownloadurl", url);nm.notify(titleId, notification);downLoadFile(url);return super.onStartCommand(intent, flags, startId);}public void downLoadFile(String url){httpHandler = httpUtils.download(url,updateFile.getAbsolutePath(), true, false, new RequestCallBack<File>() {@Overridepublic void onSuccess(ResponseInfo<File> response) {// 更改文字notification.contentView.setTextViewText(R.id.msg, "下载完成!点击安装"); // notification.contentView.setViewVisibility(R.id.btnStartStop, View.GONE); // notification.contentView.setViewVisibility(R.id.btnCancel,View.GONE);// 发送消息nm.notify(0, notification);stopSelf();//收起通知栏UpdateVersionUtil.collapseStatusBar(UpdateVersionService.this);//自动安装新版本Intent installIntent = ApkUtils.getInstallIntent(updateFile);startActivity(installIntent);}@Overridepublic void onFailure(HttpException error, String msg) {//网络连接错误if(error.getExceptionCode() == 0 ){// 更改文字notification.contentView.setTextViewText(R.id.msg, "网络异常!请检查网络设置!");}else if(error.getExceptionCode() == 416){//文件已经下载完毕// 更改文字notification.contentView.setTextViewText(R.id.msg, "xxx");// 更改文字notification.contentView.setTextViewText(R.id.bartext, "检测到新版本已经下载完成,点击即安装!");// 隐藏进度条 notification.contentView.setViewVisibility(R.id.progressBar1, View.GONE);Intent intent = ApkUtils.getInstallIntent(updateFile);PendingIntent pendingIntent = PendingIntent.getActivity(UpdateVersionService.this, 0, intent, 0);notification.flags = Notification.FLAG_AUTO_CANCEL;//点击通知栏之后 消失notification.contentIntent = pendingIntent;//启动指定意图 }// 发送消息nm.notify(0, notification);}@Overridepublic void onLoading(long total, long current, boolean isUploading) {if(initTotal == 0){//说明第一次开始下载initTotal = total;}if(initTotal != total){//说明下载过程中暂停过,文件的总长度出现问题 就把初始的文件的长度赋值给他重新计算已经下载的比例total = initTotal;}long l = current*100/total;notification.contentView.setTextViewText(R.id.msg, "正在下载:xxx");// 更改文字notification.contentView.setTextViewText(R.id.bartext, l+ "%");// 更改进度条notification.contentView.setProgressBar(R.id.progressBar1, 100,(int)l, false);// 发送消息nm.notify(0, notification);// Intent intent = new Intent(); // intent.setAction("cancel"); // PendingIntent pendingIntent = PendingIntent.getBroadcast(getApplicationContext(), 0, intent, 0); // notification.contentView.setOnClickPendingIntent(R.id.btnStartStop, pendingIntent); }@Overridepublic void onStart() {notification.contentView.setTextViewText(R.id.msg, "开始下载:智慧海事");nm.notify(titleId, notification);}});}public static HttpHandler<File> getHandler(){return httpHandler;}@Overridepublic void onDestroy() {//下载完成时,清楚该通知,自动安装 nm.cancel(titleId);System.out.println("UpdateVersionService----onDestroy"); // try { // GdmsaecApplication.db.deleteAll(VersionInfo.class); // } catch (DbException e) { // e.printStackTrace(); // }super.onDestroy();}@Overridepublic IBinder onBind(Intent intent) {return null;} }
5、吐司的工具类
public class ToastUtils { private static String oldMsg; protected static Toast toast = null; private static long oneTime=0; private static long twoTime=0; /** * 吐出一个显示时间较短的提示 * @param context 上下文 * @param s 文本内容 */ public static void showToast(Context context, String s){ if(toast==null){ toast =Toast.makeText(context, s, Toast.LENGTH_SHORT); toast.show(); oneTime=System.currentTimeMillis(); }else{ twoTime=System.currentTimeMillis(); if(s.equals(oldMsg)){ if(twoTime-oneTime>Toast.LENGTH_SHORT){ toast.show(); } }else{ oldMsg = s; toast.setText(s); toast.show(); } } oneTime=twoTime; } }
6、获取sdcard根目录
public static String getState(){ return Environment.getExternalStorageState(); } /** * SD卡是否可用 * @return 只有当SD卡已经安装并且准备好了才返回true */ public static boolean isAvailable(){ return getState().equals(Environment.MEDIA_MOUNTED); } /** * 获取SD卡的根目录 * @return null:不存在SD卡 */ public static File getRootDirectory(){ return isAvailable()?Environment.getExternalStorageDirectory():null; }
7、版本检测的实体类
public class VersionInfo implements Serializable{ /** * */ private static final long serialVersionUID = 1L; private String id; private String versionName;//版本名 private int versionCode;//版本号 private String versionDesc;//版本描述信息内容 private String downloadUrl;//新版本的下载路径 private String versionSize;//版本大小 public String getId() { return id; } public void setId(String id) { this.id = id; } public String getVersionSize() { return versionSize; } public void setVersionSize(String versionSize) { this.versionSize = versionSize; } public String getVersionName() { return versionName; } public void setVersionName(String versionName) { this.versionName = versionName; } public int getVersionCode() { return versionCode; } public void setVersionCode(int versionCode) { this.versionCode = versionCode; } public String getVersionDesc() { return versionDesc; } public void setVersionDesc(String versionDesc) { this.versionDesc = versionDesc; } public String getDownloadUrl() { return downloadUrl; } public void setDownloadUrl(String downloadUrl) { this.downloadUrl = downloadUrl; } }
8、网络监测
* 网络检查 * @author 00 * */ public class NetworkUtil { /** * 没有网络 */ public static final int NONETWORK = 0; /** * 当前是wifi连接 */ public static final int WIFI = 1; /** * 不是wifi连接 */ public static final int NOWIFI = 2; /** * 检测当前网络的类型 是否是wifi * @param context * @return */ public static int checkedNetWorkType(Context context){ if(!checkedNetWork(context)){ return NONETWORK; } ConnectivityManager cm = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE); if(cm.getNetworkInfo(ConnectivityManager.TYPE_WIFI).isConnectedOrConnecting() ){ return WIFI; }else{ return NOWIFI; } } /** * 检查是否连接网络 * @param context * @return */ public static boolean checkedNetWork(Context context){ // 1.获得连接设备管理器 ConnectivityManager cm = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE); if(cm == null) return false; /** * 获取网络连接对象 */ NetworkInfo networkInfo = cm.getActiveNetworkInfo(); if(networkInfo == null || !networkInfo.isAvailable()){ return false; } return true; } }
9、json解析类
/** * json 和 实体类之间的相互转换 * @author 00 * */ public class JsonUtil { /** * 将一个实体对象 转换成一个json字符串 提示对象中可包含集合 * @param t 实体类 * @return */ public static <T> String beanToJson(T t){ Gson gson = new Gson(); String json = gson.toJson(t); return json; } /** * 将一个json字符串 转换成一个实体类对象 可包含list * @param json * @param t * @return */ public static <T> T jsonToBean(String json,Class<T> class1) throws InstantiationException, IllegalAccessException{ Gson gson = new Gson(); T t = class1.newInstance(); t=gson.fromJson(json, class1); return t; } /** * 将json字符串转换成一个json对象 * @param str * @return */ public static JSONObject stringToJson(String str){ try { return new JSONObject(str); } catch (JSONException e) { e.printStackTrace(); return null; } } public static String getString(InputStream is){ try { ByteArrayOutputStream baos = new ByteArrayOutputStream(); byte[] buffer = new byte[1024]; int len = -1; while((len = is.read(buffer)) != -1){ baos.write(buffer, 0, len); } byte[] byteArray = baos.toByteArray(); //String str = new String(byteArray); return new String(byteArray,"utf-8"); } catch (IOException e) { e.printStackTrace(); } return ""; } /** * 从assert文件夹中读取json文件,然后转化为json对象 * @throws Exception */ public static JSONObject getJsonDataFromAssets(Context context,String jsonFileName) throws Exception{ JSONObject mJsonObj = null; StringBuffer sb = new StringBuffer(); InputStream is = context.getAssets().open(jsonFileName); int len = -1; byte[] buf = new byte[1024]; while ((len = is.read(buf)) != -1){ sb.append(new String(buf, 0, len, "UTF-8")); } is.close(); mJsonObj = new JSONObject(sb.toString()); return mJsonObj; } }
10、http请求类
/** * http 请求工具类 * @author winfo-wj * */ public class HttpRequest { private static HttpUtils http = new HttpUtils(); /** * 请求回调接口 * @author winfo-wj * */ public interface RequestCallBackListener{ /** * 请求成功 * @param resultData 服务器返回的结果数据 */ public void onSuccess(String resultData); /** * 请求失败 * @param error 错误信息 */ public void onFailure(String error); } /** * get请求 * @param url 请求路径 * @param requestCallBackListener 请求回调 */ public static void get(String url , final RequestCallBackListener requestCallBackListener){ http.configTimeout(1000*10); http.send(HttpMethod.GET, url, new RequestCallBack<String>() { @Override public void onSuccess(ResponseInfo<String> response) { requestCallBackListener.onSuccess(response.result); } @Override public void onFailure(HttpException error, String msg) { requestCallBackListener.onFailure(msg); } }); } /** * post请求 * @param url 请求地址 * @param params 请求参数 * @param requestCallBackListener 请求回调 */ public static void post(String url ,RequestParams params , final RequestCallBackListener requestCallBackListener){ http.configTimeout(1000*10); http.send(HttpMethod.POST, url, params, new RequestCallBack<String>() { @Override public void onSuccess(ResponseInfo<String> response) { requestCallBackListener.onSuccess(response.result); } @Override public void onFailure(HttpException error, String msg) { requestCallBackListener.onFailure(msg); } }); } }
12、通知栏的布局
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="fill_parent" android:orientation="vertical" android:layout_height="fill_parent" > <LinearLayout android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="horizontal" > <LinearLayout android:layout_width="wrap_content" android:layout_height="wrap_content" android:orientation="horizontal" android:layout_gravity="center_vertical" > <ImageView android:layout_width="40dp" android:layout_height="40dp" android:layout_gravity="center" android:src="@drawable/ic_launcher" /> </LinearLayout> <LinearLayout android:layout_width="match_parent" android:layout_height="wrap_content" android:orientation="vertical" android:weightSum="3" android:paddingLeft="10dp" android:paddingRight="10dp" android:layout_gravity="center_vertical" > <TextView android:id="@+id/msg" android:text="正在下载:xxx" android:layout_width="wrap_content" android:layout_height="wrap_content" android:textColor="#ffffff" android:textSize="14sp" /> <TextView android:id="@+id/bartext" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="0%" android:textColor="#ffffff" android:textSize="12sp" /> <ProgressBar android:id="@+id/progressBar1" style="?android:attr/progressBarStyleHorizontal" android:layout_width="match_parent" android:layout_height="5dp" /> <!-- <LinearLayout android:layout_width="match_parent" android:layout_height="wrap_content" android:orientation="horizontal" > <Button android:id="@+id/btnStartStop" android:layout_width="0dp" android:layout_weight="1" android:layout_height="25dp" android:text="暂停" android:textSize="12sp" android:textColor="#ffffff" /> <Button android:id="@+id/btnCancel" android:layout_width="0dp" android:layout_weight="1" android:layout_height="25dp" android:text="取消" android:textSize="12sp" android:textColor="#ffffff" /> </LinearLayout> --> </LinearLayout> </LinearLayout> </LinearLayout>
13、按本更新提示的对话框布局文件
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="wrap_content" > <LinearLayout android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_marginLeft="60dp" android:layout_centerInParent="true" android:layout_marginRight="60dp" android:background="@drawable/dialog_bg" android:orientation="vertical" > <!-- Title --> <RelativeLayout android:layout_width="fill_parent" android:layout_height="45dp" > <ImageView android:id="@+id/umeng_wifi_indicator" android:layout_width="30dp" android:layout_height="30dp" android:layout_centerVertical="true" android:layout_marginLeft="10dp" android:src="@drawable/ic_launcher" /> <TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_centerInParent="true" android:text="发现新版本" android:textSize="@dimen/normal_text_size" android:textAppearance="?android:attr/textAppearanceLarge" android:textColor="@color/black" /> </RelativeLayout> <!-- split --> <View android:layout_width="fill_parent" android:layout_height="0.5dp" android:layout_marginLeft="10dp" android:layout_marginRight="10dp" android:background="#d8d8d8" /> <!-- Content --> <ScrollView android:layout_width="fill_parent" android:layout_height="0dp" android:padding="10dp" android:layout_weight="1" > <LinearLayout android:layout_width="fill_parent" android:layout_height="wrap_content" android:orientation="vertical" > <TextView android:id="@+id/tv_update_title" android:layout_width="match_parent" android:layout_height="wrap_content" android:text="最新版本:xxxv2.2.1" android:textColor="@color/black" android:textSize="@dimen/medium_text_size" /> <TextView android:id="@+id/tv_update_msg_size" android:layout_width="match_parent" android:layout_height="wrap_content" android:text="新版本大小:19.07M" android:textSize="@dimen/medium_text_size" android:layout_marginTop="10dp" android:textColor="@color/black" /> <TextView android:id="@+id/tv_update_content" android:layout_width="fill_parent" android:layout_height="wrap_content" android:minHeight="60dp" android:textSize="@dimen/medium_text_size" android:lineSpacingExtra="3dp" android:textColor="@color/black" /> </LinearLayout> </ScrollView> <!-- Ignore CheckBox --> <!-- OK&Cancel Button --> <LinearLayout android:layout_width="fill_parent" android:orientation="horizontal" android:layout_height="wrap_content" > <Button android:id="@+id/btn_update_id_cancel" android:layout_width="0dp" android:layout_height="40dp" android:layout_weight="1" android:background="@drawable/dialog_cancel_btn_bg" android:text="以后再说" android:layout_marginLeft="10dp" android:layout_marginRight="5dp" android:layout_marginBottom="10dp" android:textSize="@dimen/normal_text_size" android:textColor="@color/black" /> <Button android:id="@+id/btn_update_id_ok" android:layout_width="0dp" android:layout_marginLeft="5dp" android:layout_marginRight="10dp" android:layout_marginBottom="10dp" android:layout_height="40dp" android:layout_weight="1" android:textSize="@dimen/normal_text_size" android:background="@drawable/dialog_ok_btn_bg" android:text="立即更新" android:textColor="@color/white" /> </LinearLayout> </LinearLayout> </RelativeLayout>
14对话框按钮的.9图
15、
<!-- 黑色 --><color name="black">#333333</color>17、字体大小文件<dimen name="title_text_size">18sp</dimen><!-- 标题字体大小 --><dimen name="normal_text_size">16sp</dimen><!-- 通常字体大小 --><dimen name="medium_text_size">14sp</dimen><!-- 中等字体大小 --><dimen name="small_text_size">12sp</dimen><!-- 小号字体大小 -->
转载于:https://www.cnblogs.com/wenjie123/p/5512853.html
android应用版本更新功能---完整版相关推荐
- 通用(任何android机型)Root教程(完整版!附砖机自救方法)转自安卓网
通用(任何android机型)Root教程(完整版!附砖机自救方法)转自安卓网 2012年01月02日 一台android终端(可能是手机.可能是平板,也可能是其它),很多功能是要取得Root权限后才 ...
- appinventor mysql_利用AppInventor实现登录功能(完整版).docx
利用AppInventor实现登录功能(完整版) 上次教程,我们已经在SAE的共享型MySQL中新建了数据表,并且通过APP向数据表中写入了用户的信息(用户名.密码.昵称),如下图所示: ?????? ...
- 清华大学计算机系毕业论文 android,计算机专业毕业论文完整版.doc
计算机专业毕业论文完整版 摘要 随着信息技术的高速发展,21世纪是数字信息时代,互联网正以前所未有的冲击力影响着人类的生活.它的出现和发展,同样也为学校的发展提供了丰富的资源.正是在这样的趋势下,大部 ...
- 购物车功能完整版12.13
一.这次系统来做了下购物车的功能模块,以下几个功能吧: 1.查询购物车列表 2.向购物车添加商品 3.删除购物车商品 4.修改购物车商品数量 以上四个是传统的增删改成功能. 5.购物车商品全选功能实现 ...
- springboot 微信小程序 对接微信支付功能(完整版)
微信小程序对接微信支付功能 业务流程时序图 JAVA版 1. 项目架构 2. pom.xml配置文件 3. 小程序账号参数配置类 4.JAVA 通用代码 4.1 工具类 4.1.1 IdGen (id ...
- wangEditor 修改 “视频”菜单 的实现方式,达到上传视频的功能---完整版
//经测,没能实现我的需求,我经二次修改实现,仅先修改了构造函数 UploadVideo 里面的些许判断,下面链接为我改过的 https://blog.csdn.net/m0_37885651/art ...
- android+客户端+教程,Android新浪客户端开发教程完整版.pdf
Android新浪客户端开发教程完整版 Android 新浪客户端开发教程新浪客户端开发教程 (完整版(完整版)) 新浪客户端开发教程新浪客户端开发教程 ((完整版完整版)) android开发我的新 ...
- Android掌中游斗地主游戏源码完整版
源码大放送-掌中游斗地主(完整版),集合了单机斗地主.网络斗地主.癞子斗地主等,有史以来最有参考价值的源码,虽然运行慢了一点但是功能正常,用的是纯java写的. 项目详细说明:http://andro ...
- HUAWEI被google禁完整版Android的背后——中美两国的博弈。
路透社5月20日报道称,谷歌已经暂停了与华为的部分业务往来. 谷歌将不再与华为开展需要转让硬件和软件产品的业务,但在开源授权范围内的除外.谷歌还将停止就安卓和谷歌服务为华为提供技术支持和协作. 对此, ...
最新文章
- Linux安装HDF5及遇到的问题总结
- 腾讯首次发布 AI 白皮书讲了什么?
- 第二次作业 郭昭杰 201731062608
- MATLAB 多项式
- 可以下载Microsoft ISA Server 2006 试用版了,网管需要关注
- 中国新型储能市场技术进展与投资经营模式建议分析报告2022-2028年版
- 使用Flow快速开发Teams小应用
- 带有自定义模块的JBoss EAP上的骆驼
- 大数据基础知识问答----hadoop篇
- 【java基础知识】swagger组件常用命令
- sklearn学习总结
- 系统提示System.Data.OracleClient 需要 Oracle 客户端软件 8.1.7 或更高版本解决办法...
- spring boot actuator 如何显示详细信息
- Hinton 最近提出的 Capsule 计划
- purifier 常用配置 保留 id 和 iframe
- 安卓客户端开发!如何试出一个Android开发者真正的水平?分享PDF高清版
- 原腾讯副总裁,Google资深研究员吴军:ChatGPT不算新技术革命,带不来什么新机会...
- mysql 查询数据库ip_如何查看连接MYSQL数据库的IP信息
- 强力解决npm各种大姨妈
- 将虚拟机VMware从C盘移动到E盘
热门文章
- CVPR | 基于LiDAR的3D物体检测新框架
- Python解决print()不换行问题
- 一道简单的sql语句题
- Numpy基础知识点汇总
- 深度学习(三十五)异构计算GLSL学习笔记(1)
- 如何写标题摘要关键字
- 使用 加载 顺序_SpringBoot系列教程之Bean加载顺序之错误使用姿势辟谣
- java实现米和厘米比较好_java如何根据实际经、纬度和已知经、纬度做对比,计算出具体偏差米数。(以米为单位)...
- centos7 mysql 5.5.27_centos7上安装mysql-5.7.27
- axios在派遣方法时候的异步