① 安卓11腳本不工作
解析度不合適,運行內存不夠。自動停止的原因有很多,比如解析度不合適,運行內存不夠等,建議使用電腦來掛機,下載雷電安卓模擬器,可以自行修改解析度,CPU以及內存,可以24小時穩定掛機。安卓腳本就是一段可以讓Android手機自動執行某些操作的程序。
② 創造 | 一個強大的 Android 自動化打包腳本
該腳本是我在獨立開發過程中,為了提升 Android 應用打包和運營的效率而開發的腳本。項目地址是,
https://github.com/Shouheng88/autopackage
如項目中的語言構成展示的,該腳本完全使用 Python 語言開發完成。
使用起來非常簡單,首先你要准備如下的環境,
然後,通過編輯配置文件 config.yml 對腳本進行配置。比如,
YAML 格式也不算新穎,早在幾年之前的 SpringBoot 裡面就已經採用了這種格式。相比於使用 json 或者 properties 等格式的配置文件,它更加簡潔。
1、使用 gradle 指令自動打包,區分 32 位和 64 位 :因為現在有些應用市場明確要求區分 32 位和 64 位,所以,打包的時候要分開進行打包。
2、打包完成之後將 APK 拷貝到指定的目錄 :主要用來做本地的 APK 文件備份,後面也會用這里拷貝的 APK 文件進行自動化加固。
3、使用 diffuse 輸出相對於上一個版本的 APK 版本差異報告 :diffuse 是 JakeWharton 開發的 APK, AAB, AAR 和 JAR 的對比工具。這里我用它對比當前版本和上一個版本的 APK 的信息,以實現對 APK 質量的監控。diffuse 項目的地址是 https://github.com/JakeWharton/diffuse
3、拷貝多語言資源到指定的目錄,並自動提交到 Github 倉庫以便於協助翻譯 :對做國際化的應用的開發者而言,我們可以通過應用內的協助翻譯功能藉助社區的力量實現應用的多語言。這里我盡量將這個過程做得更加自動化。即在應用打包完成之後將應用內的多語言資源按照版本信息拷貝到指定的目錄下。然後使用 Git 工具將其推送到 Github 等。具體的效果可以參考 https://github.com/Shouheng88/LeafNote-Community .
4、自動打 tag 並提交到遠程倉庫 :該功能用來在打包完成之後使用為當前版本添加 Git tag,以便於後續根據版本回滾到指定的 Git 提交記錄。
5、根據 Git 提交記錄自動生成更新日誌 :上面做了為項目自動添加 Git tag 的功能之後,我們可以根據當前版本到上一版本之間的 Git 提交記錄的 comment 信息自動生成版本更新日誌。雖然,這個這樣生成的更新日誌並不能直接用作發布時的更新記錄,但在至少可以讓我們直觀得看到這個版本修改了什麼。
6、使用 360 加固 對上述 APK 進行加固並輸出到指定的目錄 :加固操作其實非常簡單,只需要一個 command 指令就可以完成了,
不過在使用上述命令之前需要先通過 GUI 的形式修改你在 360 加固中的渠道和簽名信息(直接手動改文件也可以)。
7、上傳打包 APK 到藍奏雲 :藍奏雲是現在很多開發者用來分享軟體的一個雲存儲平台,100M 以下的文件可以免費存儲,類似於網路雲。上傳藍奏雲之前需要先修改配置文件,
這里需要填入的 ylogin 和 phpdisk_info 可以在登錄之後通過 Chrome 的開發工具查看 cookie 信息得到。目前能夠做到自動化的一個方案就是使用上述兩個信息。
8、通過 Telegram bot 將打包完成的渠道包和更新日誌信息發送到 Telegram 群組 :對海外的用戶我們可以通過 Telegram 作為一個交流的渠道。Telegram 是一個非常好用的聊天軟體。它提供了 bot 功能,即一個可以推送消息的機器人。我們可以通過這個功能來在群組中推送消息、圖片和文件。Telegram 的 bot 有非常強大的自定義性。其實我們完全可以基於爬蟲和 bot 維護一個社區,然後通過在社區內推送廣告來獲得一些利益。這也不失為一個賺錢的渠道。使用 Telegram bot 之前需要在配置文件中填入如下信息,
這里的 token 是注冊 bot 的時候得到的信息。chat_id 可以通過如下方式獲取到:
即將 token 信息填入到上述 <YourBOTToken> 處。在返回的 json 結果中可以獲取到 chat id 信息。
向群組推送信息的方式非常簡單,一個 http 請求即可完成,
更多的協議可以參考這個文檔: https://core.telegram.org/bots/api#senddocument
9、完成上述操作之後使用郵件通知打包結果 :最後就是在完成了最終的打包操作之後通過 Email 發送一封郵件,內部包含了本次打包的 diff 信息等給指定的用戶。使用郵件功能需要在配置文件中填寫,
這里我們使用的是 QQ 郵箱來發送郵件。這里需要填寫的 user 和 password 欄位分別是郵箱和開通 smtp 服務時系統提供的密碼信息。QQ 郵箱開通 SMTP 伺服器其 官方文檔 即可。
上述是該打包腳本的主要功能。後續我會添加更多功能。因為時間有限,有些功能需要修改一下才能使用。不過,許多功能我都封裝成了獨立的 Python 腳本,如果需要的話可以自己做細微的修改。對於這個腳本,如果你有更好的建議和想法,可以跟我交流~
③ Android內存相關知識點總結
@ toc
Java的內存模型大致可以分為5個部分,分別是堆、方法區、虛擬機棧、本地方法棧、程序計數器。其中堆里主要存放創建的對象;方法區里存放載入的類信息、定義的常量以及靜態變數信息;虛擬機棧主要是一個個的幀幀;本地方法棧與虛擬機棧差不多,也是存放棧幀,但它存放的是本地方法的棧幀;程序計數器,用來存放機器碼執行的行數。Java內存模型如下圖所示,其中==虛擬機棧、本地方法棧、程序計數器為線程私有的內存區域,而堆與方法區是線程共享的內存區域==。
虛擬機棧中的棧幀,主要存放一個方法的局部變數表、操作數、動態鏈接和返回地址。
新生代的對象在創建不久後就不再使用。
老年代的對象會存活很長時間。
當對象的引用數量為0時,該對象就可以被JVM回收了。引用計數法一般在不商用的JVM中使用,其==無法解決循環引用場景==。
分析對象是否有一條到達GcRoots的鏈路,如果沒有可達路徑時,對象可以被JVM回收。
當使用GC-Roots分析發現一個對象不可達時,會進行一次標記,並進行一次篩選,篩選的條件為對象是否有必要執行finalize方法。當前對象沒有重寫finalize方法或其finalze方法已經被執行過這兩種情況被虛擬機視為「沒有必要執行」。
對於要執行finalize方法的對象,會放置到一個叫做F-Queue的隊列,並在稍等由虛擬機自動建立一個低優先順序的線程Finalizer來執行這些finalize方法。這里的執行是批虛擬機會觸發這些方法,但不保證要等待它執行完畢,原因是一個對象的finalize方法里執行了耗時工作、或發現了死循環,會導致整個Finalizer線程阻塞。
對象要自我拯救,可以在finalize方法里將this賦值到一個GC-Roots關聯著的對象之上,此時在GC-Roots鏈路上對象是可達的,對象就會從可回收區域移出,但當對象再次不可達時,自我拯救失效,因為finalize方法已經執行過一次,不會再被執行。
對象引用有4種,分別是強引用、軟引用、弱引用和虛引用,引用的強度依次遞減。
正常使用對象的方式都是強引用,如將對象賦值給一個變數。
軟引用的引用強度為強引用稍弱一些。對於軟引用關聯的對象,在系統發生內存溢出之前,會將這些對象列進回收范圍之中進行第二次回收。
使用 SoftReferece<Object>
弱引用比軟引用的引用強度還要弱一些,關聯的對象只能生存到下一次系統回收之前。當垃圾收集器工作時,無論當前內存中否足夠,都會回收掉只被弱引用關聯的對象。使用方式 WeakReference<Object>
虛引用的對對象引用最弱。一對象是否有虛引用對象關聯,完全不會影響其生存時間,也無法通過虛引用來取得一個對象實例。為對象設置虛引用關聯的唯一目的就是能在這個對象被系統回收時收到一個系統通知。
此演算法分為「標記」和「清除」兩個階段:首先標記出哪些對象需要進行回收,在標記完成後統一進行回收。
將兩個平分成兩個部分,一部分內存被用完時,將還存活的對象依次復制到另一塊內存,並清除當前內存區域。
標記-整理演算法與標記-清除演算法一樣,也分兩個階段,首先標記出哪些對象需要回收,然後再對要回收的對象進行整理,將所有存活的對象都移向一端,然後直接清理掉邊界以外的內存。
分代收集演算法並不是一種新的收集演算法,而根據內存區域的分類,使用不同的收集演算法。根據對象存活周期不同,將內存劃分為幾塊。一般把Java內存劃分為新生代和老年代,這樣就可以根據各個代的特點使用不同的收集演算法。在新生代每次垃圾回收時發現有大量對象死去,只有少量存活,那就選擇復制演算法,只需要少量的復制操成本即可完成收集。在老年代,因對象存活率較高,就使用標記-清除或標記整理演算法來進行回收。
對象生命周期結束後,依賴被其他對象持有,導致對象不能被JVM回收,造成內存泄漏。
內存泄漏的最終結果是內存溢出,而內存溢出並不一定是由於內存泄漏導致。
④ 怎麼持續監控安卓應用程序得內存
查看內存使用情況
我常用的查看內存使用情況的兩種方式:
1、使用命令:adbshellmpsysmeminfo$package_nameor$pid
⑤ Android的內存簡單總結
內存(Memory)是計算機的重要部件,也稱內存儲器和主存儲器,它用於暫時存放CPU中的運算數據,以及與硬碟等外部存儲器交換的數據。它是外存與CPU進行溝通的橋梁,計算機中所有程序的運行都在內存中進行,內存性能的強弱影響計算機整體發揮的水平。只要計算機開始運行,操作系統就會把需要運算的數據從內存調到CPU中進行運算,當運算完成,CPU將結果傳送出來。
CPU只能訪問其寄存器(Register)和內存(Memory), 無法直接訪問硬碟(Disk)。 存儲在硬碟上的數據必須首先傳輸到內存中才能被CPU訪問。從訪問速度來看,對寄存器的訪問非常快,通常為1納秒; 對內存的訪問相對較慢,通常為100納秒(使用緩存加速的情況下);而對硬碟驅動器的訪問速度最慢,通常為10毫秒。
當一個程序載入到內存中時,它由四個內存區域組成:
RAM 分為多個「頁面」。通常,每個頁面為 4KB 的內存。 系統會將頁面視為「可用」或「已使用」。可用頁面是未使用的 RAM。已使用的頁面是系統目前正在使用的 RAM,並分為以下類別:
內核交換守護進程 ( kswapd ) 是 Linux 內核的一部分,用於將已使用內存轉換為可用內存。當設備上的可用內存不足時,該守護進程將變為活動狀態。Linux 內核設有可用內存上下限閾值。當可用內存降至下限閾值以下時, kswapd 開始回收內存。當可用內存達到上限閾值時, kswapd 停止回收內存。
當 kswapd 無法為系統釋放足夠的內存時,系統會使用 onTrimMemory() 通知應用內存不足(通過繼承 ComponentCallbacks2 可以監聽到此回調,這時對不可見,不關鍵的資源進行釋放,如Glide在收到此回調時會對緩存的圖片進行釋放),應該減少其分配量。如果內存依舊不足,內核會終止LRU中的進程以釋放內存。它會使用低內存終止守護進程 (LMK) 來執行此操作。
LMK 使用一個名為 oom_adj_score 的「內存不足」分值來確定正在運行的進程的優先順序,以此決定要終止的進程。最高得分的進程最先被終止。後台應用最先被終止,系統進程最後被終止。
終止順序:
Android 內存管理機制
內存管理概覽
管理應用內存
認真分析mmap:是什麼 為什麼 怎麼用
談談Android的內存管理機制
ART堆大小設置及動態調整過程分析(Android 8.1
進程間的內存分配
查看基於Android 系統單個進程內存、CPU使用情況的幾種方法
⑥ 開發:安卓如何修改內存數據
android源碼下
修改內存閥值的方法為:
第一步:首先建立一個XXX.txt文件,輸入以下代碼:
#!/system/bin/sh
echo
"1536,2048,4096,6144,8192,12288"
>
/sys/mole/lowmemorykiller/parameters/minfree
;
這個代碼是基於MFM配置3對應的數值。
然後保存,將保存好的XXX.txt文件修改為67-Jasonfix
將這個67-Jasonfix文件用RE管理器放入system/etc/init.d下(這個文件夾裡面都是開機腳本設定。
然後將許可權改為:全部打鉤。
第二步:修改install-recovery.sh(在system/etc目錄下)
(1).找到這些腳本所在行
sh
/system/etc/init.d/XXXXX
對應加入
sh
/system/etc/init.d/67-Jason
(2).然後找到
echo
A,B,C,D,E,F
/sys/mole/lowmemorykiller/parameters/minfree
刪除這行並保存即可。
⑦ 如何讓Android系統或Android應用執行shell腳本
一、Android應用啟動服務執行腳本
1 如何寫服務和腳本
在android源碼根目錄下有/device/tegatech/tegav2/init.rc文件相信大家對這個文件都不陌生(如果不明白就仔細研讀下android啟動流程)。如果在該腳本文件中添加諸如以下服務:
service usblp_test /data/setip/init.usblpmod.sh
oneshot
disabled
註解:每個設備下都會有自己對應的init.rc,init.設備名.rc腳本文件。oneshot disabled向我們說明了在系統啟動的時候這個服務是不會自動啟動的。並且該服務的目的是執行/data/setip/init.usblpmod.sh腳本。腳本的內容你可以隨便寫,只要符合shell語法就可以了,比如腳本可以是簡單的設置eth0:
# ! /system/bin/sh //腳本的開頭必須這樣寫。
Ifconfig eth0 172.16.100.206 netmask 255.255.0.0 up//設置ip的命令
2、如何在應用中啟動服務
1)首先了解下在服務啟動的流程
1. 在你的應用中讓init.rc中添加的服務啟動起來。
首先了解下在服務啟動的流程:
在設備目錄下的init.c(切記並不是system/core/init/init.rc)
Main函數的for(;;)循環中有一個handle_property_set_fd(),函數:
for (i = 0; i < fd_count; i++) {
if (ufds[i].revents == POLLIN) {
if (ufds[i].fd == get_property_set_fd())
handle_property_set_fd();
else if (ufds[i].fd == get_keychord_fd())
handle_keychord();
else if (ufds[i].fd == get_signal_fd())
handle_signal();
}
}
這個函數的實現也在system/core/init目錄下,該函數中的check_control_perms(msg.value, cr.uid, cr.gid)函數就是檢查該uid是否有許可權啟動服務(msg.value就是你服務的名字),如果應用為root或system用戶則直接返回1.之後就是調用handle_control_message((char*) msg.name + 4, (char*) msg.value),該函數的參數就是去掉1.ctl.後的start和2.你服務的名字。這個函數的詳細內容:
void handle_control_message(const char *msg, const char *arg)
{
if (!strcmp(msg,"start")) {
msg_start(arg);
} else if (!strcmp(msg,"stop")) {
msg_stop(arg);
} else if (!strcmp(msg,"restart")) {
msg_stop(arg);
msg_start(arg);
} else {
ERROR("unknown control msg '%s'\n", msg);
}
}
匹配start後調用msg_start.服務就這樣起來了,我們的解決方案就是在檢查許可權的地方「下點功夫」,因為我們不確定uid,所以就讓check_control_perms這個函數不要檢查我們的uid,直接檢查我們服務的名字,看看這個函數:
static int check_control_perms(const char *name, unsigned int uid, unsigned int gid) {
int i;
if (uid == AID_SYSTEM || uid == AID_ROOT)
return 1;
/* Search the ACL */
for (i = 0; control_perms[i].service; i++) {
if (strcmp(control_perms[i].service, name) == 0) {
if ((uid && control_perms[i].uid == uid) ||
(gid && control_perms[i].gid == gid)) {
return 1;
}
}
}
return 0;
}
這個函數裡面是必須要檢查uid的,我們只要在for循環上寫上。
if(strcmp(「usblp_test」,name)==0) //usblp_test就是我們服務的名字。
return 1;
這樣做不會破壞android原本的結構,不會有什麼副作用。
init.c和init.rc都改好了,現在就可以編譯源碼了,編譯好了裝到機子開發板上就可以了
⑧ android studio怎樣配置gradle內存
//設置腳本的運行環境
buildscript {
//支持java 依賴庫管理(maven/ivy),用於項目的依賴。
repositories {
mavenCentral()
}
//依賴包的定義。支持maven/ivy,遠程,本地庫,也支持單文件
dependencies {
classpath 'com.android.tools.build:gradle:0.4'
}
}
//聲明構建的項目類型,這里當然是android了
apply plugin: 'android'
//設置編譯android項目的參數
android {
compileSdkVersion 17
buildToolsVersion "17"
defaultConfig {
minSdkVersion 8
targetSdkVersion 17
}
//Android默認配置
sourceSets {
main {
manifest.srcFile 'AndroidManifest.xml'
java.srcDirs = ['src']
resources.srcDirs = ['src']
aidl.srcDirs = ['src']
renderscript.srcDirs = ['src']
res.srcDirs = ['res']
assets.srcDirs = ['assets']
}
//測試所在的路徑,這里假設是tests文件夾,沒有可以不寫這一行
instrumentTest.setRoot('tests')
}
//這個是解決lint報錯的代碼
lintOptions {
abortOnError false
}
/**
* 簽名設置
*/
signingConfigs {
myConfigs {
storeFile file("簽名文件地址")
keyAlias "..."
keyPassword "..."
storePassword "..."
}
}
/**
* 混淆設置
*/
buildTypes {
release {
signingConfig signingConfigs.myConfigs
runProguard true
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
}
}
/**
* 渠道打包(不同包名)
*/
proctFlavors {
qqqq {
applicationId = '包名'
}
hhhhh {
applicationId='包名'
}
}
}
/**
* .so文件的導入
*/
task NativeLibs(type: Copy) {
from fileTree(dir: 'libs', include: 'armeabi/*.so') into 'build/lib'
}
tasks.withType(Compile) {
options.encoding = "UTF-8"
}
tasks.withType(Compile) {
compileTask -> compileTask.dependsOn NativeLibs
}
clean.dependsOn 'cleanCopyNativeLibs'
tasks.withType(com.android.build.gradle.tasks.PackageApplication) { pkgTask ->
pkgTask.jniFolders = [new File(buildDir, 'lib')]
}
//依賴庫
dependencies {
compile fileTree(dir: 'libs', include: ['*.jar'])
}
gradle 作為構建工具,能夠很方便的使用本地jar包,以下為使用的代碼塊。
ependencies {
//單文件依賴
compile files('libs/android-support-v4.jar')
//某個文件夾下面全部依賴
compile fileTree(dir: 'libs', include: '*.jar')
}
android {
}
gradle 同時支持maven,ivy,由於ivy我沒用過,所以用maven 作為例子,以下為代碼塊:
repositories {
//從中央庫裡面獲取依賴
mavenCentral()
//或者使用指定的本地maven 庫
maven{
url "file://F:/githubrepo/releases"
}
//或者使用指定的遠程maven庫
maven{
url "遠程庫地址"
}
}
dependencies {
//應用格式: packageName:artifactId:version
compile 'com.google.android:support-v4:r13'}
android {
}
對
於項目依賴 android library的話,就不是依賴一個jar,那麼簡單了,在這里需要使用gradle mulit project
機制。在過去,android library並沒有一個很好的包管理方式,簡單來說,在gradle出現以前,官方並沒有一種用於管理android
library 依賴包的方式,一般我們都是直接下載別人的android library project
源碼進行集成,而對於第三方的android-maven-plugin 用的是apklib 格式。
而現在,官方終於推出一種android
library的打包格式,擴展名為*.aar。前面提到,目前android
gradle插件並不支持本地直接使用*.aar文件,不過,支持包管理庫的引用方式,下面,我為大家說一下,怎麼對android library
發布使用。
打包android library
對android library
進行打包直接在library項目下面使用gradle build 即可,然後,你就會在 build/libs
目錄下看到兩個*.aar文件,一個debug包用的,一個是release 下用的,看個人需求使用,這里我們用的是release 版本的 .aar文件。ITJOB祝你成就開發夢!!
⑨ 如何讓Android系統或Android應用執行shell腳本
android系統執行shell腳本,需要首先確認用戶具有修改shell的許可權,使用 process來執行指令,如下代碼:
publicvoidexecShell(Stringcmd){
try{
//許可權設置
Processp=Runtime.getRuntime().exec("su");//開始執行shell腳本
//獲取輸出流
OutputStreamoutputStream=p.getOutputStream();
=newDataOutputStream(outputStream);
//將命令寫入
dataOutputStream.writeBytes(cmd);
//提交命令
dataOutputStream.flush();
//關閉流操作
dataOutputStream.close();
outputStream.close();
}
catch(Throwablet)
{
t.printStackTrace();
}
}
⑩ android系統中查看內存信息
看下大致內存使用情況 (free+buffers+cached)
proc/meminfo 機器的內存使用信息
/proc/pid/maps pid為進程號,顯示當前進程所佔用的虛擬地址。
/proc/pid/statm 進程所佔用的內存
df 查看 存儲空間使用情況
ps -t |grep system_server (或 surfaceflinger, service manager, media server,zygote) ( 倒數第二個是不是 s) 異常情況有如』D』, 『T』, 『Z』 , 『R』等
mpsys meminfo com.android.mms 列印一個app的mem信息
從以上列印可以看出,一般來說內存佔用大小有如下規律:VSS >= RSS >= PSS >= USS
VSS - Virtual Set Size 虛擬耗用內存(包含共享庫佔用的內存)是單個進程全部可訪問的地址空間
RSS - Resident Set Size 實際使用物理內存(包含共享庫佔用的內存)是單個進程實際佔用的內存大小,對於單個共享庫, 盡管無論多少個進程使用,實際該共享庫只會被裝入內存一次。
PSS - Proportional Set Size 實際使用的物理內存(比例分配共享庫佔用的內存)
USS - Unique Set Size 進程獨自佔用的物理內存(不包含共享庫佔用的內存)
USS 是針對某個進程開始有可疑內存泄露的情況,進行檢測的最佳數字。懷疑某個程序有內存泄露可以查看這個值是否一直有增加
使用mpsys meminfo查看內存信息
腳本:
adb shell ps -t> tsq/ps.txt
adb shell top -t -m 5 -n 2 > tsq/top.txt
adb shell service list > tsq/serviceList.txt
adb shell cat /proc/meminfo >tsq/meminfo
adb shell cat /proc/buddyinfo >tsq/buddyinfo
adb shell procrank > tsq/procrank.txt
adb shell cat proc/sched_debug >tsq/sched_debug.txt
adb shell cat proc/interrupts >tsq/interrupts.txt
adb shell mpstate > tsq/mpstate.txt
adb shell bugreport > tsq/bugreport.txt
@echo "finish."
pause