Постановка задачи: Есть начальные настройки программы для конкретного клиента: IP1, IP2, port и т.д. У меня есть список клиентов, и настройки, которые соответствуют каждому клиенту. Для того чтобы не вводить их после скачивания и установки apk файла, нужно вшить эти настройки в каждую сборку. То есть для каждого клиента должна быть своя, настроенная на него, сборка приложения.
Версия Android-а: 1.6
1) нужно убедиться что у нас стоит последняя версия Ant-а, если это не так качаем и устанавливаем.( http://ant.apache.org/manualdownload.cgi ) и последняя версия Android SDK
2) создаем build.xml в папке с проектом, со следующим содержимым:
<?xml version="1.0" encoding="UTF-8"?>
<project name="1616" >
<property name="sdk.dir" location="C:\Progra~1\Android\android-sdk" />
<property file="local.properties" />
<property name="source.dir" value="src" />
<property name="clojure.source.dir" value="src/clojure" />
<property name="clojure.source.absolute.dir" location="${clojure.source.dir}" />
<property file="build.properties" />
<property file="default.properties" />
<path id="android.antlibs">
<pathelement path="${sdk.dir}/tools/lib/anttasks.jar" />
<pathelement path="${sdk.dir}/tools/lib/sdklib.jar" />
<pathelement path="${sdk.dir}/tools/lib/androidprefs.jar" />
</path>
<taskdef name="setup"
classname="com.android.ant.SetupTask"
classpathref="android.antlibs" />
<setup />
</project>
3) создаем local.property :
sdk.dir=C:\Java\jdk1.6.0_18
4) запускаем консоль и собираем проект командой ant
Для того чтобы проект не только собирался, но еще и обфусыровался, в папку с проектом нужно:
5) настроить обфускацию в eclipse-e по инструкции
6) изменить local.property :
sdk.dir=C:\Java\jdk1.6.0_18
proguard.dir=C:\Progra~1\Android\android-sdk\tools\proguard
key.store=my-release-key.keystore
key.alias=alias_name
key.store.password=12312312
key.alias.password=12341234
7) запускаем консоль и собираем проект командой ant release.
Для того, чтобы автоматически собрать проект для разных фирм, я создал jar файл, который
1) парсит файл, и достает оттуда данные
2) создает файл, размещает его в res/raw свой для каждой сборки
3) все, что в итоге собрано складывает в отдельную папку
Ниже я привожу исходники этого jar файла. Для того чтобы ими воспользоваться нужно
1) создать обычный java проект в eclipse
2) скопировать туда исходники, переделав соответственно под себя
3) командой file-> export-> runnable jar file получить jar файл
Исходники Main.java:
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.ArrayList;
public class Main {
private static String RESOURCE_PATH = "res\\raw";
private static ArrayList<TaxiCompany> taxiCompanies = new ArrayList<TaxiCompany>();
private static String currentDirectory = new File(".").getAbsolutePath();
static {
currentDirectory = new File(".").getAbsolutePath();
}
public static void main(String[] args) {
cleanFolder(currentDirectory + "\\" + "bin");
cleanFolder(currentDirectory + "\\" + "out");
readAllTaxiCompanies();
if (args != null) {
for (int i = 0; i < taxiCompanies.size(); i++) {
boolean removeCurrentCompany = true;
for (int j = 0; j < args.length; j++) {
if (taxiCompanies.get(i).getName().equals(args[j])) {
removeCurrentCompany = false;
}
}
if (removeCurrentCompany) {
taxiCompanies.remove(i);
i--;
} else {
buildAPK(taxiCompanies.get(i));
}
}
}
for (int i = 0; i < taxiCompanies.size(); i++) {
copyFileToOutFolder(taxiCompanies.get(i).getName());
}
}
private static void readAllTaxiCompanies() {
String filePath = currentDirectory + "\\" + "taxi_companies" + "\\" + "MobileTaxiMIDletClass.java";
String str = null;
try {
BufferedReader in = new BufferedReader(new FileReader(filePath));
TaxiCompany currentTaxiCompany = null;
while ((str = in.readLine()) != null) {
if (str.startsWith("//#global")) {
currentTaxiCompany.addLine(str);
} else if (str.startsWith("//#_if (Dispatcher == \"")) {
String name = str.substring(22).replace("\"", "").replace(")", "").trim();
currentTaxiCompany = new TaxiCompany(name);
taxiCompanies.add(currentTaxiCompany);
} else if (str.startsWith("//#_if(Dispatcher == \"")) {
String name = str.substring(22).replace("\"", "").replace(")", "").trim();
currentTaxiCompany = new TaxiCompany(name);
taxiCompanies.add(currentTaxiCompany);
}
}
in.close();
} catch (IOException e) {
}
}
private static void buildAPK(TaxiCompany taxiCompany) {
String name = taxiCompany.getName();
createNewFolderInFolderOut(name);
changeBuildXML(name);
String ip1 = taxiCompany.getIP1();
String ip2 = taxiCompany.getIP2();
String port = taxiCompany.getPort();
String driverCanCancelOrder = String.valueOf( taxiCompany.getDriverCanCancelOrder() );
String etherTogether = String.valueOf( taxiCompany.getEtherTogether() );
String etherSortAboutTime = String.valueOf( taxiCompany.getEtherSortAboutTime() );
try {
File file = new File(RESOURCE_PATH + "\\" + "taxi_company_property.txt");
file.createNewFile();
FileWriter fstream = new FileWriter(file);
BufferedWriter out = new BufferedWriter(fstream);
out.write("IP1:" + ip1 + "\n");
out.write("IP2:" + ip2 + "\n");
out.write("PORT:" + port + "\n");
out.write("driverCanCancelOrder:" + driverCanCancelOrder + "\n");
out.write("etherTogether:" + etherTogether + "\n");
out.write("etherSortAboutTime:" + etherSortAboutTime);
out.flush();
out.close();
fstream.close();
Runtime.getRuntime().exec("cmd.exe /c start /wait /MIN " + "ant release");
Thread.sleep(35000);
} catch (Exception e) {
}
}
private static void changeBuildXML(String companyName) {
String buildXMLPath = "build.xml";
ArrayList<String> allLines = new ArrayList<String>();
try {
BufferedReader in = new BufferedReader(new FileReader(buildXMLPath));
String str = null;
while( (str=in.readLine()) != null) {
allLines.add(str);
}
in.close();
allLines.remove(1);
allLines.add(1, "<project name=\"" + companyName + "\" >");
BufferedWriter out = new BufferedWriter(new FileWriter(buildXMLPath));
for (int i = 0; i < allLines.size(); i++) {
out.write(allLines.get(i) + "\n");
}
out.flush();
out.close();
} catch (Exception e) {}
}
private static void createNewFolderInFolderOut(String name) {
File outFolder = new File(currentDirectory + "\\" + "out");
outFolder.mkdir();
File concreteTaxiCompanyFolder = new File(currentDirectory + "\\" + "out" + "\\" + name);
concreteTaxiCompanyFolder.mkdir();
}
private static void copyFileToOutFolder(String nameCompany) {
String nameFile = nameCompany + "-release.apk";
String path1 = currentDirectory + "\\" + "bin";
String path2 = currentDirectory + "\\" + "out" + "\\" + nameCompany;
copy(path1 + "\\" + nameFile, path2 + "\\" + nameFile);
}
private static void copy(String fromFileName, String toFileName) {
try {
File fromFile = new File(fromFileName);
File toFile = new File(toFileName);
if (toFile.isDirectory()) toFile = new File(toFile, fromFile.getName());
if (toFile.exists()) {
if (!toFile.canWrite())
throw new IOException("FileCopy: "
+ "destination file is unwriteable: " + toFileName);
System.out.print("Overwrite existing file " + toFile.getName()
+ "? (Y/N): ");
System.out.flush();
BufferedReader in = new BufferedReader(new InputStreamReader(
System.in));
String response = in.readLine();
if (!response.equals("Y") && !response.equals("y"))
throw new IOException("FileCopy: "
+ "existing file was not overwritten.");
} else {
}
FileInputStream from = null;
FileOutputStream to = null;
try {
from = new FileInputStream(fromFile);
to = new FileOutputStream(toFile);
byte[] buffer = new byte[4096];
int bytesRead;
while ((bytesRead = from.read(buffer)) != -1)
to.write(buffer, 0, bytesRead); // write
} finally {
if (from != null)
try {
from.close();
} catch (IOException e) { }
if (to != null)
try {
to.close();
} catch (IOException e) { }
}
} catch (Exception e) { }
}
private static void cleanFolder(String path) {
File folder = new File(path);
String[] children = folder.list();
for (int i=0; i<children.length; i++) {
removeFolder(new File(folder, children[i]));
}
}
private static void removeFolder(File folder) {
if (folder.isDirectory()) {
String[] children = folder.list();
for (int i=0; i<children.length; i++) {
removeFolder(new File(folder, children[i]));
}
}
folder.delete();
}
}
Исходники TaxiCompany.java:
public class TaxiCompany {
private String _name = null;
private int _numberLine = 0;
private boolean _driverCanCancelOrder = true;
private boolean _etherTogether = true;
private boolean _etherSortAboutTime = true;
private String _ip1;
private String _ip2;
private String _port;
public TaxiCompany(String name) {
_name = name;
}
public void addLine(String line) {
if (_numberLine == 0) {
_driverCanCancelOrder = Boolean.getBoolean( getValue(line) );
} else if (_numberLine == 1) {
_etherTogether = getValue(line).equals("0");
} else if (_numberLine == 2) {
_etherSortAboutTime = getValue(line).equals("0");
} else if (_numberLine == 3) {
_ip1 = getValue(line);
} else if (_numberLine == 4) {
_ip2 = getValue(line);
} else if (_numberLine == 5) {
_port = getValue(line);
}
_numberLine++;
}
public String getName() {
return _name;
}
public boolean getDriverCanCancelOrder() {
return _driverCanCancelOrder;
}
public boolean getEtherTogether() {
return _etherTogether;
}
public boolean getEtherSortAboutTime() {
return _etherSortAboutTime;
}
public String getIP1() {
return _ip1;
}
public String getIP2() {
return _ip2;
}
public String getPort() {
return _port;
}
private String getValue(String line) {
int index = line.indexOf("=");
String result = line.substring(index+1, line.length()).replace("\"", "").trim();
return result;
}
}
Для того чтобы выложить результат на ftp сервер(в моем случае на 2 фтп сервера):
1) дописал build.xml создав target:
<?xml version="1.0" encoding="UTF-8"?>
<project name="1616" >
<property name="sdk.dir" location="C:\Progra~1\Android\android-sdk" />
<property file="local.properties" />
<property name="source.dir" value="src" />
<property name="clojure.source.dir" value="src/clojure" />
<property name="clojure.source.absolute.dir" location="${clojure.source.dir}" />
<property file="build.properties" />
<property file="default.properties" />
<path id="android.antlibs">
<pathelement path="${sdk.dir}/tools/lib/anttasks.jar" />
<pathelement path="${sdk.dir}/tools/lib/sdklib.jar" />
<pathelement path="${sdk.dir}/tools/lib/androidprefs.jar" />
</path>
<taskdef name="setup"
classname="com.android.ant.SetupTask"
classpathref="android.antlibs" />
<setup />
<target name="export">
<ftp password="*****" server="****.***.**"
userid="********"
passive="true"
remotedir="public/!android">
<fileset dir="./out" />
</ftp>
<ftp password="*******" server="****.**.**"
userid="*******"
passive="true"
remotedir="public/!android">
<fileset dir="./out" />
</ftp>
</target>
</project>
2) скачал jar файл(apache commons), переименовал и разместил его в папке с проектом.
3) експорт осуществляется командой в консоли: ant export -lib export_to_ftp.jar
Итого я получил 2 bat файла, из которых 1 собирает проект, а 1-ой выкладывает его на ftp.
build.bat:
java -jar buildProject.jar
pause
export_to_ftp.bat:
ant export -lib export_to_ftp.jar
Версия Android-а: 1.6
1) нужно убедиться что у нас стоит последняя версия Ant-а, если это не так качаем и устанавливаем.( http://ant.apache.org/manualdownload.cgi ) и последняя версия Android SDK
2) создаем build.xml в папке с проектом, со следующим содержимым:
<?xml version="1.0" encoding="UTF-8"?>
<project name="1616" >
<property name="sdk.dir" location="C:\Progra~1\Android\android-sdk" />
<property file="local.properties" />
<property name="source.dir" value="src" />
<property name="clojure.source.dir" value="src/clojure" />
<property name="clojure.source.absolute.dir" location="${clojure.source.dir}" />
<property file="build.properties" />
<property file="default.properties" />
<path id="android.antlibs">
<pathelement path="${sdk.dir}/tools/lib/anttasks.jar" />
<pathelement path="${sdk.dir}/tools/lib/sdklib.jar" />
<pathelement path="${sdk.dir}/tools/lib/androidprefs.jar" />
</path>
<taskdef name="setup"
classname="com.android.ant.SetupTask"
classpathref="android.antlibs" />
<setup />
</project>
3) создаем local.property :
sdk.dir=C:\Java\jdk1.6.0_18
4) запускаем консоль и собираем проект командой ant
Для того чтобы проект не только собирался, но еще и обфусыровался, в папку с проектом нужно:
5) настроить обфускацию в eclipse-e по инструкции
6) изменить local.property :
sdk.dir=C:\Java\jdk1.6.0_18
proguard.dir=C:\Progra~1\Android\android-sdk\tools\proguard
key.store=my-release-key.keystore
key.alias=alias_name
key.store.password=12312312
key.alias.password=12341234
7) запускаем консоль и собираем проект командой ant release.
Для того, чтобы автоматически собрать проект для разных фирм, я создал jar файл, который
1) парсит файл, и достает оттуда данные
2) создает файл, размещает его в res/raw свой для каждой сборки
3) все, что в итоге собрано складывает в отдельную папку
Ниже я привожу исходники этого jar файла. Для того чтобы ими воспользоваться нужно
1) создать обычный java проект в eclipse
2) скопировать туда исходники, переделав соответственно под себя
3) командой file-> export-> runnable jar file получить jar файл
Исходники Main.java:
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.ArrayList;
public class Main {
private static String RESOURCE_PATH = "res\\raw";
private static ArrayList<TaxiCompany> taxiCompanies = new ArrayList<TaxiCompany>();
private static String currentDirectory = new File(".").getAbsolutePath();
static {
currentDirectory = new File(".").getAbsolutePath();
}
public static void main(String[] args) {
cleanFolder(currentDirectory + "\\" + "bin");
cleanFolder(currentDirectory + "\\" + "out");
readAllTaxiCompanies();
if (args != null) {
for (int i = 0; i < taxiCompanies.size(); i++) {
boolean removeCurrentCompany = true;
for (int j = 0; j < args.length; j++) {
if (taxiCompanies.get(i).getName().equals(args[j])) {
removeCurrentCompany = false;
}
}
if (removeCurrentCompany) {
taxiCompanies.remove(i);
i--;
} else {
buildAPK(taxiCompanies.get(i));
}
}
}
for (int i = 0; i < taxiCompanies.size(); i++) {
copyFileToOutFolder(taxiCompanies.get(i).getName());
}
}
private static void readAllTaxiCompanies() {
String filePath = currentDirectory + "\\" + "taxi_companies" + "\\" + "MobileTaxiMIDletClass.java";
String str = null;
try {
BufferedReader in = new BufferedReader(new FileReader(filePath));
TaxiCompany currentTaxiCompany = null;
while ((str = in.readLine()) != null) {
if (str.startsWith("//#global")) {
currentTaxiCompany.addLine(str);
} else if (str.startsWith("//#_if (Dispatcher == \"")) {
String name = str.substring(22).replace("\"", "").replace(")", "").trim();
currentTaxiCompany = new TaxiCompany(name);
taxiCompanies.add(currentTaxiCompany);
} else if (str.startsWith("//#_if(Dispatcher == \"")) {
String name = str.substring(22).replace("\"", "").replace(")", "").trim();
currentTaxiCompany = new TaxiCompany(name);
taxiCompanies.add(currentTaxiCompany);
}
}
in.close();
} catch (IOException e) {
}
}
private static void buildAPK(TaxiCompany taxiCompany) {
String name = taxiCompany.getName();
createNewFolderInFolderOut(name);
changeBuildXML(name);
String ip1 = taxiCompany.getIP1();
String ip2 = taxiCompany.getIP2();
String port = taxiCompany.getPort();
String driverCanCancelOrder = String.valueOf( taxiCompany.getDriverCanCancelOrder() );
String etherTogether = String.valueOf( taxiCompany.getEtherTogether() );
String etherSortAboutTime = String.valueOf( taxiCompany.getEtherSortAboutTime() );
try {
File file = new File(RESOURCE_PATH + "\\" + "taxi_company_property.txt");
file.createNewFile();
FileWriter fstream = new FileWriter(file);
BufferedWriter out = new BufferedWriter(fstream);
out.write("IP1:" + ip1 + "\n");
out.write("IP2:" + ip2 + "\n");
out.write("PORT:" + port + "\n");
out.write("driverCanCancelOrder:" + driverCanCancelOrder + "\n");
out.write("etherTogether:" + etherTogether + "\n");
out.write("etherSortAboutTime:" + etherSortAboutTime);
out.flush();
out.close();
fstream.close();
Runtime.getRuntime().exec("cmd.exe /c start /wait /MIN " + "ant release");
Thread.sleep(35000);
} catch (Exception e) {
}
}
private static void changeBuildXML(String companyName) {
String buildXMLPath = "build.xml";
ArrayList<String> allLines = new ArrayList<String>();
try {
BufferedReader in = new BufferedReader(new FileReader(buildXMLPath));
String str = null;
while( (str=in.readLine()) != null) {
allLines.add(str);
}
in.close();
allLines.remove(1);
allLines.add(1, "<project name=\"" + companyName + "\" >");
BufferedWriter out = new BufferedWriter(new FileWriter(buildXMLPath));
for (int i = 0; i < allLines.size(); i++) {
out.write(allLines.get(i) + "\n");
}
out.flush();
out.close();
} catch (Exception e) {}
}
private static void createNewFolderInFolderOut(String name) {
File outFolder = new File(currentDirectory + "\\" + "out");
outFolder.mkdir();
File concreteTaxiCompanyFolder = new File(currentDirectory + "\\" + "out" + "\\" + name);
concreteTaxiCompanyFolder.mkdir();
}
private static void copyFileToOutFolder(String nameCompany) {
String nameFile = nameCompany + "-release.apk";
String path1 = currentDirectory + "\\" + "bin";
String path2 = currentDirectory + "\\" + "out" + "\\" + nameCompany;
copy(path1 + "\\" + nameFile, path2 + "\\" + nameFile);
}
private static void copy(String fromFileName, String toFileName) {
try {
File fromFile = new File(fromFileName);
File toFile = new File(toFileName);
if (toFile.isDirectory()) toFile = new File(toFile, fromFile.getName());
if (toFile.exists()) {
if (!toFile.canWrite())
throw new IOException("FileCopy: "
+ "destination file is unwriteable: " + toFileName);
System.out.print("Overwrite existing file " + toFile.getName()
+ "? (Y/N): ");
System.out.flush();
BufferedReader in = new BufferedReader(new InputStreamReader(
System.in));
String response = in.readLine();
if (!response.equals("Y") && !response.equals("y"))
throw new IOException("FileCopy: "
+ "existing file was not overwritten.");
} else {
}
FileInputStream from = null;
FileOutputStream to = null;
try {
from = new FileInputStream(fromFile);
to = new FileOutputStream(toFile);
byte[] buffer = new byte[4096];
int bytesRead;
while ((bytesRead = from.read(buffer)) != -1)
to.write(buffer, 0, bytesRead); // write
} finally {
if (from != null)
try {
from.close();
} catch (IOException e) { }
if (to != null)
try {
to.close();
} catch (IOException e) { }
}
} catch (Exception e) { }
}
private static void cleanFolder(String path) {
File folder = new File(path);
String[] children = folder.list();
for (int i=0; i<children.length; i++) {
removeFolder(new File(folder, children[i]));
}
}
private static void removeFolder(File folder) {
if (folder.isDirectory()) {
String[] children = folder.list();
for (int i=0; i<children.length; i++) {
removeFolder(new File(folder, children[i]));
}
}
folder.delete();
}
}
Исходники TaxiCompany.java:
public class TaxiCompany {
private String _name = null;
private int _numberLine = 0;
private boolean _driverCanCancelOrder = true;
private boolean _etherTogether = true;
private boolean _etherSortAboutTime = true;
private String _ip1;
private String _ip2;
private String _port;
public TaxiCompany(String name) {
_name = name;
}
public void addLine(String line) {
if (_numberLine == 0) {
_driverCanCancelOrder = Boolean.getBoolean( getValue(line) );
} else if (_numberLine == 1) {
_etherTogether = getValue(line).equals("0");
} else if (_numberLine == 2) {
_etherSortAboutTime = getValue(line).equals("0");
} else if (_numberLine == 3) {
_ip1 = getValue(line);
} else if (_numberLine == 4) {
_ip2 = getValue(line);
} else if (_numberLine == 5) {
_port = getValue(line);
}
_numberLine++;
}
public String getName() {
return _name;
}
public boolean getDriverCanCancelOrder() {
return _driverCanCancelOrder;
}
public boolean getEtherTogether() {
return _etherTogether;
}
public boolean getEtherSortAboutTime() {
return _etherSortAboutTime;
}
public String getIP1() {
return _ip1;
}
public String getIP2() {
return _ip2;
}
public String getPort() {
return _port;
}
private String getValue(String line) {
int index = line.indexOf("=");
String result = line.substring(index+1, line.length()).replace("\"", "").trim();
return result;
}
}
Для того чтобы выложить результат на ftp сервер(в моем случае на 2 фтп сервера):
1) дописал build.xml создав target:
<?xml version="1.0" encoding="UTF-8"?>
<project name="1616" >
<property name="sdk.dir" location="C:\Progra~1\Android\android-sdk" />
<property file="local.properties" />
<property name="source.dir" value="src" />
<property name="clojure.source.dir" value="src/clojure" />
<property name="clojure.source.absolute.dir" location="${clojure.source.dir}" />
<property file="build.properties" />
<property file="default.properties" />
<path id="android.antlibs">
<pathelement path="${sdk.dir}/tools/lib/anttasks.jar" />
<pathelement path="${sdk.dir}/tools/lib/sdklib.jar" />
<pathelement path="${sdk.dir}/tools/lib/androidprefs.jar" />
</path>
<taskdef name="setup"
classname="com.android.ant.SetupTask"
classpathref="android.antlibs" />
<setup />
<target name="export">
<ftp password="*****" server="****.***.**"
userid="********"
passive="true"
remotedir="public/!android">
<fileset dir="./out" />
</ftp>
<ftp password="*******" server="****.**.**"
userid="*******"
passive="true"
remotedir="public/!android">
<fileset dir="./out" />
</ftp>
</target>
</project>
2) скачал jar файл(apache commons), переименовал и разместил его в папке с проектом.
3) експорт осуществляется командой в консоли: ant export -lib export_to_ftp.jar
Итого я получил 2 bat файла, из которых 1 собирает проект, а 1-ой выкладывает его на ftp.
build.bat:
java -jar buildProject.jar
pause
export_to_ftp.bat:
ant export -lib export_to_ftp.jar
Грамотно, спасибо!
ОтветитьУдалитьпро сборку с помощью Ant еще вот это понравилось http://www.enterra.ru/blog/automation_builds_android_applications/