1、打印功能
Android 4.4或者更高,该框架提供了打印图片和文档的服务
PrintHelper 类提供了一个简单的方法来打印图片。这个类有一个布局选择,setScaleMode() 方法,允许你二选一:
SCALE_MODE_FIT - - 整个图像显示在页面的打印区域
SCALE_MODE_FILL - - 填满整个页面的打印区域。选择这个设置意味着,顶部和底部的一部分,或左右图像的边缘不打印。
如果不设置模式的话,SCALE_MODE_FILL 是默认值
http://blog.youkuaiyun.com/u012301841/article/details/51707932 Training(十四) -- 打印内容
2、APP架构经验
API的安全机制
1.保证API的调用者是经过自己授权的App;
2.保证数据传输的安全。
第一个问题的解决方案,我主要采用设计签名的方式。对每个客户端,Android、iOS、WeChat,分别分配一个AppKey和AppSecret。
需要调用API时,将AppKey加入请求参数列表,并将AppSecret和所有参数一起,根据某种签名算法生成一个签名字符串,然后调用API时把该签名字符串也一起带上。
服务端收到请求之后,根据请求中的AppKey查询相应的AppSecret,按照同样的签名算法,也生成一个签名字符串,
当服务端生成的签名和请求带过来的签名一致的时候,那就表示这个请求的调用者是经过自己授权的,证明这个请求是安全的。
而且,每个端都有一个Key,也方便不同端的标识和统计。为了防止AppSecret被别人获取,这个AppSecret一般写死在代码里面。
另外,签名算法也需要有一定的复杂度,不能轻易被别人破解,最好是采用自己规定的一套签名算法,而不是采用外部公开的签名算法。
另外,在参数列表中再加入一个时间戳,还可以防止部分重放攻击。
第二个问题的解决方案,主要就是采用HTTPS了。HTTPS因为添加了SSL安全协议,自动对请求数据进行了压缩加密,
在一定程序可以防止监听、防止劫持、防止重发,主要就是防止中间人攻击。苹果从iOS9开始,默认就采用HTTPS了。
而关于在Android中如何使用HTTPS,Google官方也给出了很多安全建议。不过,大部分App并没有按照安全建议去实现,
主要就是没有对SSL证书进行安全性检查,这就成为了一个很大的漏洞,中间人利用此漏洞用假证书就可以通过检查,从而可以劫持到所有数据了。
因此,为了安全考虑,建议对SSL证书进行强校验,包括签名CA是否合法、域名是否匹配、是不是自签名证书、证书是否过期等。
http://blog.youkuaiyun.com/u014454120/article/details/51752543 app架构经验总结
3、网络解析xml,json,html框架
xml解析使用工具:在android中推荐使用pull解析,还有其他的dom,sax解析。
json解析使用工具:推荐使用Fastjson,由阿里提供。还有其他的如JackSon,Gson解析。
html解析使用工具:推荐使用Jsoup,还有其他的如HtmlParser;关于使用这个,网络上的爬虫就是这样子的。
http://blog.youkuaiyun.com/baidu_26994091/article/details/51747411 网络解析xml,json,html框架
4、AS多渠道打包和混淆
Gradle是一种依赖管理工具,基于Groovy语言,面向Java应用为主
gradle-wrapper.properties 这个文件声明了gradle的目录与下载路径以及当前项目使用的gradle版本
settings.gradle是全局的项目配置文件,里面主要声明一些需要加入gradle的module.如果还有其他module按照相同的格式加上去
//文件开头apply plugin是最新gradle版本的写法
apply plugin: 'com.android.application'
buildscript {
//声明仓库的源,这里用的是mavenCentral(), jcenter可以理解成是一个新的中央远程仓库,兼容maven中心仓库,而且性能更优
repositories {
mavenCentral()
}
//声明了android gradle plugin的版本
dependencies {
classpath 'com.android.tools.build:gradle:1.1.0'
}
}
android {
compileSdkVersion 17
buildToolsVersion "21.1.2" //需要你本地安装该版本才行
defaultConfig {
applicationId "com.lippi.recorder" //应用的包名
minSdkVersion 15
targetSdkVersion 17
versionCode 1
versionName '1.4'
// dex突破65535的限制
multiDexEnabled true
// AndroidManifest.xml 里面UMENG_CHANNEL的value为 ${UMENG_CHANNEL_VALUE}
manifestPlaceholders = [UMENG_CHANNEL_VALUE: "channel_name"]
}
sourceSets {
main {
manifest.srcFile 'src/main/AndroidManifest.xml'
java.srcDirs = ['src/main/java']
resources.srcDirs = ['src/main/resources']
aidl.srcDirs = ['src/main/aidl']
renderscript.srcDirs = ['src/maom']
res.srcDirs = ['src/main/res']
assets.srcDirs = ['src/main/assets']
jniLibs.srcDir 'src/main/jniLibs'
}
// Move the tests to tests/java, tests/res, etc...
instrumentTest.setRoot('tests')
// Move the build types to build-types/<type>
// For instance, build-types/debug/java, build-types/debug/AndroidManifest.xml, ...
// This moves them out of them default location under src/<type>/... which would
// conflict with src/ being used by the main source set.
// Adding new build types or product flavors should be accompanied
// by a similar customization.
debug.setRoot('build-types/debug')
release.setRoot('build-types/release')
}
//执行lint检查,有任何的错误或者警告提示,都会终止构建,我们可以将其关掉。
lintOptions {
abortOnError false
}
//签名
signingConfigs {
debug {
storeFile file("/home/lippi/.android/debug.keystore")
}
relealse {
//这样写就得把demo.jk文件放在项目目录
storeFile file("recorder.jks")
storePassword "recorder"
keyAlias "recorder"
keyPassword "recorder"
}
}
buildTypes {
debug {
// 显示Log
buildConfigField "boolean", "LOG_DEBUG", "true"
versionNameSuffix "-debug"
minifyEnabled false
zipAlignEnabled false
shrinkResources false
signingConfig signingConfigs.debug
}
release {
// 不显示Log
buildConfigField "boolean", "LOG_DEBUG", "false"
//混淆
minifyEnabled true
//Zipalign优化
zipAlignEnabled true
// 移除无用的resource文件
shrinkResources true
//前一部分代表系统默认的android程序的混淆文件,该文件已经包含了基本的混淆声明
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard.cfg'
//签名
signingConfig signingConfigs.relealse
}
}
//渠道Flavors,配置不同风格的app
productFlavors {
GooglePlay {}
xiaomi {}
umeng {}
_360 {}
baidu {}
wandoujia {}
}
//批量配置
productFlavors.all { flavor ->
flavor.manifestPlaceholders = [UMENG_CHANNEL_VALUE: name]
}
compileOptions {
sourceCompatibility JavaVersion.VERSION_1_7
targetCompatibility JavaVersion.VERSION_1_7
}
applicationVariants.all { variant ->
variant.outputs.each { output ->
def outputFile = output.outputFile
if (outputFile != null && outputFile.name.endsWith('.apk')) {
def fileName = outputFile.name.replace(".apk", "-${defaultConfig.versionName}.apk")
output.outputFile = new File(outputFile.parent, fileName)
}
}
}
dependencies {
compile fileTree(include: ['*.jar'], dir: 'libs') //可以理解成Android Library
compile 'org.apache.commons:commons-math:2.1'
compile 'org.slf4j:slf4j-log4j12:1.7.5'
}
http://blog.youkuaiyun.com/leeo1010/article/details/49903759 Android Studio多渠道打包和代码混淆教程
5、AIDL 和 进程间通信 Binder
AIDL的全称是Android Interface Definition Language,Android接口定义语言
如果你想实现跨进程通信,但是并不关注多线程并发处理,那么你只需要使用Messenger即可,无需编写AIDL代码,
只有当你想让Service并发处理客户端的请求的时候,才需要编写AIDL代码。
http://blog.youkuaiyun.com/iispring/article/details/51815475 AIDL实现进程通信(附源码下载)
http://blog.youkuaiyun.com/mr_lu_code/article/details/51930728 浅谈binder机制
6、Android适配
px像素,ppi屏幕像素密度,dpi屏幕密度,dp虚拟像素
在dpi为160的手机上,1dp = 1px。在240dpi的手机上,1dp就是1.5px。
通用公式可以表示为:px=(dpi/160)×dp
7、WindowManager
Window:表示一个窗口
WindowManager:它是系统提供我们操作Window的一个接口,我们可以通过WindowManage提供的方法对window进行添加、修改、删除等操作
当一个点击事件产生时,它首先传递到Activity、在Activity的dispatchToucheEvent的方法中进行分发、然后传递到Window、最后才到顶级view。
http://blog.youkuaiyun.com/qq_28702545/article/details/51990473 WindowManager的分析
8、电话监听
http://blog.youkuaiyun.com/qq_32059827/article/details/51985512 内容观察者监控黑名单号码代码模板+初级教程反射+AIDL
9、AndroidStudio使用总结
右键你的module,然后OpenModuleSetting—–>dependency———>点+号,引入v7兼容包
http://blog.youkuaiyun.com/z_zt_t/article/details/51982171 Android Studio使用总结
10、MVP +Dagger2 + DataBinding+ Rxjava+Retrofit
1.MVP 大家都知道 P的作用是让MV间接拥有肮脏的PY交易,而不是直接让他们进行交易。
2.Rxjava 响应式编程 0.0 一个特别屌的地方就是你可以随便切换线程
3.Retrofit 代替Volley的东东
4.Dagger2 Android 的IOC框架,即控制反转,也叫依赖注入
4.DataBinding MVVM的东东,用起来比较方便,可以让bean与View绑定,抛弃setText()!
http://blog.youkuaiyun.com/wingichoy/article/details/51981756
11、泛型
泛型的出现避免了强转,并且把错误转移到了编译时期
泛型类,泛型方法,泛型接口
通配符?可以任意类型
泛型限定:
上限:声明对象: 类名称<? extends Person>对象名称
声明类:访问权限 类名称<泛型标识 extends 类>
这个尖括号里必须是person或者person的子类.就是你传过来的集合元素类型可以是person或者person的子类
下限:
声明对象: 类名称<? super Person>对象名称
这个尖括号里必须是person或者person的父类.就是你传过来的集合元素类型可以是person或者person的父类
泛型数组
public static <T> T[] fun1(T...arg){}
http://blog.youkuaiyun.com/a910626/article/details/51970827 夯实基础系列:泛型
12、自定义键盘代码
http://download.csdn.NET/detail/xinnian25/8531185
13、时间轴
一种方式,使用ListView实现,另一种使用动态添加View
http://jcodecraeer.com/a/anzhuokaifa/androidkaifa/2016/0121/3902.html 时间轴布局(LinearLayout)
14、更改状态栏和虚拟键等
if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
Window window = getWindow();
window.clearFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS
| WindowManager.LayoutParams.FLAG_TRANSLUCENT_NAVIGATION);
window.getDecorView().setSystemUiVisibility(View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN
| View.SYSTEM_UI_FLAG_LAYOUT_STABLE);
window.addFlags(WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS);
window.setStatusBarColor(Color.TRANSPARENT);
// window.setNavigationBarColor(Color.TRANSPARENT);
}