«

[安卓]手机管家(二)splash续

时间:2024-3-2 18:19     作者:韩俊     分类: Android


继续

之前对比了用户和服务器端版本,当可升级的时候,要做进一步处理,而不仅仅是toast一个"有新版本"

case MSG_VERSION_DIFF:
                //弹出通知
                Builder builder = new Builder(SplashActivity.this);
                builder.setTitle("发现新版本");
                builder.setMessage(description);
                //需要实现一个MyDialogOnclickListener传进来
                builder.setPositiveButton("升级",new MyDialogOnclickListener());
                builder.setNegativeButton("取消",new MyDialogOnclickListener());
                builder.show();
                break;              
             default:
                 break;
            }
        };
    };

    class MyDialogOnclickListener implements OnClickListener{
        @Override
        public void onClick(DialogInterface dialog, int which) {
            // TODO Auto-generated method stub

        }   
    }


继续~对于点击事件,需要判断,确认就直接下载,取消就回去

确认:下载,这里用之前做的app,去info里改下信息,并将apk放到root里

涉及到文件的保存,这里用AsyncHttpClient,需要loopj,拷贝过来后,base里有问题,去掉原有导包重新来

class MyDialogOnclickListener implements OnClickListener{
        @Override
        public void onClick(DialogInterface dialog, int which) {
            // TODO Auto-generated method stub
            if(which == DialogInterface.BUTTON_POSITIVE){
                //用户点击了确认下载。这里开始去下载最新版本
                AsyncHttpClient asyncHttpClient = new AsyncHttpClient();
                //需要一个handler
                asyncHttpClient.get(downloadurl, new MyDownloadHandler());
            }else{
                //用户点击了取消下载。这时候应该跳入到主界面

            }       
        }   
    }
    class MyDownloadHandler extends AsyncHttpResponseHandler{

        @Override
        public void onSuccess(int statusCode, Header[] headers,
                byte[] responseBody) {
            // TODO Auto-generated method stub

        }

        @Override
        public void onFailure(int statusCode, Header[] headers,
                byte[] responseBody, Throwable error) {
            // TODO Auto-generated method stub

        }       
    }


下载并安装:

@Override
        public void onSuccess(int statusCode, Header[] headers,
                byte[] responseBody) {
            // TODO Auto-generated method stub
            File file = new File("storage/sdcard/mobilesafe.apk");
            try {
                FileOutputStream fos = new FileOutputStream(file);
                fos.write(responseBody);
                fos.close();
            } catch (FileNotFoundException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            } catch (IOException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }       
            installapk(file);
        }
        private void installapk(File file) {
            // TODO Auto-generated method stub
            Intent intent = new Intent("android.intent.action.VIEW");
            intent.setDataAndType(Uri.fromFile(file),   "application/vnd.android.package-archive");
            startActivity(intent);
        }


此时走起一个发现解析错误,需要写权限

OK~能够安装

但是这个还有一个方法需要添加,显示安装进度,需要一个view,在splash的layout里加入

 <TextView
        android:id="@+id/tv_splash_downloadprogress"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_centerHorizontal="true"
        android:layout_alignParentBottom="true"
        android:textColor="#000000" />


oncreate里初始化

@Override
        public void onProgress(int bytesWritten, int totalSize) {
            // TODO Auto-generated method stub
            super.onProgress(bytesWritten, totalSize);
            tv_splash_downloadprogress.setText(bytesWritten+"/"+totalSize);
        }


bin目录下的apk没有签名,不能发布到市场上,小范围安装可以

关于签名,导出整个项目时,

没有签名,系统有一个测试签名,在windows下的preference的build里有一个路径

这个可以填到location里,但是还需要一个password,一般就是android

自己创建的可以和系统的类似,改一下最后的文件名就好,第二次填密码那要注意填有效期,必须能达到2033年

发布不同版本时,首选是包名必须相同,其次是签名一致,所以在升级时要用到之前的签名,当然manifest里的版本号也要改下~

继续,当可以升级,用户点击取消则应该跳到homeactivity,要完成这个activity和layout

else{
                //用户点击了取消下载。这时候应该跳入到主界面
                enterHome();
            }       
        }   
    }
    private void enterHome() {
        Intent intent = new Intent(SplashActivity.this, HomeActivity.class);
        startActivity(intent);
    }


homeactivity

import android.app.Activity;
import android.os.Bundle;
import android.widget.TextView;

public class HomeActivity extends Activity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        // TODO Auto-generated method stub
        super.onCreate(savedInstanceState);

        TextView tv = new TextView(this);
        tv.setText("我是主界面");
        setContentView(tv);

    }
}

manifest里要声明下

注意handler里,版本相同时,进入home

当出现意外时,比如服务器挂了,这个时候应该有相应处理,这时不能在异常处理里用enterhome(),因为主线程不能操作UI,所以应该利用handler发消息

注意,由于这里涉及多种消息的发送,其实可以做一些优化,把msg的声明拿出来,添加一个finally,在里面发消息,而各种状况里只需说明是哪种消息即可

异常里的消息

并且提示错误代码,给出反馈

有一个细节,当初设了一个notitle,但是背景成了黑色,现在要调成白色并且依然notitle,那么可以在values里的style加一个notitle条目,再在manifest里改主题

取消后,带参数的跳转

@Override
    protected void onActivityResult(int requestCode, int resultCode, Intent data) {
        // TODO Auto-generated method stub
        super.onActivityResult(requestCode, resultCode, data);

        if (requestCode==100 && resultCode==RESULT_CANCELED) {
            enterHome();
        }
    }

这里有两个取消,一个是直接不升级,进入home,另一个是点了升级,但是在安装的时候又选择不安张,此时也应该可以跳转到home

在安装里应该是一个带参数的跳转


要实现进入下载或者homeactivity后点back键返回九宫格,则需要销毁这个activity,这样就能回到栈底

注意IP地址改动,服务器端的info文件里的地址也要改动。。

在超时等待的时候,加一个小圆圈转动,提升体验~需要ProgressBar

<ProgressBar
           android:layout_width="wrap_content"
           android:layout_height="wrap_content"
           android:layout_below="@id/tv_splash_version"
           android:layout_marginTop="5dp"
           android:layout_centerHorizontal="true"/>
</RelativeLayout>


这一段的完整代码

import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.HttpURLConnection;
import java.net.MalformedURLException;
import java.net.URL;

import org.apache.http.Header;
import org.json.JSONException;
import org.json.JSONObject;

import com.loopj.android.http.AsyncHttpClient;
import com.loopj.android.http.AsyncHttpResponseHandler;

import utils.WebUtils;
import android.app.Activity;
import android.app.AlertDialog.Builder;
import android.net.Uri;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.content.DialogInterface;
import android.content.DialogInterface.OnClickListener;
import android.content.Intent;
import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
import android.content.pm.PackageManager.NameNotFoundException;
import android.widget.TextView;
import android.widget.Toast;

public class SplashActivity extends Activity {
    protected static final int MSG_VERSION_SAME =0;
    protected static final int MSG_VERSION_DIFF =1;
    protected static final int MSG_ERROR_URLMALFORMED = 10;
    protected static final int MSG_ERROR_JSON = 20;
    protected static final int MSG_ERROR_IO = 30;
    private String description;
    private String downloadurl;
    private String version;
    private TextView tv_splash_downloadprogress;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_splash);
        TextView tv_splash_version = (TextView) findViewById(R.id.tv_splash_version);
        //上面的声明要注意是空字符串,而不是null
        tv_splash_version.setText("版本: "+getVersion());
        //解析下载进度
        tv_splash_downloadprogress = (TextView) findViewById(R.id.tv_splash_downloadprogress);
        //获取服务器端版本号
        Update();
    }

    Handler myHandler = new Handler(){
        public void handleMessage(android.os.Message msg){
            switch(msg.what){
            case MSG_VERSION_SAME:
                //进入主界面
                enterHome();
                break;
            case MSG_VERSION_DIFF:
                //弹出通知
                Builder builder = new Builder(SplashActivity.this);
                builder.setTitle("发现新版本");
                builder.setMessage(description);
                //需要实现一个MyDialogOnclickListener传进来
                builder.setPositiveButton("升级",new MyDialogOnclickListener());
                builder.setNegativeButton("取消",new MyDialogOnclickListener());
                builder.show();
                break;  
            case MSG_ERROR_IO:
                 Toast.makeText(getApplicationContext(), "错误代码"+MSG_ERROR_IO, 1).show();
                 enterHome();
                 break;
            case MSG_ERROR_JSON:
                 Toast.makeText(getApplicationContext(), "错误代码"+MSG_ERROR_JSON, 1).show();
                 enterHome();
                 break;
            case MSG_ERROR_URLMALFORMED:
                 Toast.makeText(getApplicationContext(), "错误代码"+MSG_ERROR_URLMALFORMED, 1).show();
                 enterHome();
                break;
             default:
                 break;
            }
        };
    };

    class MyDialogOnclickListener implements OnClickListener{
        @Override
        public void onClick(DialogInterface dialog, int which) {
            // TODO Auto-generated method stub
            if(which == DialogInterface.BUTTON_POSITIVE){
                //用户点击了确认下载。这里开始去下载最新版本
                AsyncHttpClient asyncHttpClient = new AsyncHttpClient();
                //需要一个handler
                asyncHttpClient.get(downloadurl, new MyDownloadHandler());
            }else{
                //用户点击了取消下载。这时候应该跳入到主界面
                enterHome();
            }       
        }   
    }
    private void enterHome() {
        Intent intent = new Intent(SplashActivity.this, HomeActivity.class);
        startActivity(intent);
        //要实现点back键返回开始的activity,则需要销毁这个activity,这样就能回到栈底
        finish();
    }
    //进入安装后用户又取消,这时候应该能直接进入home,这是带参数值的跳转
    @Override
    protected void onActivityResult(int requestCode, int resultCode, Intent data) {
        // TODO Auto-generated method stub
        super.onActivityResult(requestCode, resultCode, data);
        if (requestCode==100 && resultCode==RESULT_CANCELED) {
            enterHome();
        }
    }
    class MyDownloadHandler extends AsyncHttpResponseHandler{

        @Override
        public void onSuccess(int statusCode, Header[] headers,
                byte[] responseBody) {
            // TODO Auto-generated method stub
            File file = new File("storage/sdcard/mobilesafe.apk");
            try {
                FileOutputStream fos = new FileOutputStream(file);
                fos.write(responseBody);
                fos.close();
            } catch (FileNotFoundException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            } catch (IOException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }       
            installapk(file);
        }
        private void installapk(File file) {
            // TODO Auto-generated method stub
            Intent intent = new Intent("android.intent.action.VIEW");
            intent.setDataAndType(Uri.fromFile(file),   "application/vnd.android.package-archive");
            startActivityForResult(intent,100);
        }
        @Override
        public void onProgress(int bytesWritten, int totalSize) {
            // TODO Auto-generated method stub
            super.onProgress(bytesWritten, totalSize);
            tv_splash_downloadprogress.setText(bytesWritten+"/"+totalSize);
        }
        @Override
        public void onFailure(int statusCode, Header[] headers,
                byte[] responseBody, Throwable error) {
            // TODO Auto-generated method stub

        }       
    }
    private void Update() {
        // TODO Auto-generated method stub
        new Thread(new Runnable(){

            @Override
            public void run() {
                String path = "http://192.168.3.100/version_info.json";
                Message msg = myHandler.obtainMessage();
                try {
                    URL url = new URL(path);
                    HttpURLConnection conn = (HttpURLConnection) url.openConnection();
                    conn.setReadTimeout(5000);
                    conn.setConnectTimeout(2000); //实际发布版本的时候,超时实际最好稍微长一些
                    conn.setRequestMethod("GET");
                    conn.connect();
                    if (conn.getResponseCode()==200) {
                        InputStream is= conn.getInputStream();
                        String jsontext = WebUtils.gettextFromInputStream(is, null);
                        JSONObject jsonObject = new JSONObject(jsontext);           
                        version = jsonObject.getString("version");   
                        description = jsonObject.getString("description");
                        downloadurl = jsonObject.getString("downloadurl");
                        System.out
                            .println("SplashActivity.Update().new Runnable() {...}.run()" 
                            +version
                            +description
                            +downloadurl);                      
                        if(version.equals(getVersion())){
                            //版本一致则进入主页                     
                            msg.what = MSG_VERSION_SAME;
                        }else{
                            //不一致则弹出dialog告诉用户,此时需要handler来处理                       
                            msg.what = MSG_VERSION_DIFF;
                        }
                    }
                } catch (MalformedURLException e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                    msg.what = MSG_ERROR_URLMALFORMED;
                } catch (IOException e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                    msg.what = MSG_ERROR_IO;
                }catch (JSONException e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                    msg.what = MSG_ERROR_JSON;
                }finally{               
                    myHandler.sendMessage(msg);
                }
            }
        }).start();
    }

    private String getVersion() {
        //获取版本号
        PackageManager pm = getPackageManager();        
        PackageInfo packageinfo;
        String version="";
        try {
            //第一个参数应该为manifest里的包名而不是工程里的包名,后直接以方法获取~
            packageinfo = pm.getPackageInfo(getPackageName(), 0);
            version = packageinfo.versionName;
        } catch (NameNotFoundException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        return version;
    }
}


标签: android

热门推荐