记录安卓下开发下载安装功能

下面文章转载自:http://blog.csdn.net/MyDreamIsNotNull/article/details/53896034

其中有几个我遇到的问题记录一下:

1、新建安卓工程:File->New->Android Application Project

2、把下面的代码放入工程

3、编译发包

4、发现unity调用后不能正常下载安装,把AsyncTaskRunnable的两句代码注释掉,才可以正常下载安装,具体原因暂未找到。

mNotification.icon = R.drawable.ic_launcher;//设置下载进度的icon

mNotification.tickerText = mContext.getResources().getString(R.string.app_name); //设置下载进度的title


最近在学习android的知识,因为功能的需要,unity3d 要和android交互。最近公司的项目中遇到了unity3d 开发的app需要更新和自动安装的功能,但是使用unity3d是实现不了这样的功能的。这个时候就想到使用android原有的知识进行开发,然后打成jar包,导成插件,放到unity3d中去调用。

     1.首先在eclipse或者android studio 中开发原有的app下载更新的功能。

      *我这里是以eclipse为例开发的。

        首先在eclipse中导入unity3d的jar包,class.jar,这里的class.jar在unity3d安装目录下,如下:D:\Unity5.2.3SetUp\Editor\Data\PlaybackEngines\androidplayer\Variations\il2cpp\Development\Classes

然后就要写相应的代码了,android的原有下载更新网上也有很多但是没有结合Untiy3d。具体的代码如下,首先要引入import com.unity3d.player.UnityPlayer,然后activity继承UnityPlayerActivity 

package com.example.downapk;
import java.io.File;


import com.unity3d.player.UnityPlayer;
import com.unity3d.player.UnityPlayerActivity;


import android.net.Uri;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.app.Activity;
import android.content.Intent;
import android.util.Log;
import android.view.Menu;


public class MainActivity extends UnityPlayerActivity 
{
     private static String tag = "MainActivity";
private Handler mHandler = new Handler()
{
public void handleMessage(Message msg) {
super.handleMessage(msg);
switch (msg.what) {
case 1:
OpenFile();
break;
default:
break;
}
}
};  
     
private AsyncTaskUtil mDownloadAsyncTask;  
public float size;
public static MainActivity instance;
public static MainActivity getInstance()
{
return instance;
}
     


     
   @Override  
   protected void onCreate(Bundle savedInstanceState) {  
       super.onCreate(savedInstanceState);  
       instance = this;  
   }  
   public void SetSize(float size)
   {
    size = this.size;
    Log.d(tag, this.size+"");
   }
   public void StartLoad(String httpUrl, String apkName)
   {
    mDownloadAsyncTask = new AsyncTaskUtil(MainActivity.this, mHandler);  
       mDownloadAsyncTask.execute(httpUrl, apkName);//必须传入两个参数——参数1:url;参数2:文件名(可以为null)
   }

   private void OpenFile() {
String str = "/test.apk";
String fileName = mDownloadAsyncTask.getFolderPath() + str;
File file = new File(fileName);
if (!file.exists()) {
Log.d("URL", "fileName:" + fileName);
}
Intent intent = new Intent(Intent.ACTION_VIEW);
intent.setDataAndType(Uri.fromFile(file),
"application/vnd.android.package-archive");
Log.d("URL", "fileName:" + fileName);
startActivity(intent);
}
    
}

上面代码是主activity 表黑部分是要在unity中调用的。调用可以是一个按钮,例如

 AndroidJavaClass jc = new AndroidJavaClass("com.unity3d.player.UnityPlayer");
        AndroidJavaObject jo = jc.GetStatic<AndroidJavaObject>("currentActivity");
        jo.Call("StartLoad", ParentApp.getInstance().updateUrl, "test.apk");

这里是使用AsyncTask进行下载的,在后来可以看到下载进度。下面下载的代码。

package com.example.downapk;


import java.io.File;
import java.io.FileOutputStream;
import java.io.InputStream;
import java.net.URL;
import java.net.URLConnection;
import java.text.DecimalFormat;
import java.util.Timer;
import java.util.TimerTask;


import com.unity3d.player.UnityPlayer;


import android.content.Context;
import android.os.AsyncTask;
import android.os.Environment;
import android.os.Handler;
import android.util.Log;
import android.widget.Toast;


public class AsyncTaskUtil extends AsyncTask<String, Double, Boolean>
{
public static final String TAG = "AsyncTaskUtil";  
     
   public static final int NOTIFICATION_PROGRESS_UPDATE = 0x10;//用于更新下载进度的标志  
   public static final int NOTIFICATION_PROGRESS_SUCCEED = 0x11;//表示下载成功  
   public static final int NOTIFICATION_PROGRESS_FAILED = 0x12;//表示下载失败  
 
   //URL  
   private String mUrl;  
   //activity  
   private Context mContext;  
   //任务定时器  
   private Timer mTimer;  
   //定时任务  
   private TimerTask mTask;  
   //主线程传递过来的handler  
   private Handler  mHandler;  
   //所要下载的文件大小  
   private long mFileSize;  
   //已下载的文件大小  
   private long mTotalReadSize;  
   //AsyncTaskRunnable实现了Runnable接口,用于更新下载进度的显示  
   private AsyncTaskRunnable mRunnable;  
 
   //构造方法  
   public AsyncTaskUtil(Context context, Handler handler) {  
       mContext = context;  
       mHandler = handler;  
 
       mTimer = new Timer();  
       mTask = new TimerTask() {//在run方法中执行定时的任务  
           @Override  
           public void run() {  
               //size表示下载进度的百分比  
               float size = (float) mTotalReadSize * 100 / (float) mFileSize;  
               
               //通过AsyncTaskRunnable的setDatas方法下载的进度和状态(更新中、失败、成功)  
               mRunnable.setDatas(NOTIFICATION_PROGRESS_UPDATE, size);  
               //更新进度  
               mHandler.post(mRunnable);  
           }  
       };  
       mRunnable = new AsyncTaskRunnable(mContext);  
   }  
 
     
   // 执行耗时操作,params[0]为url,params[1]为文件名(空则写入null)  
   @Override  
   protected Boolean doInBackground(String... params) {  
         
       //任务定时器一定要启动  
       mTimer.schedule(mTask, 0, 500);  
         
       try {  
           mUrl = params[0];  
           //建立链接  
           URLConnection connection = new URL(mUrl).openConnection();  
           //获取文件大小  
           mFileSize = connection.getContentLength();  
           Log.d(TAG, "the count of the url content length is : " + mFileSize);  
 
           //获得输入流  
           InputStream is = connection.getInputStream();  
           //先建立文件夹  
           File fold = new File(getFolderPath());  
           if (!fold.exists()) {  
               fold.mkdirs();  
           }  
             
           String fileName = "";  
           //判断文件名:用户自定义或由url获得  
           if(params[1] != null){  
               fileName = params[1];  
           } else{  
               fileName = getFileName(params[0]);  
           }  
           //文件输出流  
           FileOutputStream fos = new FileOutputStream(new File(getFolderPath()  
                           + fileName));  
 
           byte[] buff = new byte[1024];  
           int len;  
           while ((len = is.read(buff)) != -1) {  
               mTotalReadSize += len;  
             
               MainActivity.getInstance().size  =  (float) mTotalReadSize * 100 / (float) mFileSize;
               DecimalFormat format = new DecimalFormat("0");
               UnityPlayer.UnitySendMessage("UI Root","GetSize",format.format(MainActivity.getInstance().size)+"");
               Log.d(TAG, "the count of the url content length is : " + MainActivity.getInstance().size);
              
               fos.write(buff, 0, len);  
           }  
           fos.flush();  
           fos.close();  
 
       } catch (Exception e) {  
           //异常,下载失败  
           mRunnable.setDatas(NOTIFICATION_PROGRESS_FAILED, 0);  
           //发送显示下载失败  
           mHandler.post(mRunnable);  
           if(mTimer != null && mTask != null){  
               mTimer.cancel();  
               mTask.cancel();  
           }  
           e.printStackTrace();  
           return false;  
       }  
       //下载成功  
       mRunnable.setDatas(NOTIFICATION_PROGRESS_SUCCEED, 0);  
       mHandler.post(mRunnable);  
       if(mTimer != null && mTask != null){  
           mTimer.cancel();  
           mTask.cancel();  
       }  
       return true;  
   }  
 
   //由url获得文件名  
   private String getFileName(String string) {  
       return string.substring(string.lastIndexOf("/") + 1);  
   }  
 
   //下载文件夹路径  
   public String getFolderPath() {  
       return Environment.getExternalStorageDirectory().toString() + "/AsyncTaskDownload/";  
   }  
 
 
   // doInBackground方法之前调用,初始化UI  
   @Override  
   protected void onPreExecute() {  
       super.onPreExecute();  
   }  
 
   // 在doInBackground方法之后调用  
   @Override  
   protected void onPostExecute(Boolean result) {  
       super.onPostExecute(result);  
       if (result) {  
           Toast.makeText(mContext, "Download Completed ! ", Toast.LENGTH_SHORT).show(); 
           mHandler.sendEmptyMessage(1);
       } else {  
           Toast.makeText(mContext, "Download Failed ! ", Toast.LENGTH_SHORT).show();  
       }  
   }  
 
   @Override  
   protected void onProgressUpdate(Double... values) {  
       super.onProgressUpdate(values);  
   }  
 
}

标红的地方是王unity中传的,我想要在unity中看到下载的进度,当时试了unity调用android都没有成功,后来想从android中往unity中传

UnityPlayer.UnitySendMessage("UI Root","GetSize",format.format(MainActivity.getInstance().size)+"");

UI Root 表示在untiy中有这样一个gameobject 在gameobject 上面挂着一个脚本,脚本中有一个方法名称为GetSize(),最后一个为要在unity中看到的进度。

在unity中的调用代码为

  public void GetSize(string str)
    {
        mSize = str;
        Debug.Log(mSize + "************************");
        text.text = "下载进度:  " + mSize + "%";
        if (mSize == "100")
        {
            Application.Quit();
        }
    }

这个方法不需要在别的地方调用的。

二:在后台显示下载进度,代码如下:

package com.example.downapk;
import java.text.DecimalFormat;


import android.app.Notification;
import android.app.NotificationManager;
import android.content.Context;
import android.util.Log;
import android.widget.RemoteViews;
import android.widget.Toast;


public class AsyncTaskRunnable implements Runnable{


public static final String TAG = "AsyncTaskRunnable";
//主线程的activity
private Context mContext;
//notification的状态:更新 or 失败 or 成功
private int mStatus;
//notification的下载比例
private float mSize;
//管理下拉菜单的通知信息
private NotificationManager mNotificationManager;
//下拉菜单的通知信息
private Notification mNotification;
//下拉菜单的通知信息的view
private RemoteViews mRemoteViews;
    //下拉菜单的通知信息的种类id
private static final int NOTIFICATION_ID = 1;

//设置比例和数据
public void setDatas(int status , float size) {
this.mStatus = status;
this.mSize = size;
}
//初始化
public AsyncTaskRunnable(Context context) {
this.mContext = context;
mNotificationManager = (NotificationManager) mContext.getSystemService(Context.NOTIFICATION_SERVICE);
//初始化下拉菜单的通知信息
mNotification = new Notification();
mNotification.icon = R.drawable.ic_launcher;//设置下载进度的icon
mNotification.tickerText = mContext.getResources().getString(R.string.app_name); //设置下载进度的title

mRemoteViews = new RemoteViews(mContext.getPackageName(), R.layout.down_notification);//对于RemoteView的使用,不懂的需要查找google
//mRemoteViews.setImageViewResource(R.id.id_download_icon, R.drawable.ic_launcher);
}

@Override
public void run() {//通过判断不同的状态:更新中/下载失败/下载成功 更新下拉菜单的通知信息
switch (mStatus) {
case AsyncTaskUtil.NOTIFICATION_PROGRESS_FAILED://下载失败
mNotificationManager.cancel(NOTIFICATION_ID);
break;


case AsyncTaskUtil.NOTIFICATION_PROGRESS_SUCCEED://下载成功
mRemoteViews.setTextViewText(R.id.id_download_textview, "Download completed ! ");
mRemoteViews.setProgressBar(R.id.id_download_progressbar, 100, 100, false);
mNotification.contentView = mRemoteViews;
mNotificationManager.notify(NOTIFICATION_ID, mNotification);
mNotificationManager.cancel(NOTIFICATION_ID);
Toast.makeText(mContext, "Download completed ! ", Toast.LENGTH_SHORT).show();
break;

case AsyncTaskUtil.NOTIFICATION_PROGRESS_UPDATE://更新中
DecimalFormat format = new DecimalFormat("0.00");//数字格式转换
String progress = format.format(mSize);
Log.d(TAG, "the progress of the download " + progress);
mRemoteViews.setTextViewText(R.id.id_download_textview, "Download completed : " + progress + " %");
mRemoteViews.setProgressBar(R.id.id_download_progressbar, 100, (int)mSize, false);
mNotification.contentView = mRemoteViews;
mNotificationManager.notify(NOTIFICATION_ID, mNotification);
break;
}
}
}

创建一个activity代码,down_notification.xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical" >


    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:gravity="center"
        android:orientation="horizontal"
        android:background="@android:color/white" >


        <ImageView
            android:id="@+id/id_download_icon"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_marginRight="3dp"
            android:layout_marginTop="3dp"
            android:layout_marginBottom="3dp"
            android:layout_marginLeft="3dp"
            android:src="@drawable/ic_launcher" />


        <LinearLayout
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_marginRight="10dip"
            android:layout_weight="1"
            android:orientation="vertical" >


            <TextView
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:text="@string/app_name"
                android:textColor="@android:color/black"
                android:textSize="18dip"
                android:textStyle="bold" />


            <ProgressBar
                android:id="@+id/id_download_progressbar"
                style="?android:attr/progressBarStyleHorizontal"
                android:layout_width="fill_parent"
                android:layout_height="wrap_content"
                android:layout_marginTop="5dp"
                android:max="100"
                android:progress="0"
                android:secondaryProgress="0" />


            <TextView
                android:id="@+id/id_download_textview"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:text="Download completed : " 
                android:textColor="@android:color/black"
                android:textSize="12dip"
                android:textStyle="bold" />
        </LinearLayout>
    </LinearLayout>


</LinearLayout>


这些都完成后要在mianfest.xml中配置相应的权限了,首先是联网的权限,然后是读写sdk的权限

<uses-permission android:name="android.permission.WAKE_LOCK" />
    <uses-permission android:name="android.permission.INTERNET"/>
<!-- 在SDCard中创建与删除文件权限 -->
<uses-permission android:name="android.permission.MOUNT_UNMOUNT_FILESYSTEMS"/>
<!-- 往SDCard写入数据权限 -->
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>



重点在于:这些都完成后导出jar包,我这里是直接在eclipse中导出的也可以用别的方法,百度得知。导jar包的步骤如下:右键项目->Export->java->jar file->next->

在这里只选中src 文件,其余的全部勾掉,否则打出jar包有问题。


jar包导出后放到untiy中的Plugins中的android中的bin文件夹下,然后再将res拷到android下。接下来要将AndroidMiandfest.xml放到android文件夹下。如果以前项目中已经继承了别的插件后,这里就要注意了。首先将我们导入的配置文件删掉,配置原来的既可以,配置的时候要注意,要将原来的 <intent-filter>
        <category android:name="android.intent.category.LAUNCHER" />
        <action android:name="android.intent.action.MAIN" />
      </intent-filter>

注释掉,将换成新导入的如下即可。此时所有的工作都完成了。



 <activity
      android:name="com.example.downapk.MainActivity"
           android:label="@string/app_name" >
      <intent-filter>
        <category android:name="android.intent.category.LAUNCHER" />
        <action android:name="android.intent.action.MAIN" />


      </intent-filter>


    </activity>

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值