kongkong's Blog

No Silver Bullet --- Computer Language is just a tool.

使用cocoapods 总结

| Comments

  1. 使用 pod install 速度非常慢
    原因:CocoaPods在执行pod install 和 pod update时候,会默认更新一次podspec索引。使用--no-repo-update参数可以禁止索引更新。
    解决办法:pod install --no-repo-update

  2. Podfile.lock会锁定当前各依赖库的版本,之后如果多次执行pod install 不会更改版本,要pod update才会改Podfile.lock了。这样多人协作的时候,可以防止第三方库升级时造成大家各自的第三方库版本不一致。

  3. 将gem 软件源切换到淘宝的源,加快gem下载速度,使用gem sources --remove https://rubygems.org/,提示"source https://rubygems.org/ not present in cache",
    解决办法:直接 vi ~/.gemrc

  4. gem更新软件版本,直接使用gem install 重新安装

  5. gem安装东西没反应,使用--verbose显示debug信息

  6. libPods.a找不到,应该打开pod产生的那个.xcworkspace工程文件

参考文档:唐巧的blog
cocoapods使用

iOS中的Initialize 和 load方法

| Comments

总结:

  • Objective-C 提供两种方法to automatically run class-setup code, 两者都在Main方法未调用前被执行,+load方法需要显式地实现才会被调用,不会从父类继承。+initialize如果子类不实现也会从父类继承,所以会出现重复执行的情况。所以,you should always write your +initialize method to look like this:
     + (void)initialize
    {
        if(self == [WhateverClass class])
        {
            ...perform initialization...
        }
    }
    
  • +initialize方法更适合做setup tasks, 因为it runs lazily(指的是会从父类直接继承并执行) and in a nice environment.

注:下面的内容转自stackOverFlow iOS中的Initialize 和 load方法

The load message

The runtime sends the load message to each class object, very soon after the class object is loaded in the process's address space. For classes that are part of the program's executable file, the runtime sends the load message very early in the process's lifetime. For classes that are in a shared (dynamically-loaded) library, the runtime sends the load message just after the shared library is loaded into the process's address space.

Furthermore, the runtime only sends load to a class object if that class object itself implements the load method. Example:

@interface Superclass : NSObject
@end

@interface Subclass : Superclass
@end

@implementation Superclass

+ (void)load {
    NSLog(@"in Superclass load");
}

@end

@implementation Subclass

// ... load not implemented in this class

@end

The runtime sends the load message to the Superclass class object. It does not send the load message to the Subclass class object, even though Subclass inherits the method from Superclass.

The runtime sends the load message to a class object after it has sent the load message to all of the class's superclass objects (if those superclass objects implement load) and all of the class objects in shared libraries you link to. But you don't know which other classes in your own executable have received load yet.

Every class that your process loads into its address space will receive a load message, if it implements the load method, regardless of whether your process makes any other use of the class.

You can see how the runtime looks up the load method as a special case in the class_getLoadMethod of objc-runtime-new.mm, and calls it directly from callclass_loads in objc-loadmethod.mm.

The runtime also runs the load method of every category it loads, even if several categories on the same class implement load. This is unusual. Normally, if two categories define the same method on the same class, one of the methods will “win” and be used, and the other method will never be called.

The initialize Method

The runtime sends the initialize method to a class object just before sending the first message (other than load or initialize) to the class object or any instances of the class. This message is sent using the normal mechanism, so if your class doesn't implement initialize, but inherits from a class that does, then your class will use its superclass's initialize. The runtime will send the initialize to all of a class's superclasses first (if the superclasses haven't already been sent initialize).

Example:

@interface Superclass : NSObject
@end

@interface Subclass : Superclass
@end

@implementation Superclass

+ (void)initialize {
    NSLog(@"in Superclass initialize; self = %@", self);
}

@end

@implementation Subclass

// ... initialize not implemented in this class

@end

int main(int argc, char *argv[]) {
    @autoreleasepool {
        Subclass *object = [[Subclass alloc] init];
    }
    return 0;
}

This program prints two lines of output:

2012-11-10 16:18:38.984 testApp[7498:c07] in Superclass initialize; self = Superclass
2012-11-10 16:18:38.987 testApp[7498:c07] in Superclass initialize; self = Subclass

Since the system sends the initialize method lazily, a class won't receive the message unless your program actually sends messages to the class (or a subclass, or instances of the class or subclasses). And by the time you receive initialize, every class in your process should have already received load (if appropriate).

The canonical way to implement initialize is this:

@implementation Someclass

+ (void)initialize {
    if (self == [Someclass class]) {
        // do whatever
    }
}

The point of this pattern is to avoid Someclass re-initializing itself when it has a subclass that doesn't implement initialize.

The runtime sends the initialize message in the class_initialize function in objc-initialize.mm. You can see that it uses objcmsgSend to send it, which is the normal message-sending function.

Further reading

Check out Mike Ash's Friday Q&A on this topic.

Android 在应用层调用系统权限的接口

| Comments

在Android的应用层,一般是没法调用如关机,修改系统时间的接口,为了实现在APP中调用系统接口,可以通过将项目作为一个模块,放到Android系统源码中进行编译。

步骤如下:

  1. 在应用程序的AndroidManifest.xml中的manifest节点中加入"android:sharedUserId="android.uid.system"这个属性。
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
  ……
android:sharedUserId="android.uid.system" >  <!--添加该属性-->
    
<uses-permission android:name="android.permission.SHUTDOWN"/> <!--添加该权限-->
……
</manifest>
  1. 编译apk

(1)将应用程序的src文件、res文件和AndroidManifest.xml文件拷贝到Android系统源码package/apps目录下

(2)编写一个Android.mk文件(最简单的方法就是拷贝其他模块中的Android.mk文件),修改Android.mk文件,加入LOCAL_CERTIFICATE := platform这一行

Android.mk:

LOCAL_PATH:= $(call my-dir)
include $(CLEAR_VARS)

LOCAL_MODULE_TAGS := optional

LOCAL_SRC_FILES := $(call all-java-files-under, src)

LOCAL_PACKAGE_NAME := 你的项目名
LOCAL_CERTIFICATE := platform    #添加这一句

include $(BUILD_PACKAGE) 

(3)mm 编译,生成apk

遇到的问题:

  • 提示"needed by system/platform",从package/apps的其他app中copy出来Android.mk中的LOCAL_CERTIFICATE := platform 写入到Android.mk中,重新编译即可。

  • 由于太乱了,我重新编译了整个android source,但是又提示“check api”的问题,解决办法:分别使用
    make userdataimage生成data.img;
    make systemimage生成system.img和recovery.img;
    make bootimage生成boot.img 。
    这样生成了所有需要的东西而且不会像使用make那样总是提示烦人的api error。

  • mm生成的apk应该在out/target/product/sabresd_6dq/data/app/中才是正确的,在out/target/product/common是不正确的. 注意在运行mm之前,要source build/envsetup.sh 和lunch sabresd_6dq-eng

  • 编写的app在编译时候总提示:text localizated 本地化的问题,可以在Android.mk中加入

    LOCAL_MODULE_TAGS := tests   #omit the localization check 
    

总结:其实就是把应用程序当作系统应用进行编译~~这样之后就会有系统权限了。

终于成功编译freescale android

| Comments

这两周一直在编译android,期间遇到很多问题。所以只有来个彻底的重新洗牌。这个方法果然奏效,快刀斩乱麻:)

下载Andorid Source Code

为了节约时间,使用Local Mirror,以后可以直接从local mirror下载源代码,参考Android website

  • 首先下载mirror到本地。
$ mkdir  -p  ~/aosp/mirror
$ cd  ~/aosp/mirror
$ repo init -u https://android.googlesource.com/mirror/manifest -b android-4.2.2_r1  --mirror
$ repo sync
  • 从本地mirror下载source code
$ mkdir -p ~/myandroid
$ cd ~/myandroid
$ repo init -u ~/aosp/mirror/platform/manifest.git -b android-4.2.2_r1
$ repo sync
  • 最后如果要更新本地的源代码,需要先将本地镜像与远程服务端进行sync,然后本地source code与本地镜像进行sync(因为本地source code 在进行repo init -u选择的url是本地的mirror路径,所以需要先更新本地mirror与远程服务端同步,然后本地源代码与本地镜像同步)。

    $ cd  ~/aosp/mirror
    $ repo sync
    $ cd ~/myandroid
    $ repo sync
    

    编译过程出现的几个问题与解决

  • Checking API: checkapi-last (unknown): error 17 ,通常是修改了google开放出来的API或者变量。解决方法:

  1. 找到错误所在的文件的所在行,对于API,在其前添加/** @hide * / ; 对于变量,在其前添加/** {@hide} * /.
  2. 使用make update-api PRODUCT-eng.(这个方法简洁)
  • frameworks/base/core/java/com/android/internal/widget/LockPatternUtils.java:1280: error 114: @deprecated tag with no explanatory comment。 解决方法:在这个java文件中去除@deprecated这一行。

  • 这次编译没有出现上次的error with -llzo2 and -luuid ,通过查看~/myandroid/external/mtd-utils/mkfs.ubifs/Android.mk,发现这个liblzo2和uuid是在/usr/lib/x86_64-linux-gnu(原文中LOCAL_LDFLAGS += -L /usr/lib/x86_64-linux-gnu)。这个路径填写正确,就不会出现64bit不兼容的问题。

最后就是漫长的编译了。

工作杂谈-freescale 方案问题和解决方法

| Comments

错误1


frameworks/base/core/java/com/android/internal/widget/LockPatternUtils.java:1280: error 114: @deprecated tag with no explanatory comment

解决方法:

在frameworks/base/core/java/com/android/internal/widget/LockPatternUtils.java文件中, remove line 1280 * @deprecated.

错误2,Android build error with -llzo2 and -luuid on 64 bits ubuntu

解决方法:
参考:https://community.freescale.com/thread/303536
I installed liblzo2-2_2.05-1_i386.deb ,liblzo2-dev_2.05-1_i386.deb and uuid-dev_2.20.1-1ubuntu3_i386.deb
install liblzo2

$ sudo mkdir /usr/lib/liblzo2_i386
$ sudo dpkg -x liblzo2-dev_2.05-1_i386.deb /usr/lib/liblzo2_i386/
$ sudo dpkg -x liblzo2-2_2.05-1_i386.deb /usr/lib/liblzo2_i386/ 
$ cd /usr/lib/
$ sudo rm liblzo2.a
$ sudo rm liblzo2.so
$ sudo rm liblzo2.so.2
$ sudo ln -s liblzo2_i386/usr/lib/liblzo2.a liblzo2.a
$ sudo ln -s liblzo2_i386/usr/lib/liblzo2.so.2.0.0 liblzo2.so
$ sudo ln -s liblzo2_i386/usr/lib/liblzo2.so.2.0.0 liblzo2.so.2

install uuid-dev

$ sudo mkdir /usr/lib/uuid-dev
$ sudo dpkg -x uuid-dev_2.20.1-1ubuntu3_i386.deb  /usr/lib/uuid-dev/
$ cd /usr/lib/
$ sudo ln -s uuid-dev/usr/lib/i386-linux-gnu/libuuid.a  libuuid.a
$ sudo ln -s uuid-dev/usr/lib/i386-linux-gnu/libuuid.so  libuuid.so 

2.I modified the external/mtd-utils/mkfs.ubifs/Android.mk.This fixed the "-llzo2 not found; uuid/uuid.h not found;".

$ vi external/mtd-utils/mkfs.ubifs/Android.mk

I added the following to external/mtd-utils/mkfs.ubifs/Android.mk.
LOCAL_LDFLAGS +=-L /usr/lib/
LOCAL_C_INCLUDES +=/usr/lib/uuid-dev/usr/include/
LOCAL_C_INCLUDES +=/usr/lib/liblzo2_i386/usr/include

FEC: Link is down 7949

网线没插好,囧。

FEC link is down 7809

参考:https://community.freescale.com/thread/306799

从SD卡启动android

  1. 先给sd卡分区,fsl-sdcard-partition.sh是freescale提供的分区脚本,需要修改这个脚本,在"function format_android" 上一行中添加:node=/dev/mmcblk0p。 $ cd ~/myandroid/ $ sudo chmod +x ./device/fsl/common/tools//fsl-sdcard-partition.sh $ sudo ./device/fsl/common/tools/fsl-sdcard-partition.sh /dev/mmcblk0
  2. 分区完成后,使用dd命令将image拷贝到sd卡中。
    Download the U-Boot image:

    # sudo dd if=u-boot.bin of=/dev/sdx bs=1K skip=1 seek=1; sync
    
    Or If you're using no padding uboot image:
    

    sudo dd if=u-boot-no-padding.bin of=/dev/sdx bs=1K seek=1; sync

    Download the boot image:
    
    # sudo dd if=boot.img of=/dev/sdx1; sync
    
    Download the android system root image:
    
    # sudo dd if=system.img of=/dev/sdx5; sync
    
    Download the android recovery image:
    
    # sudo dd if=recovery.img of=/dev/sdx2; sync
    
  3. SW6调到 1101 0110(与文档中描述的有出入,这个地方我也不明白)。设置U-Boot的env。
    U-Boot > setenv fastboot_dev [eMMC as fastboot deivce]

    U-Boot > setenv bootcmd booti mmc2         [Load the boot.img from SD card]
    
    U-Boot > setenv bootargs console=ttymxc0,115200 init=/init video=mxcfb0:dev=ldb,bpp=32
    video=mxcfb1:off video=mxcfb2:off fbmem=10M fb0base=0x27b00000 vmalloc=400M
    androidboot.console=ttymxc0 androidboot.hardware=freescale  #[Optional]
    
    U-Boot > saveenv    #[Save the environments]
    

    从local mirror 下载android aosp

    下载mirror

    mkdir  p ~/aosp/mirror
    cd ~/aosp/mirror
    repo init -u https://android.googlesource.com/mirror/manifest -b android-4.2.2_r1  --mirror
    sync
    

    注意点:由于我在生成mirror使用使用了-b android-4.2.2_r1,所以在下载mirror时候的repo init需要加上-b android-4.2.2_r1。

    mkdir myandroid
    cd myandroid
    repo init -u ~/aosp/mirror/platform/manifest.git -b android-4.2.2_r1
    repo sync
    

    编译源码时出现 Checking API: checkapi-last (unknown): error 17

    use command make update-api then command make -j4 or either use make update-api && make -j4 , and code would be compilable.