此文章主要是針對需要在離線網(wǎng)絡(luò)扎谎、內(nèi)部網(wǎng)絡(luò)部署使用Android Studio(坑很多)的解決方案危喉。
此處使用的版本為Android Studio 3.5
一、環(huán)境準(zhǔn)備
1弹灭、 developer.android下載安裝包督暂,已安裝過的可省略此步驟。
2穷吮、 developer.android下載
Google Maven dependencies
逻翁,可省略此步驟。
實際開發(fā)中我們必然會使用到第三方庫捡鱼,因此官方提供的環(huán)境并不能滿足我們的開發(fā)需求八回。
3、使用一臺可上網(wǎng)電腦堰汉,安裝辽社、部署并成功編譯Android項目(建議在一個項目內(nèi)提前依賴我們需要的三方款),此步驟是為了解決離線環(huán)境中g(shù)radle下載和需要的開發(fā)庫環(huán)境等翘鸭。
4滴铅、準(zhǔn)備好Android SDK(建議提前下載需要的環(huán)境)。
二就乓、安裝及配置
2.1 安裝Android Studio
此處省略一萬字(sdk需手動配置路徑為下載好的Android Sdk)汉匙。
2.2 配置離線Grandle
2.3 設(shè)置離線開發(fā)
2.4 配置離線插件和依賴
解壓下載的Google Maven dependencies
文件offline-gmaven-stable
文件拱烁,打開Readme文件,可以看到離線配置教程如下:
2.4.1 新建offline.gradle文件
在.gradle目錄中創(chuàng)建下圖中的目錄和文件
office.gradle內(nèi)容如下
def reposDir = new File(System.properties['user.home'], ".android/manual-offline-m2")
def repos = new ArrayList()
reposDir.eachDir {repos.add(it) }
repos.sort()
allprojects {
buildscript {
repositories {
for (repo in repos) {
maven {
name = "injected_offline_${repo.name}"
url = repo.toURI().toURL()
}
}
}
}
repositories {
for (repo in repos) {
maven {
name = "injected_offline_${repo.name}"
url = repo.toURI().toURL()
}
}
}
}
其中
new File(System.properties['user.home'], ".android/manual-offline-m2")
標(biāo)識的就是依賴庫所在的位置噩翠,其中user.home
標(biāo)識window中用戶所在目錄戏自。
2.4.2 新建manual-offline-m2目錄
對應(yīng)目錄創(chuàng)建manual-offline-m2
2.4.3、處理依賴和插件
本質(zhì)上是需要將“androidx.activity\activity\1.0.0\28eb83e6a29ac3fbb87aa632cfa0e644a313f491\activity-1.0.0-sources.jar”這樣的結(jié)構(gòu)處理為“androidx\activity\1.0.0\activity-1.0.0-sources.jar”在Android Studio中我們所依賴的庫系統(tǒng)會默認(rèn)緩存.gradle中(如下圖所示)伤锚,但是在離線狀態(tài)下擅笔,系統(tǒng)無法根據(jù)現(xiàn)有的目錄結(jié)構(gòu)找到需要的jar、aar屯援、so等文件猛们,因此需要對目錄結(jié)構(gòu)進(jìn)行處理
我們使用java工具對目錄進(jìn)行處理,工具代碼來源于逍遙游俠狞洋,當(dāng)然大家可以自己封裝一下方便使用弯淘。
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.ArrayList;
import java.util.LinkedList;
import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.DataInputStream;
import java.io.DataOutputStream;
/**
* 將Android中使用的gradle緩存目錄中的jar包重新處理路徑,用于內(nèi)網(wǎng)離線構(gòu)建
* @author yhh
*
*/
public class CopyTool {
// static String path = "D:\\Androidstudio2.3.3\\Android Studio\\gradle\\m2repository";
// static String path = "D:\\gradle_cache\\files-2.1";
static String path = "D:\\test\\files-2.1"; //C:\Users\Administrator\.gradle\caches\modules-2\files-2.1
// static String stopName= "files-2.1";
static String stopName = "files-2.1";
public static void main(String[] args) {
System.out.println("Begin to copy");
processDotForld();
copyToLastForld();
System.out.println("Copy finished");
}
/**
* 處理文件夾中帶點(diǎn)好的吉懊。庐橙;例如:D:/test/com.ifind.android/
*/
public static void processDotForld() {
File file = new File(path);
if (file.exists()) {
LinkedList<File> list = new LinkedList<>();
File[] files = file.listFiles();
for (int i = 0; i < files.length; i++) {
File file2 = files[i];
if (file2.isDirectory()) {
//文件夾
File desFile = creatforld(file2);
copyFileToDes(file2, desFile);
} else {
//文件//目前不存在
}
}
}
}
/**
* 文件夾拷貝
*
* @param source
* @param des
*/
public static void copyFileToDes(File source, File des) {
try {
copyDir(source.getPath(), des.getPath());
} catch (Exception e) {
// TODO: handle exception
}
}
/**
* 文件夾拷貝
*
* @param sourcePath
* @param newPath
* @throws IOException
*/
public static void copyDir(String sourcePath, String newPath) throws IOException {
File file = new File(sourcePath);
String[] filePath = file.list();
if (!(new File(newPath)).exists()) {
(new File(newPath)).mkdir();
}
for (int i = 0; i < filePath.length; i++) {
if ((new File(sourcePath + file.separator + filePath[i])).isDirectory()) {
copyDir(sourcePath + file.separator + filePath[i], newPath + file.separator + filePath[i]);
}
if (new File(sourcePath + file.separator + filePath[i]).isFile()) {
copyFile(sourcePath + file.separator + filePath[i], newPath + file.separator + filePath[i]);
}
}
}
public static void copyFile(String oldPath, String newPath) throws IOException {
File oldFile = new File(oldPath);
File file = new File(newPath);
FileInputStream in = new FileInputStream(oldFile);
FileOutputStream out = new FileOutputStream(file);
byte[] buffer = new byte[2097152];
//while((in.read(buffer)) != -1){
// out.write(buffer);
//}
DataInputStream dis = new DataInputStream(new BufferedInputStream(in));
DataOutputStream dos = new DataOutputStream(new BufferedOutputStream(out));
int length;
while ((length = dis.read(buffer)) != -1) {
dos.write(buffer, 0, length);
}
dos.flush();
dos.close();
dis.close();
}
/**
* 創(chuàng)建文件夾
*
* @param file
*/
public static File creatforld(File file) {
String path = file.getAbsolutePath();
if (path != null) {
String temp = "files-2.1";
temp = stopName;
String temS[] = path.split(temp);
if (temS != null && temS.length == 2) {
String firstName = temS[0];
String dotName = temS[1];
if (dotName != null) {
String[] lasts = dotName.split("\\.");
int count = lasts.length;
if (count < 2) {
return null;
}
String pathNew = firstName + temp;
for (int i = 0; i < count; i++) {
if (i == 0) {
pathNew = pathNew + lasts[i];
} else {
pathNew = pathNew + "\\" + lasts[i];
}
}
if (pathNew != null && !pathNew.equals("")) {
File fileForld = new File(pathNew);
if (!fileForld.exists()) {
fileForld.mkdirs();
}
return fileForld;
}
}
}
}
return null;
}
public static ArrayList<File> getFile(File file) {
ArrayList<File> list = new ArrayList<>();
if (file.isDirectory()) {
File[] filesTemp = file.listFiles();
for (int i = 0; i < filesTemp.length; i++) {
ArrayList<File> result = getFile(filesTemp[i]);
list.addAll(result);
}
} else {
list.add(file);
}
return list;
}
// 創(chuàng)建目錄
public static boolean createDir(String destDirName) {
File dir = new File(destDirName);
if (dir.exists()) {// 判斷目錄是否存在
System.out.println("創(chuàng)建目錄失敗乎赴,目標(biāo)目錄已存在谋右!");
return false;
}
if (!destDirName.endsWith(File.separator)) {// 結(jié)尾是否以"/"結(jié)束
destDirName = destDirName + File.separator;
}
if (dir.mkdirs()) {// 創(chuàng)建目標(biāo)目錄
System.out.println("創(chuàng)建目錄成功隆敢!" + destDirName);
return true;
} else {
System.out.println("創(chuàng)建目錄失斅咽贰咽弦!");
return false;
}
}
public static void copyToLastForld() {
File file = new File(path);
if (file.exists()) {
LinkedList<File> list = new LinkedList<>();
File[] files = file.listFiles();
for (int i = 0; i < files.length; i++) {
File file2 = files[i];
if (file2.isDirectory()) {
//文件夾
proceessForld(file2);
} else {
//文件//目前不存在
}
}
}
}
private static void proceessForld(File file) {
File[] files = file.listFiles();
for (int i = 0; i < files.length; i++) {
File file2 = files[i];
if (file2.isDirectory()) {
//文件夾
proceessForld(file2);
} else {
//文件//目前不存在//判斷是否進(jìn)行拷貝
try {
proceessFile(file2);
} catch (FileNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}
private static void proceessFile(File file) throws FileNotFoundException {
if (file != null) {
String path = file.getAbsolutePath();
if (path != null) {
String[] lasts = splitString(path);
if (lasts != null && lasts.length > 0) {
int count = lasts.length;
String last = lasts[count - 1];
String last2 = lasts[count - 2];
if (last2 != null && last2.length() > 20) {
//拷貝到上一級目錄
String des = null;
if (count < 2) {
return;
}
for (int i = 0; i < count - 2; i++) {
if (i == 0) {
des = lasts[i];
} else {
des = des + "\\\\" + lasts[i];
}
}
des = des + "\\\\" + last;
String strParentDirectory = file.getParent();
File parentFile = new File(strParentDirectory);
strParentDirectory = parentFile.getParent() + "\\" + last;
copy(file, path, strParentDirectory);
} else {
// System.out.println("source = "+path);
}
// System.out.println("source = "+path);
// System.out.println("des = "+des);
}
}
}
}
private static String[] splitString(String path) {
String[] lasts = null;
lasts = path.split("\\\\");
int count = lasts.length;
boolean isFirst = true;
for (int i = 0; i < count; i++) {
String str = lasts[i];
if (str != null && str.contains(".")) {
if (isFirst) {
isFirst = false;
System.out.println("\n\n\n\n");
System.out.println("path=" + path + "");
}
System.out.println("str=" + str + "");
}
}
return lasts;
}
/**
* copy動作
*
* @param file
* @param source
* @param des
* @throws FileNotFoundException
*/
private static void copy(File file, String source, String des) throws FileNotFoundException {
if (file != null) {
FileInputStream fis = null;
FileOutputStream fot = null;
byte[] bytes = new byte[1024];
int temp = 0;
File desFile = new File(des);
if (desFile.exists()) {
return;
}
try {
fis = new FileInputStream(file);
fot = new FileOutputStream(desFile);
while ((temp = fis.read(bytes)) != -1) {
fot.write(bytes, 0, temp);
fot.flush();
}
} catch (IOException e) {
e.printStackTrace();
} finally {
if (fis != null) {
try {
fis.close();
} catch (IOException e) {
e.printStackTrace();
}
}
if (fot != null) {
try {
fot.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
}
private static String getContent(String content) {
String str = content;
if (content != null && content.length() > 4) {
str = content.substring(0, 4);
}
return str;
}
}
最后將處理后的文件夾copy至offline-gmaven-stable目錄中
tip:其他解決方案:使用內(nèi)網(wǎng)搭建maven(更好的兼容版本和管理)