android手動打包
『壹』 Android開發問題:Failed to install Hello.apk on device 'emulator-5554!
R.java消失或解析異常
自定義title欄
SQLite isFirst和isBeforeFirst方法的區別
eclipse刪除空行
getX()和getRawX()的區別
imagView居中顯示問題
synchronized引發了 java.util.
獲取隨機顏色
去掉Activity的標題欄,全屏顯示
如何修改應用名稱及應用圖標
關於調試方法
Couldn't read row 0, col -1 from CursorWindow. Make sure the Cursor is initialized correctly before accessing data from it.
android.content.res.Resources.loadXmlResourceParser
android.content.res.Resources$NotFoundException
交互性的button定義的方法
在超級終端中執行程序報錯-Permission deny
從svn導入工程項目有驚嘆號
從svn導入工程項目有驚嘆號
首次進入帶有EditText的Activity不自動彈出軟鍵盤,再次點擊才彈
Gallery中OnItemClickListener與OnItemSelectedListener的區別
Eclipse中簽名導出apk崩潰,手動簽名
android.view.InflateException: Binary XML file line #異常的解決
判斷是否有root許可權
最簡單的Root 模擬器的方法
新版ADT開啟eclipse提示 "Running Android Lint" has encountered a problem
新版ADT開啟eclipse提示cannot open libstdc++.so.6..
無法升級ADT
『貳』 android如何使用ant批量打包
ps :後期熟悉ant的話,可以使用純ant腳本或者使用另一種更好的自動化打包工具(maven)關鍵代碼如下:package com.cn.ant; import java.io.BufferedReader; import java.io.BufferedWriter; import java.io.File; import java.io.FileReader; import java.io.FileWriter; import java.io.IOException; import java.util.ArrayList; import org.apache.tools.ant.DefaultLogger; import org.apache.tools.ant.Project; import org.apache.tools.ant.ProjectHelper; public class AntTest { private Project project; public void init(String _buildFile, String _baseDir) throws Exception { project = new Project(); project.init(); DefaultLogger consoleLogger = new DefaultLogger(); consoleLogger.setErrorPrintStream(System.err); consoleLogger.setOutputPrintStream(System.out); consoleLogger.setMessageOutputLevel(Project.MSG_INFO); project.addBuildListener(consoleLogger); // Set the base directory. If none is given, "." is used. if (_baseDir == null) _baseDir = new String("."); project.setBasedir(_baseDir); if (_buildFile == null) _buildFile = new String(projectBasePath + File.separator + "build.xml"); //ProjectHelper.getProjectHelper().parse(project, new File(_buildFile)); // 關鍵代碼 ProjectHelper.configureProject(project, new File(_buildFile)); } public void runTarget(String _target) throws Exception { // Test if the project exists if (project == null) throw new Exception( "No target can be launched because the project has not been initialized. Please call the 'init' method first !"); // If no target is specified, run the default one. if (_target == null) _target = project.getDefaultTarget(); // Run the target project.executeTarget(_target); } // private final static ArrayList<String> flagList = new ArrayList<String>(); //也可以使用集合,不過需要手動添加項 private final static String[] flagList = new String[]{"htc","moto","oppo"};//此處初始化市場標識 private final static String projectBasePath = ""; //項目的根目錄,需要配置 private final static String ApkPath = ""; //要改名後拷貝的目錄,需要配置 private final static String placeHolder = ""; //佔位符,需要配置 public static void main(String args[]) { //flagList.add("htc"); //flagList.add("moto"); //flagList.add("oppo"); try { System.out.println("---------ant批量自動化打包開始----------"); for(String flag : flagList){ //先修改manifest文件:讀取臨時文件中的@market@修改為市場標識,然後寫入manifest.xml中 String tempFilePath = projectBasePath + File.separator + "AndroidManifest.xml.temp"; String filePath = projectBasePath + File.separator + "AndroidManifest.xml"; write(filePath,read(tempFilePath, flag)); //執行打包命令 AntTest mytest = new AntTest(); mytest.init( projectBasePath + File.separator + "build.xml", projectBasePath); mytest.runTarget("clean"); mytest.runTarget("release"); //打完包後執行重命名加拷貝操作 //String flag = "htc"; File file = new File(projectBasePath + File.separator +"bin"+File.pathSeparator+"MainActivity-release.apk");//bin目錄下簽名的apk文件 file.renameTo(new File(ApkPath + File.separator + "MainActivity_"+flag+".apk")); } System.out.println("---------ant批量自動化打包結束----------"); } catch (Exception e) { e.printStackTrace(); System.out.println("---------ant批量自動化打包中發生異常----------"); } } public static String read(String filePath,String replaceStr) { BufferedReader br = null; String line = null; StringBuffer buf = new StringBuffer(); try { // 根據文件路徑創建緩沖輸入流 br = new BufferedReader(new FileReader(filePath)); // 循環讀取文件的每一行, 對需要修改的行進行修改, 放入緩沖對象中 while ((line = br.readLine()) != null) { // 此處根據實際需要修改某些行的內容 if (line.contains(placeHolder)) { line = line.replace(placeHolder, replaceStr); buf.append(line); } else { buf.append(line); } buf.append(System.getProperty("line.separator")); } } catch (Exception e) { e.printStackTrace(); } finally { // 關閉流 if (br != null) { try { br.close(); } catch (IOException e) { br = null; } } } return buf.toString(); } /** * 將內容回寫到文件中 * * @param filePath * @param content */ public static void write(String filePath, String content) { BufferedWriter bw = null; try { // 根據文件路徑創建緩沖輸出流 bw = new BufferedWriter(new FileWriter(filePath)); // 將內容寫入文件中 bw.write(content); } catch (Exception e) { e.printStackTrace(); } finally { // 關閉流 if (bw != null) { try { bw.close(); } catch (IOException e) { bw = null; } } } } }
『叄』 Android應用手動簽名打包的apk無法在手機上安裝,而自動用debug簽名的apk包安裝就沒題
應該是proguard.cfg文件缺東西
『肆』 如何打包安卓手機Zip升級包如何簽名不換Recovery,用官方Recovery
通過分析update.zip包在具體Android系統升級的過程,來理解Android系統中Recovery模式服務的工作原理。
我們先從update.zip包的製作開始,然後是Android系統的啟動模式分析,Recovery工作原理,如何從我們上層開始選擇system update到重啟到Recovery服務,以及在Recovery服務中具體怎樣處理update.zip包升級的,我們的安裝腳本updater-script怎樣被解析並執行的等一系列問題。分析過程中所用的Android源碼是gingerbread0919(tcc88xx開發板標配的),測試開發板是tcc88xx。
一、 update.zip包的目錄結構
|----boot.img
|----system/
|----recovery/
`|----recovery-from-boot.p
`|----etc/
`|----install-recovery.sh
|---META-INF/
`|CERT.RSA
`|CERT.SF
`|MANIFEST.MF
`|----com/
`|----google/
`|----android/
`|----update-binary
`|----updater-script
`|----android/
`|----metadata
二、 update.zip包目錄結構詳解
以上是我們用命令make otapackage 製作的update.zip包的標准目錄結構。
1、boot.img是更新boot分區所需要的文件。這個boot.img主要包括kernel+ramdisk。
2、system/目錄的內容在升級後會放在系統的system分區。主要用來更新系統的一些應用或則應用會用到的一些庫等等。可以將Android源碼編譯out/target/proct/tcc8800/system/中的所有文件拷貝到這個目錄來代替。
3、recovery/目錄中的recovery-from-boot.p是boot.img和recovery.img的補丁(patch),主要用來更新recovery分區,其中etc/目錄下的install-recovery.sh是更新腳本。
4、update-binary是一個二進制文件,相當於一個腳本解釋器,能夠識別updater-script中描述的操作。該文件在Android源碼編譯後out/target/proct/tcc8800/system bin/updater生成,可將updater重命名為update-binary得到。
該文件在具體的更新包中的名字由源碼中bootable/recovery/install.c中的宏ASSUMED_UPDATE_BINARY_NAME的值而定。
5、updater-script:此文件是一個腳本文件,具體描述了更新過程。我們可以根據具體情況編寫該腳本來適應我們的具體需求。該文件的命名由源碼中bootable/recovery/updater/updater.c文件中的宏SCRIPT_NAME的值而定。
6、 metadata文件是描述設備信息及環境變數的元數據。主要包括一些編譯選項,簽名公鑰,時間戳以及設備型號等。
7、我們還可以在包中添加userdata目錄,來更新系統中的用戶數據部分。這部分內容在更新後會存放在系統的/data目錄下。
8、update.zip包的簽名:update.zip更新包在製作完成後需要對其簽名,否則在升級時會出現認證失敗的錯誤提示。而且簽名要使用和目標板一致的加密公鑰。加密公鑰及加密需要的三個文件在Android源碼編譯後生成的具體路徑為:
out/host/linux-x86/framework/signapk.jar
build/target/proct/security/testkey.x509.pem
build/target/proct/security/testkey.pk8 。
我們用命令make otapackage製作生成的update.zip包是已簽過名的,如果自己做update.zip包時必須手動對其簽名。
具體的加密方法:$ java –jar gingerbread/out/host/linux/framework/signapk.jar –w gingerbread/build/target/proct/security/testkey.x509.pem gingerbread/build/target/proct/security/testkey.pk8 update.zip update_signed.zip
以上命令在update.zip包所在的路徑下執行,其中signapk.jar testkey.x509.pem以及testkey.pk8文件的引用使用絕對路徑。update.zip 是我們已經打好的包,update_signed.zip包是命令執行完生成的已經簽過名的包。
9、MANIFEST.MF:這個manifest文件定義了與包的組成結構相關的數據。類似Android應用的mainfest.xml文件。
10、CERT.RSA:與簽名文件相關聯的簽名程序塊文件,它存儲了用於簽名JAR文件的公共簽名。
11、CERT.SF:這是JAR文件的簽名文件,其中前綴CERT代表簽名者。
另外,在具體升級時,對update.zip包檢查時大致會分三步:①檢驗SF文件與RSA文件是否匹配。②檢驗MANIFEST.MF與簽名文件中的digest是否一致。③檢驗包中的文件與MANIFEST中所描述的是否一致。
三、 Android升級包update.zip的生成過程分析
1) 對於update.zip包的製作有兩種方式,即手動製作和命令生成。
第一種手動製作:即按照update.zip的目錄結構手動創建我們需要的目錄。然後將對應的文件拷貝到相應的目錄下,比如我們向系統中新加一個應用程序。可以將新增的應用拷貝到我們新建的update/system/app/下(system目錄是事先拷貝編譯源碼後生成的system目錄),打包並簽名後,拷貝到SD卡就可以使用了。這種方式在實際的tcc8800開發板中未測試成功。簽名部分未通過,可能與具體的開發板相關。
第二種製作方式:命令製作。Android源碼系統中為我們提供了製作update.zip刷機包的命令,即make otapackage。該命令在編譯源碼完成後並在源碼根目錄下執行。 具體操作方式:在源碼根目錄下執行
①$ . build/envsetup.sh。
②$ lunch 然後選擇你需要的配置(如17)。
③$ make otapackage。
在編譯完源碼後最好再執行一遍上面的①、②步防止執行③時出現未找到對應規則的錯誤提示。命令執行完成後生成的升級包所在位置在out/target/proct/full_tcc8800_evm_target_files-eng.mumu.20120309.111059.zip將這個包重新命名為update.zip,並拷貝到SD卡中即可使用。
這種方式(即完全升級)在tcc8800開發板中已測試成功。
2) 使用make otapackage命令生成update.zip的過程分析。
在源碼根目錄下執行make otapackage命令生成update.zip包主要分為兩步,第一步是根據Makefile執行編譯生成一個update原包(zip格式)。第二步是運行一個python腳本,並以上一步准備的zip包作為輸入,最終生成我們需要的升級包。下面進一步分析這兩個過程。
第一步:編譯Makefile。對應的Makefile文件所在位置:build/core/Makefile。從該文件的884行(tcc8800,gingerbread0919)開始會生成一個zip包,這個包最後會用來製作OTA package 或者filesystem image。先將這部分的對應的Makefile貼出來如下:
[python] view plainprint?
# -----------------------------------------------------------------
# A zip of the directories that map to the target filesystem.
# This zip can be used to create an OTA package or filesystem image
# as a post-build step.
#
根據上面的Makefile可以分析這個包的生成過程:
首先創建一個root_zip根目錄,並依次在此目錄下創建所需要的如下其他目錄
①創建RECOVERY目錄,並填充該目錄的內容,包括kernel的鏡像和recovery根文件系統的鏡像。此目錄最終用於生成recovery.img。
②創建並填充BOOT目錄。包含kernel和cmdline以及pagesize大小等,該目錄最終用來生成boot.img。
③向SYSTEM目錄填充system image。
④向DATA填充data image。
⑤用於生成OTA package包所需要的額外的內容。主要包括一些bin命令。
⑥創建META目錄並向該目錄下添加一些文本文件,如apkcerts.txt(描述apk文件用到的認證證書),misc_info.txt(描述Flash內存的塊大小以及boot、recovery、system、userdata等分區的大小信息)。
⑦使用保留連接選項壓縮我們在上面獲得的root_zip目錄。
⑧使用fs_config(build/tools/fs_config)配置上面的zip包內所有的系統文件(system/下各目錄、文件)的許可權屬主等信息。fs_config包含了一個頭文件#include「private/android_filesystem_config.h」。在這個頭文件中以硬編碼的方式設定了system目錄下各文件的許可權、屬主。執行完配置後會將配置後的信息以文本方式輸出 到META/filesystem_config.txt中。並再一次zip壓縮成我們最終需要的原始包。
第二步:上面的zip包只是一個編譯過程中生成的原始包。這個原始zip包在實際的編譯過程中有兩個作用,一是用來生成OTA update升級包,二是用來生成系統鏡像。在編譯過程中若生成OTA update升級包時會調用(具體位置在Makefile的1037行到1058行)一個名為ota_from_target_files的python腳本,位置在/build/tools/releasetools/ota_from_target_files。這個腳本的作用是以第一步生成的zip原始包作為輸入,最終生成可用的OTA升級zip包。
二 下面我們分析ota_from_target_files這個python腳本是怎樣生成最終zip包的。先講這個腳本的代碼貼出來如下:
[python] view plainprint?
import sys
if sys.hexversion < 0x02040000:
print >> sys.stderr, "Python 2.4 or newer is required."
sys.exit(1)
主函數main是python的入口函數,我們從main函數開始看,大概看一下main函數(腳本最後)里的流程就能知道腳本的執行過程了。
① 在main函數的開頭,首先將用戶設定的option選項存入OPTIONS變數中,它是一個python中的類。緊接著判斷有沒有額外的腳本,如果有就讀入到OPTIONS變數中。
② 解壓縮輸入的zip包,即我們在上文生成的原始zip包。然後判斷是否用到device-specific extensions(設備擴展)如果用到,隨即讀入到OPTIONS變數中。
③ 判斷是否簽名,然後判斷是否有新內容的增量源,有的話就解壓該增量源包放入一個臨時變數中(source_zip)。自此,所有的准備工作已完畢,隨即會調用該 腳本中最主要的函數WriteFullOTAPackage(input_zip,output_zip)
④ WriteFullOTAPackage函數的處理過程是先獲得腳本的生成器。默認格式是edify。然後獲得metadata元數據,此數據來至於Android的一些環境變數。然後獲得設備配置參數比如api函數的版本。然後判斷是否忽略時間戳。
⑤ WriteFullOTAPackage函數做完准備工作後就開始生成升級用的腳本文件(updater-script)了。生成腳本文件後將上一步獲得的metadata元數據寫入到輸出包out_zip。
⑥至此一個完整的update.zip升級包就生成了。生成位置在:out/target/proct/tcc8800/full_tcc8800_evm-ota-eng.mumu.20120315.155326.zip。將升級包拷貝到SD卡中就可以用來升級了。
四、 Android OTA增量包update.zip的生成
在上面的過程中生成的update.zip升級包是全部系統的升級包。大小有80M多。這對手機用戶來說,用來升級的流量是很大的。而且在實際升級中,我們只希望能夠升級我們改變的那部分內容。這就需要使用增量包來升級。生成增量包的過程也需要上文中提到的ota_from_target_files.py的參與。
下面是製作update.zip增量包的過程。
① 在源碼根目錄下依次執行下列命令
$ . build/envsetup.sh
$ lunch 選擇17
$ make
$ make otapackage
執行上面的命令後會在out/target/proct/tcc8800/下生成我們第一個系統升級包。我們先將其命名為A.zip
② 在源碼中修改我們需要改變的部分,比如修改內核配置,增加新的驅動等等。修改後再一次執行上面的命令。就會生成第二個我們修改後生成的update.zip升級包。將 其命名為B.zip。
③ 在上文中我們看了ota_from_target_files.py腳本的使用幫助,其中選項-i就是用來生成差分增量包的。使用方法是以上面的A.zip 和B.zip包作為輸入,以update.zip包作 為輸出。生成的update.zip就是我們最後需要的增量包。
具體使用方式是:將上述兩個包拷貝到源碼根目錄下,然後執行下面的命令。
$ ./build/tools/releasetools/ota_from_target_files -i A.zip B.zip update.zip。
在執行上述命令時會出現未找到recovery_api_version的錯誤。原因是在執行上面的腳本時如果使用選項i則會調用WriteIncrementalOTAPackage會從A包和B包中的META目錄下搜索misc_info.txt來讀取recovery_api_version的值。但是在執行make otapackage命令時生成的update.zip包中沒有這個目錄更沒有這個文檔。
此時我們就需要使用執行make otapackage生成的原始的zip包。這個包的位置在out/target/proct/tcc8800/obj/PACKAGING/target_files_intermediates/目錄下,它是在用命令make otapackage之後的中間生產物,是最原始的升級包。我們將兩次編譯的生成的包分別重命名為A.zip和B.zip,並拷貝到SD卡根目錄下重復執行上面的命令:
$ ./build/tools/releasetools/ota_form_target_files -i A.zip B.zip update.zip。
在上述命令即將執行完畢時,在device/telechips/common/releasetools.py會調用IncrementalOTA_InstallEnd,在這個函數中讀取包中的RADIO/bootloader.img。
而包中是沒有這個目錄和bootloader.img的。所以執行失敗,未能生成對應的update.zip。可能與我們未修改bootloader(升級firmware)有關。此問題在下一篇博客已經解決。
製作增量包失敗的原因,以及解決方案。
Android系統Recovery工作原理之使用update.zip升級過程分析(二)---update.zip差分包問題的解決
在上一篇末尾提到的生成差分包時出現的問題,現已解決,由於最近比較忙,相隔的時間也比較長,所以單列一個篇幅提示大家。這個問題居然是源碼中的問題,可能你已經製作成功了,不過我的這個問題確實是源碼中的一個問題,不知道是不是一個bug,下文會具體分析!
一、生成OTA增量包失敗的解決方案
在上一篇中末尾使用ota_from_target_files腳本製作update.zip增量包時失敗,我們先將出現的錯誤貼出來。
在執行這個腳本的最後讀取input_zip中RADIO/bootloader.img時出現錯誤,顯示DeviceSpecifiParams這個對象中沒有input_zip屬性。
我們先從腳本中出現錯誤的調用函數中開始查找。出現錯誤的調用地方是在函WriteIncrementalOTAPackage(443行)中的device_specific.IncrementalOTA_InstallEnd(),其位於WriteIncrementalOTAPackage()中的末尾。進一步跟蹤源碼發現,這是一個回調函數,他的具體執行方法位於源碼中/device/telechips/common/releasetools.py腳本中的IncrementalOTA_InstallEnd()函數。下面就分析這個函數的作用。
releasetools.py腳本中的兩個函數FullOTA_InstallEnd()和IncrementalOTA_InstallEnd()的作用都是從輸入包中讀取RADIO/下的bootloader.img文件寫到輸出包中,同時生成安裝bootloader.img時執行腳本的那部分命令。只不過一個是直接將輸入包中的bootloader.img鏡像寫到輸出包中,一個是先比較target_zip和source_zip中的bootloader.img是否不同(使用選項-i生成差分包時),然後將新的鏡像寫入輸出包中。下面先將這個函數(位於/device/telechips/common/releasetools.py)的具體實現貼出來:
我們的實際情況是,在用命令make otapackage時生成的包中是沒有這個RADIO目錄下的bootloader.img鏡像文件(因為這部分更新已被屏蔽掉了)。但是這個函數中對於從包中未讀取到bootloader.img文件的情況是有錯誤處理的,即返回。所以我們要從 出現的實際錯誤中尋找問題的原由。
真正出現錯誤的地方是:
target_bootloader=info.input_zip.read(「RADIO/bootloader.img」)。
出現錯誤的原因是:AttributeError:『DeviceSpecificParams』object has no attribute 『input_zip』,提示我們DeviceSpecificParams對象沒有input_zip這個屬性。
二、updater-script腳本執行流程分析:
先看一下在測試過程中用命令make otapackage生成的升級腳本如下:
[python] view plainprint?
assert(!less_than_int(1331176658, getprop("ro.build.date.utc")));
assert(getprop("ro.proct.device") == "tcc8800" ||
下面分析下這個腳本的執行過程:
①比較時間戳:如果升級包較舊則終止腳本的執行。
②匹配設備信息:如果和當前的設備信息不一致,則停止腳本的執行。
③顯示進度條:如果以上兩步匹配則開始顯示升級進度條。
④格式化system分區並掛載。
⑤提取包中的recovery以及system目錄下的內容到系統的/system下。
⑥為/system/bin/下的命令文件建立符號連接。
⑦設置/system/下目錄以及文件的屬性。
⑧將包中的boot.img提取到/tmp/boot.img。
⑨將/tmp/boot.img鏡像文件寫入到boot分區。
⑩完成後卸載/system。
三、總結
以上的九篇著重分析了Android系統中Recovery模式中的一種,即我們做好的update.zip包在系統更新時所走過的流程。其核心部分就是Recovery服務的工作原理。其他兩種FACTORY RESET、ENCRYPTED FILE SYSTEM ENABLE/DISABLE與OTA INSTALL是相通的。重點是要理解Recovery服務的工作原理。另外詳細分析其升級過程,對於我們在實際升級時,可以根據我們的需要做出相應的修改。
『伍』 如何手動安裝apk(不使用打包安裝程序和應用商店的root快速安裝等方法)我對Android有一
可能直接用命令安裝,首先准備需要安裝的apk文件
然後執行以下步驟:
1.將需要安裝的apk文件放在和adb應用程序的同一個文件夾中。
2.打開cmd應用程序窗口。
3.用命令進入adb的系統文件夾裡面。
4.使用命令adb install xxx.apk 回車,接下來就是等待安裝。安裝好之後會返回success。
『陸』 如何將資源打包到 /data/data/PackageName/files/ 目錄下
這個很好弄啊!你可以把文件放在assets文件夾裡面,然後直接從assets文件夾裡面拷貝到/data/data/package/files/目錄下面就成了啊!
『柒』 android app調試沒問題,但打包簽名的apk,運行時出現閃退怎麼辦
.找到Project -> Build Automatically,取消它關閉自動編譯
2.然後Clean一下
3.最後在手動Build一下
然後你再打包簽名,這樣就可以正常運行了。
『捌』 我打包android apk 安裝新版本的時候為什麼必須卸載之前卸載的版本
不是卸載之前的版本,是新版本覆蓋之前的版本,同一個版本包名一致就會覆蓋,你可以試下換個包名再安裝
『玖』 android studio 打包誰會
1)手動打包
項目寫完了,現在需要把應用上傳到市場,問題出現—怎麼把代碼變成.apk(Android的可安裝文件)。
1. 創建簽名文件
這里寫圖片描述
2. 填寫好簽名參數
這里寫圖片描述
3. 生成APK
注意:簽名的密碼和密匙的密碼注意保管,不要忘了,簽名文件別泄漏了,也別搞丟了
為什麼要打包
我最開始就有這個疑問,我們的代碼不是點了下運行按鈕就直接安裝到手機上了嗎,我們在在項目Project目錄的build/outputs/apk目錄下可以找到剛剛新鮮生成的app-debug.apk.直接把這個上傳給市場不就行了嗎。
這里寫圖片描述
NO,當然不行,想想手機安裝App的時候怎麼來區分各個APK的。
通過包名+簽名 來確定一個應用的唯一性,那個 debug.apk 只是系統用來給我們調試用的,如果上傳到市場,怎麼來保證他的安全性。
OK,我們已經解決了第一步—怎麼打包。上傳上去後,市場反饋發現我們的App寫得太棒了,這時候老大讓趕快多上些平台,主流的平台、非主流的平台都要放上去。
那麼問題來了,為了方便統計各個平台的安裝情況,配合運營推廣,需要統計各個平台的安裝情況。
分渠道打包
不錯,我們需要用到分渠道打包,那麼我們需要解決兩個問題
1. 怎麼區分各個平台的標識
2. 怎麼每次版本更新都生成幾十個包、幾百個包
第一個簡單,用過友盟打包的同學肯定不陌生這段代碼
<meta-data android:name="UMENG_CHANNEL" android:value="Channel_ID"></meta-data>
value裡面填的就是各個平台的值,比如填寫uc、yyb(應用寶)、360、替換掉Channel_ID,App安裝好,可以讀取這個值然後傳給後台,從而實現區分各個平台的安裝需求。
第二個問題:
在Eclipse時代,最開始我是手動打的,一次打30個包,每次最怕版本更新,基本一下午都在做機械運動,現在想起來手都在抽筋。
後來,學會了Ant自動打包,快倒是快,只是配置太坑爹了,超級麻煩。
現在有了Android Studio,媽媽再也不用擔心我不能愉快的打包了。
隨便新建一個項目,修改Mole:app build.gradle為
『拾』 如何將h5程序打包成android應用
H5開發的web APP和原生APP的區別有以下幾個方面: 一、開發方面 原生App ⊙ 每一種移動操作系統都需要獨立的開發項目 ⊙ 每種平台都需要獨立的開發語言。Java(Android), Objective-C(iOS)以及VisualC++(Windows Mobile)等等 ⊙ 需要使用各自的軟體開發包,開發工具以及各自的控制項 移動Web App ⊙ 因為運行在移動設備的瀏覽器上,所以只需要一個開發項目 ⊙ 這種應用可以使用HTML5,CSS3以及JavaScript以及伺服器端語言來完成(PHP,Ruby on Rails,Python) ⊙ 這里可沒有標準的SDK,基本任意選擇別忘了有一些跨平台的開發工具,比如PhoneGap, Sencha Touch 2,APPcan以及Appcelerator Titanium等等。 二、能力方面 原生App ⊙ 能夠與移動硬體設備的底層功能,比如個人信息,攝像頭以及重力加速器等等 移動Web App ⊙ 只能使用有限的移動硬體設備功能。 三、獲取方法 原生App ⊙ 直接下載到設備 ⊙ 以獨立的應用程序運行(並不需要瀏覽器) ⊙ 用戶必須手動去下載並安裝這些原生App ⊙ 有一些商店與賣場來幫助用戶尋找你的App,目前app市場不計其數 移動Web App ⊙ 從移動設備上的瀏覽器訪問 ⊙ 不需要安裝額外的軟體 ⊙ 軟體更新只需要伺服器就夠了 ⊙ 因為現在沒有什麼商品或賣場提供這種App,所以如何搜索這些移動Web App相當不簡單。 四、版本控制 原生App ⊙ 用戶可以自由地選擇是否更新軟體版本,所以會出現不同用戶同時使用不同版本的情況 移動Web App ⊙ 所有的用戶都是用同樣的版本 五、優勢 原生App ⊙ 比移動Web App運行快 ⊙ 一些商店與賣場會幫助用戶尋找原生App ⊙ 官方賣場的應用審核流程會保證讓用戶得到高質量以及安全的App ⊙ 官方會發布很多開發工具或者人工支持來幫助你的開發 移動Web App ⊙ 跨平台開發 ⊙ 用戶不需要去賣場來下載安裝App ⊙ 任何時候都可以發布App,因為根本不需要官方賣場的審核 ⊙ 如果你已經有了一個Web App,你可以使用 responsive web design來輔助改進 六、缺陷 原生App ⊙ 開發成本高,尤其是當需要多種移動設備來測試時 ⊙ 因為是不同的開發語言,所以開發,維護成本也高 ⊙ 因為用戶使用的App版本不同,所以你維護起來很困難 ⊙ 官方賣場審核流程復雜且慢,會嚴重影響你的發布進程 移動Web App ⊙ 無法使用很多移動硬體設備的獨特功能 ⊙ 要同時支持多種移動設備的瀏覽器讓開發維護的成本也不低 ⊙ 如果用戶使用更多的新型瀏覽器,那問題就更不好處理了 ⊙ 對於用戶來說,這種App很難被用戶發現 附:原生App 與 移動Web App:您如何選擇? 所以在你准備做移動App時,你應該先問問自己以下幾個問題: 1. 你的應用是否需要使用某些設備的特殊功能,比如攝像頭,攝像頭閃光燈或者重力加速器 2. 你的開發預算是多少? 3. 你的應用是否一定需要網路 4. 你的應用的目標硬體設備是所有的移動設備還是僅僅只是一部分而已 5. 你自己已經熟悉的開發語言 6. 這個應用對於性能要求是否苛刻 7. 如何靠這個應用贏利