Android源码下载 APK原型

本程序适用于下载http://androidxref.com/网站的ANDROID SOURCE 与KERNEL SOURCE。 由于是原型,所以完全没考虑下载效率,代码结构等问题,此类问题有待读者继续完善。

新建一个android5.0的项目,然后创建以下文件

\Download\AndroidManifents.xml 里面只定义了一个activity 

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.androidxref.download" android:versionCode="1"
android:versionName="1.0">

<uses-sdk android:minSdkVersion="21" android:targetSdkVersion="21" />

<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.MOUNT_UNMOUNT_FILESYSTEMS" />

<application android:allowBackup="true" android:icon="@drawable/ic_launcher"
android:label="@string/app_name" android:theme="@android:style/Theme.Holo.Light.NoActionBar">
<activity android:name="com.androidxref.download.ui.MainActivity"
android:label="@string/app_name">
<intent-filter>
<action android:name="android.intent.action.MAIN" />

<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
</application>

</manifest>


\Download\libs\jsoup-1.8.3.jar 自行在百度下载jsoup-1.8.3.jar库

Download\src\com\androidxref\download\downloader\DownloaderAsyncTask.java

package com.androidxref.download.downloader;

import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.URL;
import java.net.URLConnection;

import org.jsoup.Jsoup;
import org.jsoup.nodes.Document;
import org.jsoup.nodes.Element;
import org.jsoup.select.Elements;

import android.content.ContentValues;
import android.content.Context;
import android.os.AsyncTask;
import android.os.Handler;
import android.text.TextUtils;
import android.view.View;
import android.widget.ScrollView;
import android.widget.TextView;

import com.androidxref.download.tools.FileUtil;
import com.androidxref.download.tools.LogUtil;

public class DownloaderAsyncTask extends AsyncTask<String, String, Float>{
String TAG = DownloaderAsyncTask.class.getName();
Context mContext;
TextView mTextView;
ScrollView mScrollView;
public DownloaderAsyncTask(Context context, TextView textView, ScrollView scrollView) {
mContext = context;
mTextView = textView;
mScrollView = scrollView;
}

@Override
protected Float doInBackground(String... params) {
String androidVersion = FileUtil.getAndroidVersionByUri(params[0]);
// 获取要下载的Android版本
if(TextUtils.isEmpty(androidVersion)){
publishProgress("android version is empty");
publishProgress("please according to the following format and try again");
publishProgress("http://androidxref.com/XXXXXXX/xref/");
} else {
LogUtil.i(TAG, androidVersion);
try{
String uri = params[0];
LogUtil.i(TAG, uri.toString());
//开始下载
publishProgress("downloaduri = " + uri);
startDownload(uri);
}catch(Exception e) {
LogUtil.e(TAG, e.toString() );
publishProgress(e.toString());
e.printStackTrace();
}
}
return null;
}

private void startDownload(String uri) {
try {
Document doc = Jsoup.connect(uri).timeout(5000).post();
Document content = Jsoup.parse(doc.toString());
Elements divs = content.select("#download"); // 获取download
if(divs.size() == 0){ // 获取所有可下载的目录
divs = content.select("#dirlist"); // 获取dirlist
Document divcontions = Jsoup.parse(divs.toString());
Elements element = divcontions.getElementsByTag("a");
for (Element links : element) {
String title = links.getElementsByTag("a").text();
if(title.contains("..")) {
continue;
}
String link = links.select("a").attr("href").replace("/", "")
.trim();
String url = uri.endsWith("/") ? (uri + link) : (uri + "/" + link);
LogUtil.i(TAG, "startDownload url = " + url);
publishProgress("startDownload " + url);
startDownload(url); // 递归调用startDownload下载当前目录下所有文件
}
}
// 获取要下载的url
Elements parents = divs.parents();
String downloadLink = parents.get(0).select("a").attr("href").trim();
if(downloadLink.contains("..")) {
return;
}
downloadLink = FileUtil.formatDownloadLink(downloadLink);

// 下载到指定位置
downloadFile(downloadLink,uri);
} catch (IOException e) {
e.printStackTrace();
}
}

private void downloadFile(String downloadLink, String filePath) {
File newFile = FileUtil.getEmptyFile(downloadLink,filePath,mContext);
publishProgress("downloadFile " + downloadLink + " to " + newFile.getPath());
LogUtil.i(TAG, "downloadFile " + downloadLink + " to " + newFile.getPath());
try {
// 构造URL
URL url = new URL(downloadLink);
// 打开连接
URLConnection con = url.openConnection();
// 输入流
InputStream is = con.getInputStream();
// 1K的数据缓冲
byte[] bs = new byte[1024];
// 读取到的数据长度
int len;
// 输出的文件流
OutputStream os = new FileOutputStream(newFile);
// 开始读取
while ((len = is.read(bs)) != -1) {
os.write(bs, 0, len);
}
// 完毕,关闭所有链接
os.close();
is.close();
} catch (Exception e) {
LogUtil.e(TAG, "downloadFile e.toString() = " + e.toString());
LogUtil.e(TAG, "downloadFile downloadLink = " + downloadLink);
LogUtil.e(TAG, "downloadFile file = " + newFile);
publishProgress("downloadFile e = " + e.toString());
e.printStackTrace();
}
}

@Override
protected void onProgressUpdate(String... values) {
super.onProgressUpdate(values);
mTextView.append(values[0] + "\n\n");
scrollToBottom(mScrollView,mTextView);
}

public static void scrollToBottom(final View scroll, final View inner) {
Handler mHandler = new Handler();
mHandler.post(new Runnable() {
public void run() {
if (scroll == null || inner == null) {
return;
}

int offset = inner.getMeasuredHeight() - scroll.getHeight();
if (offset < 0) {
offset = 0;
}

scroll.scrollTo(0, offset);
}
});
}

@Override
protected void onPostExecute(Float result) {
super.onPostExecute(result);
publishProgress("...stoping...");
}

@Override
protected void onPreExecute() {
super.onPreExecute();
mTextView.setText("");
publishProgress("...initing...");
}
}


Download\src\com\androidxref\download\ui\MainActivity.java

package com.androidxref.download.ui;

import android.annotation.SuppressLint;
import android.app.Activity;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;
import android.widget.ScrollView;
import android.widget.TextView;

import com.androidxref.download.R;
import com.androidxref.download.downloader.DownloaderAsyncTask;
import com.androidxref.download.tools.LogUtil;

public class MainActivity extends Activity {

private final static String TAG = MainActivity.class.getName(); 

private static String mDownloadUri;
private EditText mDownloadUriEditText;
private TextView mDownloadLogs;
ScrollView mScrollView;
private static DownloaderAsyncTask mDownloaderAsyncTask;

private final static int MSG_START_DOWNLOAD = 0X00001;
private final static int MSG_STOP_DOWNLOAD = 0X11110;

@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Button download = (Button) findViewById(R.id.button_download);
mDownloadUriEditText = (EditText) findViewById(R.id.download_uri);
mDownloadLogs = (TextView) findViewById(R.id.download_logs);
mScrollView = (ScrollView) findViewById(R.id.download_logs_scrollview);
download.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
try {
mDownloadUri = mDownloadUriEditText.getText().toString();
Message msg = new Message();
msg.what = MSG_START_DOWNLOAD;
mHandler.removeMessages(MSG_START_DOWNLOAD);
mHandler.sendMessageDelayed(msg, 200);
} catch (Exception e) {
LogUtil.e(TAG, "error = "+e.toString());
e.printStackTrace();
}
}
});
}

@SuppressLint("HandlerLeak")
Handler mHandler = new Handler(){
public void handleMessage(Message msg) {
LogUtil.i(TAG, "mHandler.handleMessage( "+ msg.what + " );");
switch (msg.what) {
case MSG_START_DOWNLOAD:
if(mDownloaderAsyncTask == null){
mDownloaderAsyncTask = new DownloaderAsyncTask(MainActivity.this,mDownloadLogs,mScrollView);
mDownloaderAsyncTask.execute(mDownloadUri);
}
break;
case MSG_STOP_DOWNLOAD:
if(mDownloaderAsyncTask != null){
mDownloaderAsyncTask.cancel(true);
mDownloaderAsyncTask = null;
}
break;
default:
break;
}
};
};
}


Download\src\com\androidxref\download\tools\FileUtil.java

package com.androidxref.download.tools;

import java.io.File;

import android.content.Context;
import android.os.Environment;
import android.os.storage.StorageManager;
import android.text.TextUtils;

public class FileUtil {

final static String TAG = FileUtil.class.getName();
private static String mFileNamePrefix = "Android";
private static String mAndroidVersion = mFileNamePrefix;
final static String MUNSTCONTAINSTR[] = {"/xref/","http://androidxref.com/"};

/**
* @param downloaduri download url
* @return android version
*/
public static String getAndroidVersionByUri(String downloaduri) {
String result ;
// 判断string中是否存在MUNSTCONTAINSTR中的字段
if(!isContains(downloaduri)) {
return null;
}

// 获取android的版本号
result = downloaduri.substring(downloaduri.lastIndexOf(MUNSTCONTAINSTR[1])+MUNSTCONTAINSTR[1].length(), downloaduri.indexOf(MUNSTCONTAINSTR[0]));

mAndroidVersion = null == result ? result : mFileNamePrefix+result;
return mAndroidVersion;
}

private static boolean isContains(String str) {
boolean result = true;
if(!TextUtils.isEmpty(str)){
for(int i = 0; i < MUNSTCONTAINSTR.length; i++){
result &= str.contains(MUNSTCONTAINSTR[i]);
}
return result;
}
return false;
}

public static File convertUriToLocalPath(String string,Context context) {
String path = string.substring(string.indexOf(MUNSTCONTAINSTR[0])+MUNSTCONTAINSTR[0].length(), 
string.lastIndexOf("/")+1);
LogUtil.i(TAG, "convertUriToLocalPath path = " + path);
// 递归创建文件目录 
File file = FileUtil.createFiles(new File("/sdcard/"+mAndroidVersion+"/"+path));
return file;
}

public static File createFiles(File file) {
LogUtil.i(TAG, "createFiles file.getPath() = "+file.getPath());
if(file.exists()){
return file;
}
// /sdcard/Android1.1/developers/demos/JustForUs/gradle/wrapper/
String path = file.getPath();
if(path.endsWith("/")){
path = path.substring(0,path.lastIndexOf("/"));
}
LogUtil.i(TAG, "createFiles path = "+path);
File newFile = new File(file.getPath().substring(0, file.getPath().lastIndexOf("/")));
createFiles(newFile);

file.mkdir();
return file;
}

public static String formatDownloadLink(String downloadLink) {
downloadLink = MUNSTCONTAINSTR[1].substring(0, MUNSTCONTAINSTR[1].length()-1) + downloadLink;
return downloadLink;
}

public static File getEmptyFile(String downloadLink, String filePath,Context mContext) {
File file = FileUtil.convertUriToLocalPath(filePath, mContext);
if (!file.exists()) {
LogUtil.e(TAG, "downloadFile : " + file.getPath() + " not created");
}

// 如果目标文件已经存在,则删除。产生覆盖旧文件的效果
String fileName = file.getPath() + "/" + downloadLink.substring(downloadLink.lastIndexOf("/") + 1, downloadLink.length());
File newFile = new File(fileName);
if (newFile.exists()) {
newFile.delete();
}
return newFile;
}
}


Download\src\com\androidxref\download\tools\LogUtil.java

package com.androidxref.download.tools;

import android.util.Log;

public final class LogUtil {
final static int LOGLEV = 10;
final static String LOGPREF = "======> ";
final static String LOGSUFF = " <======";
    /**
     * Priority constant for the println method; use Log.v.
     */
    public static final int VERBOSE = 2;
    public static int v(String tag, String msg) {
    if(LOGLEV > VERBOSE){
    Log.v(tag, LOGPREF + msg + LOGSUFF);
    }
    return -1;
    }

    /**
     * Priority constant for the println method; use Log.d.
     */
    public static final int DEBUG = 3;
    public static int d(String tag, String msg) {
    if(LOGLEV > DEBUG){
    Log.d(tag, LOGPREF + msg + LOGSUFF);
    }
    return -1;
    }

    /**
     * Priority constant for the println method; use Log.i.
     */
    public static final int INFO = 4;
    public static int i(String tag, String msg) {
    if(LOGLEV > INFO){
    Log.i(tag, LOGPREF + msg + LOGSUFF);
    }
    return -1;
    }

    /**
     * Priority constant for the println method; use Log.w.
     */
    public static final int WARN = 5;
    public static int w(String tag, String msg) {
    if(LOGLEV > INFO){
    Log.w(tag, LOGPREF + msg + LOGSUFF);
    }
    return -1;
    }

    /**
     * Priority constant for the println method; use Log.e.
     */
    public static final int ERROR = 6;
    public static int e(String tag, String msg) {
    if(LOGLEV > INFO){
    Log.e(tag, LOGPREF + msg + LOGSUFF);
    }
    return -1;
    }
}


\Download\res\layout\activity_main.xml

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    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:orientation="vertical">
   <EditText android:id="@+id/download_uri"
       android:layout_width="match_parent"
       android:layout_height="wrap_content"
       android:text="@string/download_uri_text"
       android:hint="@string/download_uri"/>
   <Button android:id="@+id/button_download"
       android:layout_width="wrap_content"
       android:layout_height="wrap_content"
       android:text="@string/button_download"/>
    </LinearLayout>
    <ScrollView
         android:id="@+id/download_logs_scrollview"
    android:layout_width="match_parent"
    android:layout_height="match_parent">
   <TextView
          android:id="@+id/download_logs"
       android:layout_width="match_parent"
       android:textSize="16sp"
       android:layout_height="wrap_content"/>
</ScrollView>
</LinearLayout>


Download\res\values\strings.xml

<?xml version="1.0" encoding="utf-8"?>
<resources>
    <string name="app_name">demo</string>
    <string name="action_settings">Settings</string>
    <string name="button_download">Download</string>
    <string name="download_uri">download uri</string>
    <string name="download_uri_text">http://androidxref.com/6.0.0_r1/xref/external/flac</string>
</resources>

关键文件就这么几个,其他都是一些eclipse自动生成的文件

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值