com.android.dex.DexIndexOverflowException

现象描述


注意,本文描述的方案,仅在Android Studio 1.5,Gradle插件版本1.3.1中测试成立!

同时在工程中引入了多个第三方jar包,导致调用的方法数超过了android设定的65536个(DEX 64K problem),进而导致dex无法生成,也就无法生成APK文件。

编译时候产生如下的异常信息:

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 节中添加分包设置:

      dependencies { 
      ... 
         compile 'com.android.support:multidex:1.0.1' 
         ... 
      }
      

      2.通过在defaultConfig节中设置multiDexEnabled标签为true,开启multi-dexing支持.

      defaultConfig { 
         ... 
      multiDexEnabled true 
      ... 
      }
      

      3.如果没有创建自己的Application.class,直接在AndroidManifest.xml文件的Application声明中添加:

      android:name="android.support.multidex.MultiDexApplication"

      如果实现了自己的Application.class,则修改继承的父类为
      android.support.multidex.MultiDex.MultiDexApplication

 

  • Multidex Apps单元测试

    1.在项目的build.gradle文件的dependencies 节中添加分包设置:

    dependencies { 
    ... 
          androidTestCompile 'com.android.support:multidex-instrumentation:1.0.1'
       ... 
    }
    

    2.通过在defaultConfig节中设置multiDexEnabled标签为true,开启multi-dexing支持.

    defaultConfig { 
       ... 
    multiDexEnabled true 
    testInstrumentationRunner "com.android.test.runner.MultiDexTestRunner"
    ... 
    }
    

 


参考链接


  1. Building Apps with Over 65K Methods
  2. Which package for MultiDexTestRunner? android.support.multidex or com.android.test.runner
  3. Android学习笔记----解决“com.android.dex.DexIndexOverflowException: method ID not in [0, 0xffff]: 65536”问题

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的基本步骤就是

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.绘制矩形

cxt.fillStyle="#FF0000";
cxt.fillRect(0,0,150,75);

2.绘制线

cxt.moveTo(10,10);
cxt.lineTo(150,50);
cxt.lineTo(10,50);
cxt.stroke();

3.绘制圆形

cxt.fillStyle="#FF0000";
cxt.beginPath();
cxt.arc(70,18,15,0,Math.PI*2,true);
cxt.closePath();
cxt.fill();

4.绘制渐变

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.绘制图

var img=new Image()
img.src="flower.png"
cxt.drawImage(img,0,0);

这些绘制组合使用基本上可以满足我们的一般绘制需求。

绘制动画基本流程

But,如果要绘制动画,还需要配合另一个神接口,

requestAnimationFrame

requestAnimationFrame的用法请自行google。大概原理就是,requestAnimationFrame需要传入一个函数,浏览器每绘制一帧都会通过requestAnimationFrame来调用这个函数。通常,我们把这个函数命名为step,在step中,放入我们的draw函数(这里与Android的draw流程很类似,不过Android更方便些)。

draw与requestAnimationFrame绑定

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放到了一起)

this.hide = function() {
    cancelAnimationFrame(this.animationId);
    this.element && (this.element.style.visibility = "hidden");
};

draw函数

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绘制范围。

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按照步进返回值

var easeInOutQuint = function (t) {
    return t < 0.5 ? 16 * t * t * t * t * t : 1 + 16 * --t * t * t * t * t;
};

更高明的做法,比如Jquery中,以时间为参数

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就比较简单了

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却一直提示

Connection failed. Please check your network connection and try again

,开始以为是由于G*W在捣乱,但是打开VPN后还是无法更新,然后开始Google了一下找到了下面的解决办法。

android-studio-update-error.png

Mac OSX

首先打开Finder在左边选择Application目录,在右边找到Android Studio.app,然后右击选择“显示包内容”如下图:

android_studio_in_finder

然后找到 Contents/bin/ 目录下的 .vmoptions 后缀的文件

mac-studio-vmoptions.png

Linux

找到 bin/ 目录下的 studio.vmoptions (32位系统) 或者 studio64.vmoptions (64位系统)文件

linux-studio-vmoptions.png

Windows

找到 bin/ 目录下的 studio.vmoptions (32位系统) 或者 studio64.exe.vmoptions (64位系统)文件

windows-studio-vmoptions.png

接着用自己趁手的编辑器打开 idea.vmoptions 或者 studio.vmoptions/studio64.vmoptions 或者 studio.exe.vmoptions/studio64.exe.vmoptions 文件添加如下内容:

-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就会弹出更新信息提示了

android-studio-update-info

如果仍然无效,将url里的修改httphttps,然后重启点击Check Update试试~~~

剽窃地址 Android Studio 自动更新失败解决办法

android-ndk-r10e开启C++11,编译TEMP_FAILURE_RETRY错误

在使用select来操作socket的时候,一般都是会这么写

int err = TEMP_FAILURE_RETRY(select(socket_fd + 1, NULL, &set, NULL, const_cast<struct timeval*>(&timeout)));

其中的“TEMP_FAILURE_RETRY”宏在“unistd.h”中的定义如下:

/* Used to retry syscalls that can return EINTR. */
#define TEMP_FAILURE_RETRY(exp) ({         \
    typeof (exp) _rc;                      \
    do {                                   \
        _rc = (exp);                       \
    } while (_rc == -1 && errno == EINTR); \
    _rc; })

正常情况下,编译是没问题的。但是当在“Application.mk”中增加

APP_CPPFLAGS += -std=c++11

之后,发现编译不通过了。报告“error: 'typeof' was not declared in this scope”。

解决方法:

APP_CPPFLAGS += -std=gun++11

“c++11”和“gnu++11”的差别:

“gnu++11”增加了很多的扩展“c++11”的功能,功能更加多,具体的扩展参考Extensions to the C++ Language

NDK下GCC定义__cplusplus不正确的问题

在C++升级之后,编译会出现“C++11 error: unable to find string literal operator 'operator"”这种错误,按照链接里面操作,在“android-ndk-r10e”上面依旧出现问题。

追踪了一下,才发现,这个是GCC的一个BUG,GCC-4.7,GCC-4.8中定义的__cplusplus 竟然都是 “__cplusplus=1”,这个是明显不正确的,具体的BUG内容查看“__cplusplus defined to 1, should be 199711L”。

尽管这个BUG已经修复了,但是很明显“android-ndk-r10e”使用的GCC版本并没有合并这个补丁。

解决方案

升级GCC到4.9,在”Application.mk“中增加

NDK_TOOLCHAIN_VERSION = 4.9

OpenSCAD用户手册/第一步

目录


  1. 创建一个简单的模型
  2. 打开一个已有的示例模型
  3. 放置一个对象
  4. 改变一个对象的颜色
  5. 模型视图

1.创建一个简单的模型

对于我们的第一个模型,我们将会创建一个简单的2*3*4大小的立方体。在OpenSCAD编辑器中,输入下面的命令

cube([2,3,4]);

220px-OpenSCAD_Simple_Cuboid

编译并渲染我们的第一个模型

当焦点在OpenSCAD的编辑器上面的时候,按下F5或F6就可以编译并渲染这个立方体模型了。


2.打开一个已有的示例模型

打开OpenSCAD自带的许多例子中的一个,或者复制下面的例子代码到OpenSCAD的编辑窗口中:

difference() {
    cube(30, center=true);
    sphere(20);
}
translate([0, 0, 30]) {
    cylinder(h=40, r=10);
}

然后,按下F5预览(或者F6渲染)。Openscad_first_steps

有三种方式对预览框进行操作:

  1. 鼠标左键的拖拽来旋转视图,底部状态栏显示的rotate会随着旋转而改变。
  2. 鼠标右键(OSX使用Ctrl+鼠标左键)的拖拽会移动视图,底部状态栏显示的translate会随着拖拽而改变。
  3. 鼠标滚轮用来缩放。也可以使用Shift+鼠标右键(OSX使用Shift+Crtl+鼠标左键),底部状态栏显示的distance会随之而改变。

3.放置一个对象

我们已经学会如何创建一个简单的立方体。我们的下一个任务是学习使用位置偏移命令来放置一个立方体到一个已经存在的立方体边上。

cube([2,3,4]);
translate([3,0,0]) {
  cube([2,3,4]);
}

OpenSCAD_Positioning_an_Object

在位置偏移命令最后没有分号:

注意在位置偏移命令后面没有分号。因为位置偏移命令需要包含后面的对象,如果在小括号后面使用了分号,对于位置偏移的影响将会终止,第二个立方体将会放到第一个立方体相同的位置。


4.改变一个对象的颜色

通过指定一个RGB数字,可以改变对象的颜色。不同于传统的用0-255来表示的RGB颜色,OpenSCAD使用0.0到1.0之间的浮点数来表示。注意!颜色的改变只在预览模式下面有效(F5)。渲染模式(F6)暂时不支持设置颜色。

color([1,0,0]) cube([2,3,4]);
translate([3,0,0])
color([0,1,0]) cube([2,3,4]);
translate([6,0,0])
color([0,0,1]) cube([2,3,4]);

OpenSCAD_Changing_Color

2011.12 版本(以及后续版本)可以使用颜色名字指定颜色。颜色名字与Web colors使用相同的定义。比如:color("red") cube();

如果把整条命令当作一个语句来分析的话,color()是整个句子中描述"对象"(名词)的形容词,而cube()就是要创建的那个对象。一般句子中,形容词放在名词的前面,比如color() cube();。同理,translate()可以理解为操作对象的动词,因此排列方式应该是这样的translate() color() cube();。如下的代码来展示这种情况:

translate([6,0,0])
{
   color([0,0,1])    // notice that there is NO semicolon
   cube([2,3,4]);    // notice the semicolon is at the end of all related commands
}

5.模型视图

视图("View")菜单在OpenSCAD应用窗口顶部的菜单栏上,提供了一系列的视图选项。


预览(Preview)


当模型代码首次渲染的视图就是预览视图。选择"View->Preview"可以返回预览视图。image024

外表面(Surfaces)


选择"View->Surfaces"将会使用开源构造立体几何库(OpenCSG)利用OpenGL进行渲染。如果OpenCSG不存在,或者显卡驱动不支持OpenGL会导致渲染失败。image020

线框(Wireframe)


当处理非常复杂的3D模型的时候,设计师一般会选择"View->Wireframe"。
轮廓视图只呈现支撑框架。可参考埃菲尔铁塔。
线框是一种三维或者物理对象的视觉表现形式。使用线框模型允许一个3D模型的基本结构设计可视化。由于线框渲染相当的简单并且计算快速,因此常被用于需要高帧率渲染的场景(比如,当需要渲染复杂3D模型,或者实时模型外观渲染系统)。当需要更多的图像细节的时候,可以自动在复杂的框架渲染之后再追加表面纹理。这就允许设计师可以在不经过长时间的重新渲染的情况下,快速的预览改变或者旋转到一个其他的设计视图。线框格式也被数控机械设备良好支持,并被广泛用于程序化路径控制。线框模型常被用于计算机辅助制造(CAM)。线框是三种主要CAD视图中,最抽象,最逼真的。这种建模方法只包括直线、点和曲线的定义。image022

混合(Thrown Together)


选择"View->Thrown Together"可以把上述所有视图一起显示出来。

OpenSCAD中文手册

简介


OpenSCAD是一款用于构建三维立体模型的软件。它是一款自由软件,可用于多种操作系统,包括GNU/Linux,微软Windows和苹果OSX。

不同于其他多数用于构建三维立体模型的自由软件(比如大家熟知的Blender),OpenSCAD的主要用途并不是用于外观艺术渲染,而是更多致力于CAD方面的功能。所以如果你在寻找一款用于构建机械零件模型的应用软件,他可能正好是你想要找的,而如果你更感兴趣的是制作电脑动画或模拟生命模型软件的话,他可能不够胜任。

OpenSCAD并不是交互建模工具,这一点跟多数的CAD工具也不同。它更像是一个2D/3D编译器,读取描述对象的程序文件,从中生成出模型。这样使得设计者能够全面控制模型处理过程,能够容易的改变其中的步骤,或者通过定义配置参数来进行设计。

OpenSCAD主要有两种操作模式,预览和渲染。预览通过利用三维图形技术和计算机图形处理单元进行处理,速度相对较快,但是只能输出一个模型的近似结果,预览使用的是OpenCSG跟OpenGL。渲染生成精确的几何模型并完全棋盘化,栅格化,而不是近似模拟,因而过程较为漫长,较大的设计通常需要以分钟甚至小时记的时间,渲染使用的是CGAL几何引擎。

OpenSCAD提供了两种类型的3D建模,构造立体几何Constructive Solid Geometry(CSG)或通过二维图元生成三维空间。

AutoCAD的DXF文件作为二维轮廓数据的交换格式。除了使用二维路径建立模型,还可以直接从DXF文件读取设计参数。除了可以读取DXF文件,OpenSCAD还可以读取和创建STL和OFF文件格式的三维模型。

OpenSCAD可以在http://openscad.org/下载。

如果不想(或者不能)在电脑上面安装新的OpenSCAD软件,在浏览器支持WebGL的情况下,也可以使用OpenJSCAD(http://OpenJSCAD.org/),一个运行在Web浏览器上的OpenSCAD工具。

CGAL开源项目,目标是以C++库的形式提供方便,高效,可靠的几何运算,CGAL应用到在诸多方面有几何运算需要的地方,如:计算机图形学,科学可视化,计算机辅助设计与建模,地理信息系统,分子生物学,医学成像,机器人技术和运动规划,网格生成,数值计算方法等等。

目录


  1. 第一步
  2. OpenSCAD用户界面
  3. OpenSCAD语言
    1. 综述-初步了解-注释,数值以及数据类型,变量
    2. 基本立体模型-立方体,球体,柱体&多面体
    3. 数学运算符
    4. 数学函数
      1. 三角函数(cos sin tan acos asin atan atan2)
      2. 其他(abs ceil concat cross exp floor ln len let log lookup max min norm pow rands round sign sqrt)
    5. 字符串函数-str,chr
    6. 列表
    7. 变换-尺寸&方位.scale,resize,rotate,translate,mirror,multmatrix,offset,color,minkowsik&hull
    8. 条件and迭代-for,if&assign
    9. CSG建模-基本模型的组合.union,difference,intersection&render
    10. 修饰字符-辅助调试,% # !*
    11. 模型-编写自定义基本模型与变换
    12. 用户自定义功能
    13. 包含声明
    14. 其他语言特性-特殊的'$'变量,echo,render,surface,search,version()&version_num()
  4. 使用二维子系统
  5. STL导入与导出
  6. 带注释的项目示例
  7. 在OpenSCAD上使用外部编辑器
  8. 在命令行环境下使用OpenSCAD
  9. 使用源文件编译OpenSCAD
  10. 常见问题

openSCAD中文教程

解决Ubuntu和Windows双系统时间差异8小时的方法

Windows/Ubuntu双系统用户会发现在Ubuntu里面的时间正常的情况下Windows的系统时间被改到8小时前。

原来Linux操作系统是以CMOS时间做为格林威治标准时间,再根据系统设置的时区来确定目前系统时间。但是Windows会直接修改CMOS时间。而中国的时区是+8区,所以才会造成时间被调整了-8个小时。

所以您可以让Windows去使用时区或者让Ubuntu使用本地时间。

修改Windows使用时区的方法是在注册表:

HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\TimeZoneInformation\

下面增加一个名为RealTimeIsUniversalREG_DWORD键,并赋值为1

对于Ubuntu 16.04以下版本, 使用本地时间的方法是:

$ sudo gedit /etc/default/rcS

把里面的 UTC=yes 改为 UTC=no

对于`Ubuntu 16.04`以及之后的版本(如:`Ubuntu 18.04`),使用如下命令:

$ sudo timedatectl set-local-rtc 1

参考链接


解决ubuntu和windows双系统时间差异8小时的方法