你的位置:首页 > 操作系统

[操作系统]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;    @Override  protected void onCreate(Bundle savedInstanceState) {    super.onCreate(savedInstanceState);    setContentView(R.layout.activity_main);        button = (Button) findViewById(R.id.button1);        button.setOnClickListener(new OnClickListener() {            @Override      public void onClick(View v) {        //本地测试检测是否有新版本发布        UpdateVersionUtil.localCheckedVersion(MainActivity.this,new UpdateListener() {                    @Override          public 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() {                    @Override          public 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() {            @Override      public 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);        }      }            @Override      public 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() {      @Override      public 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() {      @Override      public 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;//文件的总长度    @Override  public 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);      }  @Override  public 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>() {            @Override      public 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);              }            @Override      public 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);      }      @Override      public 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);              }      @Override      public void onStart() {        notification.contentView.setTextViewText(R.id.msg, "开始下载:智慧海事");        nm.notify(titleId, notification);      }          });  }      public static HttpHandler<File> getHandler(){    return httpHandler;  }      @Override  public void onDestroy() {    //下载完成时,清楚该通知,自动安装    nm.cancel(titleId);    System.out.println("UpdateVersionService----onDestroy");//    try {//      GdmsaecApplication.db.deleteAll(VersionInfo.class);//    } catch (DbException e) {//      e.printStackTrace();//    }    super.onDestroy();  }    @Override  public 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 ="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 ="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><!-- 小号字体大小 -->