主要知识点:
1、项目的代码组织结构
2、PackageManager 获取应用程序的版本号;
3、URL HttpUrlConntion
4、子线程 handler + message
5、Json解析
6、Intent 显示意图
7、Alterdialog
8、两种上下文
9、下载--FinalHttp
10、安装apk
11、应用程序的签名;
12、ListView gridView 数据适配
13、滚动的TextView
14、自定义组合控件 实现关闭自动更新;
15、自定义属性
参考文档下载地址:http://download.csdn.net/detail/itjavawfc/8232073
参考源代码下载地址:http://download.csdn.net/detail/itjavawfc/8232083
项目最终运行界面效果:
自己第一天主要学习内容总结:
1)启动页面结合设计到检查版本然后判断是否升级【checkUpdate()】:里面根据网络请求通过Message、Handler消息传递机制传递消息,对话框展现是否升级知识,自定义主题实现全屏和4.1以后新的对话框效果,利用系统Intent实习APK安装。
代码如下:
public class SplashActivity extends Activity { protected static final String TAG = "SplashActivity"; protected static final int ENTR_HOME = 1; protected static final int SHOW_UPDATE_DIALOG = 0; protected static final int NETWORK_ERROR = 3; protected static final int JSON_ERROR =4 ; protected static final int URL_ERROR = 2; private TextView tv_splash_version; private String description; private TextView tv_update_info; /* * 对应新版本的下载地址 */ private String apkurl; private SharedPreferences sp; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_splash); sp=getSharedPreferences("config", MODE_PRIVATE); tv_splash_version=(TextView) findViewById(R.id.tv_splash_version); tv_splash_version.setText("版本号"+getVersionName()); tv_update_info=(TextView) findViewById(R.id.tv_update_info); boolean update=sp.getBoolean("dupdate", false); if(update){ //检查升级 checkUpdate(); }else{ //自动升级已经关闭了 handler.postDelayed(new Runnable(){ @Override public void run() { // TODO Auto-generated method stub enterHome(); } }, 2000); } AlphaAnimation aa=new AlphaAnimation(0.3f, 1.0f); aa.setDuration(500); findViewById(R.id.rl_root_splash).startAnimation(aa); } Handler handler=new Handler(){ @Override public void handleMessage(Message msg) { // TODO Auto-generated method stub super.handleMessage(msg); switch(msg.what){ case SHOW_UPDATE_DIALOG://显示升级的对话框 Log.i(TAG,"显示升级的对话框"); showUpdateDialot(); break; case ENTR_HOME: //进入主页面 enterHome(); break; case URL_ERROR: //URL 错误 enterHome(); Toast.makeText(getApplicationContext(), "URL错误", 0).show(); break; case NETWORK_ERROR: //网络异常 Toast.makeText(getApplicationContext(), "网络异常", 0).show(); enterHome(); break; case JSON_ERROR: //JSON解析出错 Toast.makeText(SplashActivity.this, "JSON解析错误", 0).show(); enterHome(); break; default: break; } } }; /* * 检查是否有版本升级,如果有就升级 */ private void checkUpdate() { new Thread(){ public void run(){ Message mes=Message.obtain(); long startTime=System.currentTimeMillis(); //URLhttp://192.168.1.105:8080/MobileSafe.apk try{ URL url=new URL(getString(R.string.serverurl)); //联网 HttpURLConnection conn=(HttpURLConnection) url.openConnection(); conn.setRequestMethod("GET"); conn.setConnectTimeout(5000); int code=conn.getResponseCode(); if(code==200){ //联网成功 InputStream is= conn.getInputStream(); //把流转成String String result=StreamTools.readFromStream(is); System.out.println("联网成功"); Log.i(TAG,"联网成功过呢。。"+result); //json解析 JSONObject obj=new JSONObject(result); //得到服务器的版本信息 String version=(String) obj.get("verson"); description=(String) obj.get("description"); apkurl=(String) obj.get("apkurl"); //校验是否有新版本 if(getVersionName().equals(version)){ //版本一直,没有新版本,进入主页面 mes.what=ENTR_HOME; }else{ //有新版本弹出升级对话框 mes.what=SHOW_UPDATE_DIALOG; } } }catch(MalformedURLException e){ mes.what=URL_ERROR; e.printStackTrace(); } catch (IOException e) { mes.what=NETWORK_ERROR; e.printStackTrace(); } catch (JSONException e) { mes.what=JSON_ERROR; e.printStackTrace(); }finally{ long endTime=System.currentTimeMillis(); //我们花了多少时间 long dTime=endTime-startTime; //界面停留2s种 if(dTime<2000){ try { Thread.sleep(2000-dTime); } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } } handler.sendMessage(mes); } }; }.start(); } /* * 弹出升级对话框 */ private void showUpdateDialot() { //this=activity.class AlertDialog.Builder builder=new Builder(this); builder.setTitle("提示升级"); //设置此属性,让对话框外的点击事件不可触发 builder.setCancelable(false); //强制升级 //点击返回键时触发 builder.setOnCancelListener(new OnCancelListener(){ @Override public void onCancel(DialogInterface dialog) { //进入主页面 enterHome(); dialog.dismiss(); } }); builder.setMessage(description); builder.setPositiveButton("立刻升级", new OnClickListener(){ @Override public void onClick(DialogInterface dialog, int which) { //下载APK,bignqie tihuan if(Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED)){ //sd卡存在 FinalHttp finalhttp=new FinalHttp(); finalhttp.download(apkurl, Environment.getExternalStorageDirectory().getAbsolutePath()+"/mobilesafe2.0.apk", new AjaxCallBack<File>(){ @Override public void onFailure(Throwable t, int errorNo, String strMsg) { t.printStackTrace(); Toast.makeText(getApplicationContext(), "下载失败", 1).show(); super.onFailure(t, errorNo, strMsg); } @Override public void onLoading(long count, long current) { super.onLoading(count, current); tv_update_info.setVisibility(View.VISIBLE); //当前下载进度 int progress=(int)(current*100/count); tv_update_info.setText("下载进度:"+progress+"%"); } @Override public void onSuccess(File t) { // TODO Auto-generated method stub super.onSuccess(t); installAPK(t); } /* * 安装APK */ private void installAPK(File t) { Intent intent=new Intent(); intent.setAction("android.intent.action.VIEW"); intent.addCategory("android.intent.category.DEFAULT"); intent.setDataAndType(Uri.fromFile(t), "application/vnd.android.package-archive"); startActivity(intent); } }); }else{ Toast.makeText(getApplicationContext(), "没有sdcard,请安装上再试", 0).show(); return ; } } }); builder.setNegativeButton("下次再说", new OnClickListener(){ @Override public void onClick(DialogInterface dialog, int which) { dialog.dismiss();//对话框消掉 enterHome();//进入主页面 } }); builder.show(); } protected void enterHome() { Intent intent=new Intent(this,HomeActivity.class); startActivity(intent); //关闭当前页面 finish(); } /* * 得到应用程序的版本名称 */ private String getVersionName(){ //用来管理手机的APK PackageManager pm=getPackageManager(); //得到指定apk的功能的清单文件 try { PackageInfo info=pm.getPackageInfo(getPackageName(), 0); return info.versionName; } catch (Exception e) { // TODO Auto-generated catch block e.printStackTrace(); return ""; } } }
2)进入主页HomeActivity
复习了GridLayout布局结合Adapter的运用,效果就是上面的图所示,在它的布局文件中学习了一个自定义可滚动的TextView,非常有意思。
public class HomeActivity extends Activity { private GridView list_home; private MyAdapter adapter; private static String[] names={ "手机防盗","通讯卫士","软件管理", "进程管理","流量统计","手机杀毒", "缓存清理","高级工具","设置中心" }; private static int[] ids={ R.drawable.safe,R.drawable.callmsgsafe,R.drawable.app, R.drawable.taskmanager,R.drawable.netmanager,R.drawable.trojan, R.drawable.sysoptimize,R.drawable.atools,R.drawable.settings }; protected void onCreate(Bundle savedInstanceState) { // TODO Auto-generated method stub super.onCreate(savedInstanceState); setContentView(R.layout.activity_home); list_home=(GridView) findViewById(R.id.list_home); adapter=new MyAdapter(); list_home.setAdapter(adapter); list_home.setOnItemClickListener(new OnItemClickListener() { @Override public void onItemClick(AdapterView<?> parent, View view, int position, long id) { // TODO Auto-generated method stub switch(position){ case 8://进入设置中心 Intent intent=new Intent(HomeActivity.this,SettingActivity.class); startActivity(intent); break; default: break; } } }); } private class MyAdapter extends BaseAdapter{ //屏幕要显示多少个 @Override public int getCount() { // TODO Auto-generated method stub return names.length; } //点击的时候返回某个对象 @Override public Object getItem(int position) { // TODO Auto-generated method stub return null; } @Override public long getItemId(int position) { // TODO Auto-generated method stub return 0; } @Override public View getView(int position, View convertView, ViewGroup parent) { // TODO Auto-generated method stub View view=View.inflate(HomeActivity.this, R.layout.list_item_home, null); ImageView iv_item=(ImageView) view.findViewById(R.id.iv_item); TextView tv_item=(TextView) view.findViewById(R.id.tv_item); tv_item.setText(names[position]); iv_item.setImageResource(ids[position]); return view; } } }
<com.example.mobilesafe.ui.FocusedTextView android:focusableInTouchMode="true" android:singleLine="true" android:ellipsize="marquee" android:textSize="18sp" android:text="最新的手机卫士,快来下载,下载就好了" android:layout_width="fill_parent" android:layout_height="wrap_content" />
3)在SettingActivity中学习了通过自定义类来自定义布局,SharedPreferences来保存数据,在布局文件中自定义属性。
public class SettingActivity extends Activity { private SettingItemView siv_update; private SharedPreferences sp; @Override protected void onCreate(Bundle savedInstanceState) { // TODO Auto-generated method stub super.onCreate(savedInstanceState); setContentView(R.layout.activity_setting); sp=getSharedPreferences("config", MODE_PRIVATE); siv_update=(SettingItemView) findViewById(R.id.siv_update); boolean update=sp.getBoolean("update", false); if(update){ //自动升级已经开启 siv_update.setChecked(true); }else{ //自动升级已经关闭 siv_update.setChecked(false); } siv_update.setOnClickListener(new OnClickListener() { @Override public void onClick(View v) { Editor editor=sp.edit(); //判断是否选中 //已经打开自动升级 if(siv_update.isChecked()){ siv_update.setChecked(false); editor.putBoolean("update", false); }else{ //没有打开自动升级 siv_update.setChecked(true); editor.putBoolean("update", true); } editor.commit(); } }); } }