① 安卓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