Android Studio 指定签名证书文件
1.先参照Android Studio中创建keystore生成指定的证书文件。
2.在app/build.gradle文件中增加signingConfigs
字段:如下所示:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 |
apply plugin: 'com.android.application' android { compileSdkVersion 21 buildToolsVersion "21.1.0" defaultConfig { applicationId "com.test.example" minSdkVersion 14 targetSdkVersion 21 versionCode 1 versionName "1.0" } signingConfigs { debug { File strFile = new File("../../Keystore/Debug/debug.jks") storeFile file(strFile) storePassword "storeDebug1234567890" keyAlias "debugkey" keyPassword "aliasDebug1234567890" //println strFile.absolutePath; } release { File strFile = new File("../../Keystore/Release/release.jks") storeFile file(strFile) storePassword "storeRelease1234567890" keyPassword "keyRelease1234567890" keyAlias "releasekey" // println strFile.absolutePath; } } buildTypes { release { signingConfig signingConfigs.release runProguard false proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' } } } |
注意
1.storeFile
,storePassword
,keyAlias
,keyPassword
缺一不可,都必须填写,并且填写正确。
如果没有填写keyAlias
,则签名时候会报告Android-APK signing error : Failed to read key from keystore
密码不正确的时候,会报告java.security.UnrecoverableKeyException: Cannot recover key
This exception may result from the fact that you had provided a key password that was different from the keystore password
2.对于Release
配置,在buildTypes
中必须指定
1 |
signingConfig signingConfigs.release |
否则,会出现
1 |
Error: The apk for your currently selected variant(app-release-unsigned.apk) is not signed. please specify a signing configuration for this variant(release) |
3.signingConfigs
必须在buildTypes
前面声明,否则会出现找不到配置选项的错误。
查看Keystore文件的签名信息/检查APK文件中的签名信息
-
查看 keystore文件的签名信息
1 |
$ keytool -list -v -keystore keystoreName -storepass keystorePassword |
-
检查APK文件中的签名信息
解压出apk中META-INF目录下的CERT.RSA文件,然后用keytool即可查看签名信息:
1 |
$ keytool -printcert -file CERT.RSA |
-
比对签名是否一致
验证APK的签名是不是我们给定的签名文件的签名。
1.解压出apk中META-INF目录下的CERT.RSA文件.
2.执行如下命令:
Windows:
1 2 3 |
$ keytool -printcert -file CERT.RSA | findstr MD5 $ keytool -list -v -keystore keystoreName -storepass keystorePassword | findstr MD5 |
Linux:
1 2 3 |
$ keytool -printcert -file CERT.RSA | grep MD5 $ keytool -list -v -keystore keystoreName -storepass keystorePassword | grep MD5 |
比较两者输出的MD5字符串,是否一致即可。
Android Studio 1.5使用junit单元测试,以及“Test running startedTest running failed: Instrumentation run failed due to 'java.lang.RuntimeException' Empty test suite”
Android Studio 1.5创建的工程,会生成两个默认的测试目录:test
,androidTest
,其中,test
目录为在本机执行单元测试代码的目录,androidTest
为在Android设备上执行单元测试代码的目录。
目录如下图所示:
对于新建的工程,默认会生成相应的测试代码例子。如下图所示:
请注意上图的两个文件图标的差别,一个文件的图标的右上角是两个三角标记,另一个文件的右下角是个时钟的标记。
右击androidTest
目录下的ApplicationTest.java
,就会出现执行测试用例的菜单。如下图:
但是当右击test
目录下的ExampleUnitTest.java
则没有任何的运行菜单。如下图:
那么,如何执行test
目录下的ExampleUnitTest.java
呢?
操作方法为"View"
->"Tool Windows"
->"Build Variants"
,然后,切换Test Artifact
从Android Instrumentation Tests
到Unit Tests
。
如下图:
切换Test Artifact
可以看到,切换完成后,两个文件的图标互换了一下:
此时右击test
目录下的ExampleUnitTest.java
则会出现Run 'ExampleUnitTest'
,Debug 'ExampleUnitTest'
的菜单了。
如下图:
至于
1 2 |
Test running startedTest running failed: Instrumentation run failed due to 'java.lang.RuntimeException' Empty test suite |
这个问题,是由于Android Studio 的BUG,导致的,一般是没有执行上述的切换命令,然后右击test
目录下的ExampleUnitTest.java
依旧会出现Run 'ExampleUnitTest'
,Debug 'ExampleUnitTest'
的菜单,然后点击后,会让我们选择运行的设备,这个时候,明显是把我们当作可以在设备上运行的测试用例了,因此,找不到是必然的。
应对这个BUG的解决方法,就是清理代码,然后重新加载工程,一般可以解决这个问题了。
Android Studio编译报错“java.lang.OutOfMemoryError: GC overhead limit exceeded”
Android Studio编译报错 java.lang.OutOfMemoryError: GC overhead limit exceeded
详细的崩溃信息如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 |
UNEXPECTED TOP-LEVEL ERROR: java.lang.OutOfMemoryError: GC overhead limit exceeded at com.android.dx.cf.code.RopperMachine.getSources(RopperMachine.java:665) at com.android.dx.cf.code.RopperMachine.run(RopperMachine.java:288) at com.android.dx.cf.code.Simulator$SimVisitor.visitLocal(Simulator.java:612) at com.android.dx.cf.code.BytecodeArray.parseInstruction(BytecodeArray.java:412) at com.android.dx.cf.code.Simulator.simulate(Simulator.java:94) at com.android.dx.cf.code.Ropper.processBlock(Ropper.java:782) at com.android.dx.cf.code.Ropper.doit(Ropper.java:737) at com.android.dx.cf.code.Ropper.convert(Ropper.java:346) at com.android.dx.dex.cf.CfTranslator.processMethods(CfTranslator.java:282) at com.android.dx.dex.cf.CfTranslator.translate0(CfTranslator.java:139) at com.android.dx.dex.cf.CfTranslator.translate(CfTranslator.java:94) at com.android.dx.command.dexer.Main.processClass(Main.java:682) at com.android.dx.command.dexer.Main.processFileBytes(Main.java:634) at com.android.dx.command.dexer.Main.access$600(Main.java:78) at com.android.dx.command.dexer.Main$1.processFileBytes(Main.java:572) at com.android.dx.cf.direct.ClassPathOpener.processArchive(ClassPathOpener.java:284) at com.android.dx.cf.direct.ClassPathOpener.processOne(ClassPathOpener.java:166) at com.android.dx.cf.direct.ClassPathOpener.process(ClassPathOpener.java:144) at com.android.dx.command.dexer.Main.processOne(Main.java:596) at com.android.dx.command.dexer.Main.processAllFiles(Main.java:498) at com.android.dx.command.dexer.Main.runMonoDex(Main.java:264) at com.android.dx.command.dexer.Main.run(Main.java:230) at com.android.dx.command.dexer.Main.main(Main.java:199) at com.android.dx.command.Main.main(Main.java:103) |
解决方法:
- 如果在整个工程中生效,则在build.gradle中增加如下配置:
12345678android {..............dexOptions {incremental truejavaMaxHeapSize "4g"}...............} - 如果只在单元测试的时候生效,则在build.gradle中增加如下配置:
12345678910android {..............testOptions {android.dexOptions {incremental truejavaMaxHeapSize "4g"}}...............}
Android Studio 1.5增加Stacktrace或debug选项输出详细编译错误
Android Studio 编译工程的时候,如果出现错误,会打印如下信息:
1 2 3 4 5 6 7 8 9 10 11 |
:myapp:processDebugResources FAILED FAILURE: Build failed with an exception. * What went wrong: Execution failed for task ':app:processDebugResources'. ... ... * Try: Run with --stacktrace option to get the stack trace. Run with --info or --debug option to get more log outp |
最后会提示,增加--stacktrace
,--info
或 --debug
来获取更加详细的信息。
那么如何设置这些参数呢?如下操作即可:
"Android Studio"
->"preferences-Build, Execution, Deployment"
->"Compiler"
如下图所示:
com.android.dex.DexIndexOverflowException
现象描述
注意,本文描述的方案,仅在Android Studio 1.5,Gradle插件版本1.3.1中测试成立!
同时在工程中引入了多个第三方jar包,导致调用的方法数超过了android设定的65536个(DEX 64K problem),进而导致dex无法生成,也就无法生成APK文件。
编译时候产生如下的异常信息:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
Error:Execution failed for task ':xxx:dexRelease'. > com.android.ide.common.internal.LoggedErrorException: Failed to run command: C:\Android\sdk\android-sdk\build-tools\23.0.1\dx.bat --dex --output D:\Source\android\build\intermediates\dex\release --input-list=D:\Source\android\build\intermediates\tmp\dex\release\inputList.txt Error Code: Output: UNEXPECTED TOP-LEVEL EXCEPTION: com.android.dex.DexIndexOverflowException: method ID not in [0, 0xffff]: 65536 at com.android.dx.merge.DexMerger$6.updateIndex(DexMerger.java:502) at com.android.dx.merge.DexMerger$IdMerger.mergeSorted(DexMerger.java:277) at com.android.dx.merge.DexMerger.mergeMethodIds(DexMerger.java:491) at com.android.dx.merge.DexMerger.mergeDexes(DexMerger.java:168) at com.android.dx.merge.DexMerger.merge(DexMerger.java:189) at com.android.dx.command.dexer.Main.mergeLibraryDexBuffers(Main.java:454) at com.android.dx.command.dexer.Main.runMonoDex(Main.java:302) at com.android.dx.command.dexer.Main.run(Main.java:245) at com.android.dx.command.dexer.Main.main(Main.java:214) at com.android.dx.command.Main.main(Main.java:106) |
解决方案
Google给出的解决方案就是使用MultiDexApplication
-
Multidex Apps
1.在项目的build.gradle文件的dependencies 节中添加分包设置:
12345dependencies {...compile 'com.android.support:multidex:1.0.1'...}2.通过在defaultConfig节中设置multiDexEnabled标签为true,开启multi-dexing支持.
12345defaultConfig {...multiDexEnabled true...}3.如果没有创建自己的
Application.class
,直接在AndroidManifest.xml
文件的Application声明中添加:1android:name="android.support.multidex.MultiDexApplication"如果实现了自己的
Application.class
,则修改继承的父类为
android.support.multidex.MultiDex.MultiDexApplication
-
Multidex Apps单元测试
1.在项目的build.gradle文件的dependencies 节中添加分包设置:
12345dependencies {...androidTestCompile 'com.android.support:multidex-instrumentation:1.0.1'...}2.通过在defaultConfig节中设置multiDexEnabled标签为true,开启multi-dexing支持.
123456defaultConfig {...multiDexEnabled truetestInstrumentationRunner "com.android.test.runner.MultiDexTestRunner"...}
参考链接
JS-call apply bind
经常碰到JS中的这三兄弟,记一下他们的用法和区别。
1.改变函数上下文
2.就算不为了改变,但JS那坑爹的作用域下,也为了能够明确知道函数上下文
(为什么要改变请参考JS的作用域链)
区别:
call与apply
call与apply用法很相似,区别就是一个是一个一个传参数,一个是传一个参数数组
fun().call(object, p1, p2);
fun().apply(object, [p1,p2]);
或者经常直接继承父函数参数
fun().apply(object, arguments);
call和apply都会立刻执行,只是改变了fun()里面的this
bind不会立刻执行,bind会返回一个指定上下文的函数
var fun1 = fun().bind(object, p1, p2); //参数传递跟call一样
bind最适合作为回调函数使用,尤其是setTimeout
func(function(){}.bind(this));
我们知道,setTimeout的回调函数上下文会被置为window(use strict下是null),在setTimeout中没办法使用原有实例,bind就可以了
setTimeout(function(){}.bind(this), 1000);
JS-使用canvas绘制动画
HTML5中提供了transform transition等动画方式,已经能够满足绝大部分动画需求。
但在移动端,使用Transform等还是会出现不流畅的情况,比如背景上一个无限循环的动画,不管是使用setInterval 还是捕捉每次的AnimationEnd来实现,都会有一定的问题,因为我们设定的延时还是动画时间都不能得到保证,并且会影响页面性能。
优化是无尽的,所以学习使用Canvas
使用Canvas能做什么?
1.知道/控制每帧的绘制
2.预加载img来绘制
3.canvas保证了性能
如何使用Canvas?
http://www.w3school.com.cn/html5/html_5_canvas.asp
W3C等有canvas的简单介绍,使用Canvas的基本步骤就是
1 2 |
var c=document.getElementById("myCanvas"); var cxt=c.getContext("2d"); |
拿到canvas标签的dom,调用dom的getContext接口拿到Canvas类,就可以使用canvas的各种接口了
Canvas接口手册:http://www.w3school.com.cn/tags/html_ref_canvas.asp
canvas简单使用
1.绘制矩形
1 2 |
cxt.fillStyle="#FF0000"; cxt.fillRect(0,0,150,75); |
2.绘制线
1 2 3 4 |
cxt.moveTo(10,10); cxt.lineTo(150,50); cxt.lineTo(10,50); cxt.stroke(); |
3.绘制圆形
1 2 3 4 5 |
cxt.fillStyle="#FF0000"; cxt.beginPath(); cxt.arc(70,18,15,0,Math.PI*2,true); cxt.closePath(); cxt.fill(); |
4.绘制渐变
1 2 3 4 5 |
var grd=cxt.createLinearGradient(0,0,175,50); grd.addColorStop(0,"#FF0000"); grd.addColorStop(1,"#00FF00"); cxt.fillStyle=grd; cxt.fillRect(0,0,175,50); |
5.绘制图
1 2 3 |
var img=new Image() img.src="flower.png" cxt.drawImage(img,0,0); |
这些绘制组合使用基本上可以满足我们的一般绘制需求。
绘制动画基本流程
But,如果要绘制动画,还需要配合另一个神接口,
1 |
requestAnimationFrame |
requestAnimationFrame的用法请自行google。大概原理就是,requestAnimationFrame需要传入一个函数,浏览器每绘制一帧都会通过requestAnimationFrame来调用这个函数。通常,我们把这个函数命名为step,在step中,放入我们的draw函数(这里与Android的draw流程很类似,不过Android更方便些)。
draw与requestAnimationFrame绑定
1 2 3 4 5 6 7 8 |
this.show = function() { var step = function() { this.draw(); this.animationId = requestAnimationFrame(step.bind(this)); }; this.animationId = requestAnimationFrame(step.bind(this)); this.element.style.visibility = "visible"; }; |
解绑(这里把绑定与show/hide放到了一起)
1 2 3 4 |
this.hide = function() { cancelAnimationFrame(this.animationId); this.element && (this.element.style.visibility = "hidden"); }; |
draw函数
1 2 3 4 5 6 |
this.draw = function() { this.flash++; this.context.clearRect(0, 0, this.element.width, this.element.height); this.rect0.update(); this.rect0.draw(this.context); }; |
draw函数中我们把绘制分为两步,一步是update(和Android类比就是在这里做mesure,确定View中各个元素的位置),第二步是绘制。
子View中实现各自的update和draw
需要注意的是,Canvas的使用宽高默认为300 150,我们设定的宽高只会对Canvas进行缩放。
update-动画曲线
使用css动画时,可以方便的给一个动画曲线,比如easeinout等,使用canvas绘制就需要我们不断的update绘制范围。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 |
this.update = function() { if (!this.isAnimating) { return; } this.t += 0.05; switch (this.direction) { case "right": this.x = easeInOutQuint(this.t) * 70; break; case "down": this.y = easeInOutQuint(this.t) * 70; break; case "left": this.x = (1 - easeInOutQuint(this.t)) * 70; break; case "up": this.y = (1 - easeInOutQuint(this.t)) * 70; break; } if (this.t >= 1) { this.nextDirection(); this.t = 0; } }; |
在update里面,我们完成让一个矩形以指定动画曲线在四个方向转圈的位移。
缓动函数就负责返回位移的值
下面的easeInOutQuint按照步进返回值
1 2 3 |
var easeInOutQuint = function (t) { return t < 0.5 ? 16 * t * t * t * t * t : 1 + 16 * --t * t * t * t * t; }; |
更高明的做法,比如Jquery中,以时间为参数
1 2 3 4 5 6 7 8 9 10 11 |
function easeOutBounce(progress, currentTime, begin, change, duration) { if ((currentTime/=duration) < (1/2.75)) { return change*(7.5625*currentTime*currentTime) + begin; } else if (currentTime < (2/2.75)) { return change*(7.5625*(currentTime-=(1.5/2.75))*currentTime + .75) + begin; } else if (currentTime < (2.5/2.75)) { return change*(7.5625*(currentTime-=(2.25/2.75))*currentTime + .9375) + begin; } else { return change*(7.5625*(currentTime-=(2.625/2.75))*currentTime + .984375) + begin; } } |
draw就比较简单了
1 2 3 4 |
this.draw = function(ctx) { ctx.fillStyle = this.color; ctx.fillRect(this.x, this.y, 70, 70); }; |
Android Studio 自动更新失败解决办法(2015-11-21,1.4.1升级1.5.0版本有效)
昨天在G+中看到Android Studio又有更新了就心血来潮想去更新体验一下,可是无论我怎么点Check Update却一直提示
1 |
Connection failed. Please check your network connection and try again |
,开始以为是由于G*W在捣乱,但是打开VPN后还是无法更新,然后开始Google了一下找到了下面的解决办法。
Mac OSX
首先打开Finder
在左边选择Application
目录,在右边找到Android Studio.app
,然后右击选择“显示包内容”如下图:
然后找到 Contents/bin/
目录下的 .vmoptions
后缀的文件
Linux
找到 bin/
目录下的 studio.vmoptions
(32位系统) 或者 studio64.vmoptions
(64位系统)文件
Windows
找到 bin/
目录下的 studio.vmoptions
(32位系统) 或者 studio64.exe.vmoptions
(64位系统)文件
接着用自己趁手的编辑器打开 idea.vmoptions
或者 studio.vmoptions/studio64.vmoptions
或者 studio.exe.vmoptions/studio64.exe.vmoptions
文件添加如下内容:
1 2 3 |
-Djava.net.preferIPv4Stack=true -Didea.updates.url=http://dl.google.com/android/studio/patches/updates.xml -Didea.patches.url=http://dl.google.com/android/studio/patches/ |
保存后,重新打开Android Studio
点击Check Update就会弹出更新信息提示了
如果仍然无效,将url里的修改http
为https
,然后重启点击Check Update试试~~~