閱讀250 返回首頁    go 阿裏雲 go 技術社區[雲棲]


手機衛士03-下載app並安裝

原文再續書接上一回,昨天我們把那個與服務器端的交互以及解析xml的內容給搭建出來啦,那麼今天我們就來完成一下下載新版的apk並安裝的邏輯寫一下

既然要下載apk,那麼肯定是另開一個線程下載的啦,所以我們在這裏就新建一個類啦

com.xiaobin.security.engine.DownloadTask


  1. <font color="#333333"><font face="Arial">package com.xiaobin.security.engine;

  2. import java.io.File;
  3. import java.io.FileOutputStream;
  4. import java.io.InputStream;
  5. import java.net.HttpURLConnection;
  6. import java.net.URL;

  7. import android.app.ProgressDialog;

  8. public class DownloadTask
  9. {
  10.         
  11.         public static File getFile(String path, String filePath, ProgressDialog progressDialog) throws Exception
  12.         {
  13.                 URL url = new URL(path);
  14.                 HttpURLConnection httpURLConnection = (HttpURLConnection) url.openConnection();
  15.                 httpURLConnection.setConnectTimeout(2000);
  16.                 httpURLConnection.setRequestMethod("GET");
  17.                 if(httpURLConnection.getResponseCode() == 200)
  18.                 {
  19.                         int total = httpURLConnection.getContentLength();
  20.                         progressDialog.setMax(total);
  21.                         
  22.                         InputStream is = httpURLConnection.getInputStream();
  23.                         File file = new File(filePath);
  24.                         FileOutputStream fos = new FileOutputStream(file);
  25.                         byte[] buffer = new byte[1024];
  26.                         int len;
  27.                         int process = 0;
  28.                         while((len = is.read(buffer)) != -1)
  29.                         {
  30.                                 fos.write(buffer, 0, len);
  31.                                 process += len;
  32.                                 progressDialog.setProgress(process);
  33.                         }
  34.                         fos.flush();
  35.                         fos.close();
  36.                         is.close();
  37.                         return file;
  38.                 }
  39.                 return null;
  40.         }

  41. }
  42. </font></font>
複製代碼
好啦,那個寫好了,從服務器裏麵拿到一個最新版的apk之後,我們就要在SplashActivity裏麵寫一些安裝的邏輯啦,還有一個內部類,用來啟動另一個線程下載  com.xiaobin.security.ui.SplashActivity
  1. package com.xiaobin.security.ui;

  2. import java.io.File;

  3. import android.annotation.SuppressLint;
  4. import android.app.Activity;
  5. import android.app.AlertDialog;
  6. import android.app.ProgressDialog;
  7. import android.content.DialogInterface;
  8. import android.content.Intent;
  9. import android.content.pm.PackageInfo;
  10. import android.content.pm.PackageManager;
  11. import android.content.pm.PackageManager.NameNotFoundException;
  12. import android.net.Uri;
  13. import android.os.Bundle;
  14. import android.os.Environment;
  15. import android.os.Handler;
  16. import android.os.Message;
  17. import android.util.Log;
  18. import android.view.Window;
  19. import android.view.WindowManager;
  20. import android.view.animation.AlphaAnimation;
  21. import android.widget.LinearLayout;
  22. import android.widget.TextView;
  23. import android.widget.Toast;

  24. import com.xiaobin.security.R;
  25. import com.xiaobin.security.domain.UpdateInfo;
  26. import com.xiaobin.security.engine.DownloadTask;
  27. import com.xiaobin.security.engine.UpdateInfoService;

  28. public class SplashActivity extends Activity
  29. {
  30.         private TextView tv_version;
  31.         private LinearLayout ll;
  32.         private ProgressDialog progressDialog;
  33.         
  34.         private UpdateInfo info;
  35.         private String version;
  36.         
  37.         private static final String TAG = "Security";
  38.         
  39.         @SuppressLint("HandlerLeak")
  40.         private Handler handler = new Handler()
  41.         {
  42.                 public void handleMessage(Message msg)
  43.                 {
  44.                         if(isNeedUpdate(version))
  45.                         {
  46.                                 showUpdateDialog();
  47.                         }
  48.                 };
  49.         };
  50.         
  51.         @Override
  52.         protected void onCreate(Bundle savedInstanceState)
  53.         {
  54.                 super.onCreate(savedInstanceState);
  55.                 requestWindowFeature(Window.FEATURE_NO_TITLE);
  56.                 setContentView(R.layout.splash);
  57.                 getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN, WindowManager.LayoutParams.FLAG_FULLSCREEN);
  58.                
  59.                 tv_version = (TextView) findViewById(R.id.tv_splash_version);
  60.                 version = getVersion();
  61.                 tv_version.setText("版本號  " + version);
  62.                
  63.                 ll = (LinearLayout) findViewById(R.id.ll_splash_main);
  64.                 AlphaAnimation alphaAnimation = new AlphaAnimation(0.0f, 1.0f);
  65.                 alphaAnimation.setDuration(2000);
  66.                 ll.startAnimation(alphaAnimation);
  67.                
  68.                 progressDialog = new ProgressDialog(this);
  69.                 progressDialog.setProgressStyle(ProgressDialog.STYLE_HORIZONTAL);
  70.                 progressDialog.setMessage("正在下載...");
  71.                
  72.                 new Thread()
  73.                 {
  74.                         public void run()
  75.                         {
  76.                                 try
  77.                                 {
  78.                                         sleep(3000);
  79.                                         handler.sendEmptyMessage(0);
  80.                                 }
  81.                                 catch (InterruptedException e)
  82.                                 {
  83.                                         e.printStackTrace();
  84.                                 }
  85.                         };
  86.                 }.start();
  87.                
  88.         }
  89.         
  90.         private void showUpdateDialog()
  91.         {
  92.                 AlertDialog.Builder builder = new AlertDialog.Builder(this);
  93.                 builder.setIcon(android.R.drawable.ic_dialog_info);
  94.                 builder.setTitle("升級提醒");
  95.                 builder.setMessage(info.getDescription());
  96.                 builder.setCancelable(false);
  97.                
  98.                 builder.setPositiveButton("確定", new DialogInterface.OnClickListener()
  99.                 {
  100.                         
  101.                         @Override
  102.                         public void onClick(DialogInterface dialog, int which)
  103.                         {
  104.                                 if(Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED))
  105.                                 {
  106.                                         File dir = new File(Environment.getExternalStorageDirectory(), "/security/update");
  107.                                         if(!dir.exists())
  108.                                         {
  109.                                                 dir.mkdirs();
  110.                                         }
  111.                                         String apkPath = Environment.getExternalStorageDirectory() + "/security/update/new.apk";
  112.                                         UpdateTask task = new UpdateTask(info.getUrl(), apkPath);
  113.                                         progressDialog.show();
  114.                                         new Thread(task).start();
  115.                                 }
  116.                                 else
  117.                                 {
  118.                                         Toast.makeText(SplashActivity.this, "SD卡不可用,請插入SD卡", Toast.LENGTH_SHORT).show();
  119.                                         loadMainUI();
  120.                                 }
  121.                         }
  122.                 });
  123.                 builder.setNegativeButton("取消", new DialogInterface.OnClickListener()
  124.                 {

  125.                         @Override
  126.                         public void onClick(DialogInterface dialog, int which)
  127.                         {
  128.                                 loadMainUI();
  129.                         }
  130.                         
  131.                 });
  132.                 builder.create().show();
  133.         }

  134.         private boolean isNeedUpdate(String version)
  135.         {
  136.                 UpdateInfoService updateInfoService = new UpdateInfoService(this);
  137.                 try
  138.                 {
  139.                         info = updateInfoService.getUpdateInfo(R.string.serverUrl);
  140.                         String v = info.getVersion();
  141.                         if(v.equals(version))
  142.                         {
  143.                                 Log.i(TAG, "當前版本:" + version);
  144.                                 Log.i(TAG, "最新版本:" + v);
  145.                                 loadMainUI();
  146.                                 return false;
  147.                         }
  148.                         else
  149.                         {
  150.                                 Log.i(TAG, "需要更新");
  151.                                 return true;
  152.                         }
  153.                 }
  154.                 catch (Exception e)
  155.                 {
  156.                         e.printStackTrace();
  157.                         Toast.makeText(this, "獲取更新信息異常,請稍後再試", Toast.LENGTH_SHORT).show();
  158.                         loadMainUI();
  159.                 }
  160.                 return false;
  161.         }

  162.         private String getVersion()
  163.         {
  164.                 try
  165.                 {
  166.                         PackageManager packageManager = getPackageManager();
  167.                         PackageInfo packageInfo = packageManager.getPackageInfo(getPackageName(), 0);
  168.                         
  169.                         return packageInfo.versionName;
  170.                 }
  171.                 catch (NameNotFoundException e)
  172.                 {
  173.                         e.printStackTrace();
  174.                         return "版本號未知";
  175.                 }
  176.         }
  177.         
  178.         private void loadMainUI()
  179.         {
  180.                 Intent intent = new Intent(this, MainActivity.class);
  181.                 startActivity(intent);
  182.                 finish();
  183.         }
  184.         
  185.         /**
  186.          * 安裝apk
  187.          * @param file 要安裝的apk的目錄
  188.          */
  189.         private void install(File file)
  190.         {
  191.                 Intent intent = new Intent();
  192.                 intent.setAction(Intent.ACTION_VIEW);
  193.                 intent.setDataAndType(Uri.fromFile(file), "application/vnd.android.package-archive");
  194.                 finish();
  195.                 startActivity(intent);
  196.         }
  197.         
  198.         //===========================================================================================
  199.         
  200.         /**
  201.          * 下載的線程
  202.          *
  203.          */
  204.         class UpdateTask implements Runnable
  205.         {
  206.                 private String path;
  207.                 private String filePath;
  208.                
  209.                 public UpdateTask(String path, String filePath)
  210.                 {
  211.                         this.path = path;
  212.                         this.filePath = filePath;
  213.                 }

  214.                 @Override
  215.                 public void run()
  216.                 {
  217.                         try
  218.                         {
  219.                                 File file = DownloadTask.getFile(path, filePath, progressDialog);
  220.                                 progressDialog.dismiss();
  221.                                 install(file);
  222.                         }
  223.                         catch (Exception e)
  224.                         {
  225.                                 e.printStackTrace();
  226.                                 progressDialog.dismiss();
  227.                                 Toast.makeText(SplashActivity.this, "更新失敗", Toast.LENGTH_SHORT).show();
  228.                                 loadMainUI();
  229.                         }
  230.                 }
  231.                
  232.         }

  233. }

複製代碼
ps:上麵那個com.xiaobin.security.ui.SplashActivity類裏麵的那個handler是我為讓用戶清楚看到那個啟動界麵而設置的,不然,因為都是在同一個局域網裏麵,一下子就會完成那個更新的判斷的啦,如果不用更新,那就會看不到那個啟動界麵的啦,所以為了我們能夠看到那個界麵,我讓它休眠了2秒鍾,才進行與服務器更新的,所以有什麼不明白的也可以問一下
就這樣子,我們就把啟動界麵時候,從服務器獲取最新版的內容,然後提示用戶是不是要更新的處理弄好啦! 既然啟動界麵弄好啦,那麼,我們接下來,肯定是要做我們最重要的主界麵啦 我們的主界麵用到的是一個叫GridView的控件,它需要一個adapter,所以我們也要新建一個adapter的類 下麵是主界麵的布局文件
  1. <?xml version="1.0" encoding="utf-8"?>
  2. <LinearLayout xmlns:andro
  3.     android:layout_width="match_parent"
  4.     android:layout_height="match_parent"
  5.     android:orientation="vertical" >
  6.    
  7.     <LinearLayout
  8.         android:layout_width="match_parent"
  9.         android:layout_height="40dip"
  10.         android:gravity="center_vertical|center_horizontal"
  11.         android:background="@drawable/title_background"
  12.         android:orientation="vertical">
  13.         
  14.         <TextView
  15.             android:layout_width="wrap_content"
  16.             android:layout_height="wrap_content"
  17.             android:textColor="@android:color/white"
  18.             android:textSize="22sp"
  19.             android:text="@string/main"/>
  20.         
  21.     </LinearLayout>
  22.    
  23.     <GridView
  24.         android:
  25.         android:layout_width="match_parent"
  26.         android:layout_height="match_parent"
  27.         android:verticalSpacing="8dip"
  28.         android:numColumns="2" />

  29. </LinearLayout>

複製代碼
下麵是adapter類的代碼com.xiaobin.security.adapter.MainUIAdapter
  1. package com.xiaobin.security.adapter;

  2. import android.content.Context;
  3. import android.content.SharedPreferences;
  4. import android.view.LayoutInflater;
  5. import android.view.View;
  6. import android.view.ViewGroup;
  7. import android.widget.BaseAdapter;
  8. import android.widget.ImageView;
  9. import android.widget.TextView;

  10. import com.xiaobin.security.R;

  11. public class MainUIAdapter extends BaseAdapter
  12. {
  13.         private static final String[] NAMES = new String[] {"手機防盜", "通訊衛士", "軟件管理", "流量管理", "任務管理", "手機殺毒",
  14.                         "係統優化", "高級工具", "設置中心"};
  15.         
  16.         private static final int[] ICONS = new int[] {R.drawable.widget01, R.drawable.widget02, R.drawable.widget03,
  17.                         R.drawable.widget04, R.drawable.widget05, R.drawable.widget06, R.drawable.widget07,
  18.                         R.drawable.widget08, R.drawable.widget09};
  19.         
  20.         //聲明成靜態,起到一定的優化作用,關於adapter還有別的優化方法的,有機會我們再說
  21.         private static ImageView imageView;
  22.         private static TextView textView;
  23.         
  24.         private Context context;
  25.         private LayoutInflater inflater;
  26.         private SharedPreferences sp;
  27.         
  28.         public MainUIAdapter(Context context)
  29.         {
  30.                 this.context = context;
  31.                 inflater = LayoutInflater.from(this.context);
  32.                 sp = context.getSharedPreferences("config", Context.MODE_PRIVATE);
  33.         }

  34.         @Override
  35.         public int getCount()
  36.         {
  37.                 return NAMES.length;
  38.         }

  39.         @Override
  40.         public Object getItem(int position)
  41.         {
  42.                 return position;
  43.         }

  44.         @Override
  45.         public long getItemId(int position)
  46.         {
  47.                 return position;
  48.         }

  49.         @Override
  50.         public View getView(int position, View convertView, ViewGroup parent)
  51.         {
  52.                 View view = inflater.inflate(R.layout.main_item, null);
  53.                 imageView = (ImageView) view.findViewById(R.id.iv_main_icon);
  54.                 textView = (TextView) view.findViewById(R.id.tv_main_name);
  55.                 imageView.setImageResource(ICONS[position]);
  56.                 textView.setText(NAMES[position]);
  57.                         
  58.                 if(position == 0)
  59.                 {
  60.                         String name = sp.getString("lostName", "");
  61.                         if(!name.equals(""))
  62.                         {
  63.                                 textView.setText(name);
  64.                         }
  65.                 }
  66.                
  67.                 return view;
  68.         }
  69.         
  70. }

複製代碼
adapter也寫好啦,那麼接下來,肯定就是我們的主界麵啦com.xiaobin.security.ui.MainActivity
  1. package com.xiaobin.security.ui;

  2. import com.xiaobin.security.R;
  3. import com.xiaobin.security.adapter.MainUIAdapter;

  4. import android.app.Activity;
  5. import android.app.AlertDialog;
  6. import android.content.Context;
  7. import android.content.DialogInterface;
  8. import android.content.SharedPreferences;
  9. import android.content.SharedPreferences.Editor;
  10. import android.os.Bundle;
  11. import android.view.View;
  12. import android.widget.AdapterView;
  13. import android.widget.EditText;
  14. import android.widget.TextView;
  15. import android.widget.Toast;
  16. import android.widget.AdapterView.OnItemLongClickListener;
  17. import android.widget.GridView;
  18. import android.widget.AdapterView.OnItemClickListener;

  19. public class MainActivity extends Activity implements OnItemClickListener
  20. {
  21.         private GridView gridView;
  22.         
  23.         private MainUIAdapter adapter ;
  24.         private SharedPreferences sp;

  25.         @Override
  26.         protected void onCreate(Bundle savedInstanceState)
  27.         {
  28.                 super.onCreate(savedInstanceState);
  29.                 setContentView(R.layout.main);
  30.                
  31.                 sp = this.getSharedPreferences("config", Context.MODE_PRIVATE);
  32.                 gridView = (GridView) findViewById(R.id.gv_main);
  33.                 adapter = new MainUIAdapter(this);
  34.                 gridView.setAdapter(adapter);
  35.                 gridView.setOnItemClickListener(this);
  36.                 gridView.setOnItemLongClickListener(new OnItemLongClickListener()
  37.                 {
  38.                         @Override
  39.                         public boolean onItemLongClick(AdapterView<?> parent, final View view, int position, long id)
  40.                         {
  41.                                 if(position == 0)        //這個是因為,如果我們的手機被盜了,用戶一看到第一個手機防盜,那樣肯定會先卸載我們的程序的,所以我們在手機防盜這個item裏麵,設置了一個重命名的功能
  42.                                 {
  43.                                         AlertDialog.Builder builder = new AlertDialog.Builder(MainActivity.this);
  44.                                         builder.setTitle("設置");
  45.                                         builder.setMessage("請輸入要理性的名稱");
  46.                                         final EditText et = new EditText(MainActivity.this);
  47.                                         et.setHint("新名稱");
  48.                                         builder.setView(et);
  49.                                         builder.setPositiveButton(android.R.string.ok, new DialogInterface.OnClickListener()
  50.                                         {
  51.                                                 @Override
  52.                                                 public void onClick(DialogInterface dialog, int which)
  53.                                                 {
  54.                                                         String name = et.getText().toString();
  55.                                                         if(name.equals(""))
  56.                                                         {
  57.                                                                 Toast.makeText(MainActivity.this, "輸入內容不能為空", Toast.LENGTH_SHORT).show();
  58.                                                         }
  59.                                                         else
  60.                                                         {
  61.                                                                 Editor editor = sp.edit();
  62.                                                                 editor.putString("lostName", name);
  63.                                                                 editor.commit();
  64.                                                                
  65.                                                                 TextView tv = (TextView) view.findViewById(R.id.tv_main_name);
  66.                                                                 tv.setText(name);
  67.                                                                 adapter.notifyDataSetChanged();
  68.                                                         }
  69.                                                 }
  70.                                         });
  71.                                         builder.setNegativeButton(android.R.string.cancel, new DialogInterface.OnClickListener()
  72.                                         {
  73.                                                 @Override
  74.                                                 public void onClick(DialogInterface dialog, int which)
  75.                                                 {
  76.                                                         // TODO Auto-generated method stub
  77.                                                         
  78.                                                 }
  79.                                         });
  80.                                         builder.create().show();
  81.                                 }
  82.                                 return false;
  83.                         }
  84.                 });
  85.         }

  86.         @Override
  87.         public void onItemClick(AdapterView<?> parent, View view, int position, long id)
  88.         {
  89.                 switch(position)
  90.                 {
  91.                         case 0 : //手機防盜
  92.                                 break;
  93.                                 
  94.                         case 1 : //通訊衛士
  95.                                 break;
  96.                                 
  97.                         case 2 : //軟件管理
  98.                                 break;
  99.                                 
  100.                         case 3 : //流量管理
  101.                                 break;
  102.                                 
  103.                         case 4 : //任務管理
  104.                                 break;
  105.                                 
  106.                         case 5 : //手機殺毒
  107.                                 break;
  108.                                 
  109.                         case 6 : //係統優化
  110.                                 break;
  111.                                 
  112.                         case 7 : //高級工具
  113.                                 break;
  114.                                 
  115.                         case 8 : //設置中心
  116.                                 break;
  117.                                 
  118.                         default :
  119.                                 break;
  120.                 }
  121.         }

  122. }

複製代碼
上麵的那個重命名的功能,是我們把重新命名的名字,存放到一個SharedPreferences裏麵的,然後下一次啟動的時候,就先檢查裏麵有沒有對應的值,沒有就用默認的,有就用用戶自己命名的 好啦,今天的代碼基本上寫得差不多的啦,現在隻剩下添加權限啦,因為要讀取sd卡,所以要添加相應的權限
  1. <uses-permission android:name="android.permission.MOUNT_UNMOUNT_FILESYSTEMS" />
  2.     <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
複製代碼
現在就可以測試啦,記得要把服務器打開喔,還要昨天說的那個服務器的目錄下麵放一個apk喔,並把那個update.xml修改成與現在這個版本不一致的喔,不然不會更新的,不明白的可以看看下麵的圖 注意一下名稱的對應 好啦,今天就說到這裏啦 Security_03_完成app更新的邏輯和主界麵.rar(1.67 MB, 下載次數: 1115)

最後更新:2017-04-03 14:54:29

  上一篇:go 仿uc下部彈出菜單
  下一篇:go 奇虎360“Ctrl兩下”:有用嗎?