8/26/2011 10:19:38 PM

 

8/26/2011 10:19:38 PM

 

google API

 

前两天配置好了Android开发环境,并且写了Hello World,但是对Android开发还是一知半解,就像尝试一下地图的开发,因为我后面要做的工作是与地图息息相关的。

我在安装Android SDK Platform的时候顺便安装了开发示例。在Google API平台下有一个示例叫做MapsDemo,我本以为运行它就可以直接显示地图了,

结果到模拟器上面执行,只显示网格,没有半点地图的迹象。

上网搜索了一下,发现Android上面的Google Map也需要API Key。它根据应用程序的keystore的MD5签名来生成API key,

使用keytool工具可以获得keystore的获得MD5签名。Android SDK默认生成一个debug.keystore文件,放在用户主目录下的.android文件夹中,

运行keytool工具(JDK中bin目录下有 keytool工具)命令如下:

C:\Program Files\Java\jdk1.6.0_18\bin>keytool.exe -list -alias androiddebugkey -keystore C:\Users\westyi\.android\debug.keystore -storepass android -keypass android
 
即可得到debug.keystore的MD5签名值,然后到http://code.google.com/android/add-ons/google-apis/maps-api-signup.html 页面提交上面得到的MD5签名即可获得地图API key。

得到自己的API key之后,就要对MapsDemo进行修改,将其中需要的Map key修改为自己获得的Key。主要修改两个地方:

res/layout/mapview.xml中第30行
android:apikey="sample_api_key"
以及MapViewCompassDemo.java文件中第143行
mMapView = new MapView(this, "sample_api_key");
将sample_api_key改为自己获得的api key即可。
   
至此,我以为大功告成了,因为网上多数地图方面的问题都是关于API Key的,我想这个Demo也应该就是这方面的问题吧。但事实确并非如此,运行后确实不再是网格了,这次是全白的!很诡异~~~

我百思不得其解,然后就在网上拼命找与Android地图开发相关的文章,发现多数的文章中都没有理会google这个示例,而是自己动手写 Activity。

经过我对MapsDemo的代码分析,我发现代码中只是使用了MapView,而并未设置地图的缩放级别和地图中心。这可能就是显示全白界面的原因!需要对MapViewDemo.java文件进行修改,

在onCreate方法最后添加代码:

Java代码 
1.MapView map = (MapView)findViewById(R.id.map);//获得MapView对象  
2.map.getController().setCenter(new GeoPoint(39971036,116314659));//设置地图中心  
3.map.getController().setZoom(10);//设置缩放级别 
MapView map = (MapView)findViewById(R.id.map);//获得MapView对象
map.getController().setCenter(new GeoPoint(39971036,116314659));//设置地图中心
map.getController().setZoom(10);//设置缩放级别

其中R.id.map是Android SDK自动生成的,需要在res/layout/mapview.xml文件第25行加上android:id="@+id/map",为MapView 添加一个id编号,才能在代码中用findViewById获得MapView对象。

再次在模拟器中运行,亲爱的北京地图终于显示在了Android模拟器上面!


需要提交字节的API key

屏幕的分辨率


QVGA/WQVGA/HVGA/VGA/WVGA说的是手机屏幕不同的分辨率,他们之间的区别就是分辨率水平,表现出来的图像细腻度也不相同。
  其中QVGA的全称是Quarter VGA,分辨率为240*320像素,一般比较老和新款低端的Windows Mobile机型采用这一分辨率;
  WQVGA是QVGA的加强升级版Wide Quarter
VGA,可以看做是QVGA分辨率的加宽版本,分辨率达到了240*400像素,一般也是用在低端手机中;
  HVGA的全称是Half VGA,分辨率为320*480像素,一般的中端Windows Mobile机型和较老的高端WM机型都采用这一分辨率。
  VGA是最为标准的分辨率,这点从前面的介绍中就能够了解到,因为他们都是在VGA之前加了一个字母将改分辨率进行缩减。
VGA分辨率为480*640像素,一般用在中端机型和较老的高端手机中;

 

  最后的WVGA分辨率全称是Wide VGA,分辨率达到了480*800像素或者480*854(宽屏)像素,是目前最高端的Windows
Mobile手机使用的分辨率。众所周知目前HTC HD2是当之无愧的机皇,这款手机的分辨率就达到了WVGA级别。
一般手机液晶屏幕都是TFT材质,VGA WVGA QVGA HVGE XGA只是表示屏幕分辨率只,是个代号和材质没关系。
分辨率对照表:
代号 分辨率 代号 分辨率
QVGA 320*240像素 WQVGA 400*240像素
HVGA 320*480像素 VGA 640*480像素
WVGA 800*480像素 XGA 1024*480像素
QVGA 即Quarter VGA。顾名思义即VGA的四分之一尺寸
HVGA (Half-size VGA),即VGA(640*480)的一半
WVGA 即Wide VGA

 


sqlite3

插入表和查询表
sqlite3 /data/data/com.android.providers.settings/databases/settings.db "INSERT INTO system VALUES(99,'http_proxy','10.10.26.252:1080')"

sqlite3 /data/data/com.android.providers.settings/databases/settings.db "SELECT * FROM system"

删除表
sqlite3 /data/data/com.android.providers.settings/databases/settings.db "DELETE FROM system WHERE _id=99"

模拟器的启动过程

在模拟器中安装APK包

adb install

读取系统属性的值qemu-props

int  main(void)
{
    int  qemud_fd, count = 0;

    /* try to connect to the qemud service */
    {
        int  tries = MAX_TRIES;

        while (1) {
            qemud_fd = qemud_channel_open( "boot-properties" );
            if (qemud_fd >= 0)
                break;

            if (--tries <= 0) {
                DD("Could not connect after too many tries. Aborting");
                return 1;
            }

            DD("waiting 1s to wait for qemud.");
            sleep(1);
        }
    }
   
    打开一个通道
   
    DD("connected to '%s' qemud service.", QEMUD_SERVICE);

    /* send the 'list' command to the service */
    if (qemud_channel_send(qemud_fd, "list", -1) < 0) {
        DD("could not send command to '%s' service", QEMUD_SERVICE);
        return 1;
    }

    /* read each system property as a single line from the service,
     * until exhaustion.
     */
    for (;;)
    {
#define  BUFF_SIZE   (PROPERTY_KEY_MAX + PROPERTY_VALUE_MAX + 2)
        DD("receiving..");
        char* q;
        char  temp[BUFF_SIZE];
        int   len = qemud_channel_recv(qemud_fd, temp, sizeof temp - 1);

        /* lone NUL-byte signals end of properties */
        if (len < 0 || len > BUFF_SIZE-1 || temp[0] == '\0')
            break;

        temp[len] = '\0';  /* zero-terminate string */

        DD("received: %.*s", len, temp);

        /* separate propery name from value */
        q = strchr(temp, '=');
        if (q == NULL) {
            DD("invalid format, ignored.");
            continue;
        }
        *q++ = '\0';

        if (property_set(temp, q) < 0) {
            DD("could not set property '%s' to '%s'", temp, q);
        } else {
            count += 1;
        }
    }


    /* finally, close the channel and exit */
    close(qemud_fd);
    DD("exiting (%d properties set).", count);
    return 0;
}

也就是简单的读取了qemu的引导属性

/* we connect with the emulator through the "sensors" qemud service
 */


通过这个与模拟器进行通信???

#define  SENSORS_LIST  \
    SENSOR_(ACCELERATION,"acceleration") \
    SENSOR_(MAGNETIC_FIELD,"magnetic-field") \
    SENSOR_(ORIENTATION,"orientation") \
    SENSOR_(TEMPERATURE,"temperature") \

static const struct {
    const char*  name;
    int          id; } _sensorIds[MAX_NUM_SENSORS] =
{
#define SENSOR_(x,y)  { y, ID_##x },
    SENSORS_LIST
#undef  SENSOR_
};

static const char*
_sensorIdToName( int  id )
{
    int  nn;
    for (nn = 0; nn < MAX_NUM_SENSORS; nn++)
        if (id == _sensorIds[nn].id)
            return _sensorIds[nn].name;
    return "<UNKNOWN>";
}

从Id到名字的转换

 static int
_sensorIdFromName( const char*  name )
{
    int  nn;

    if (name == NULL)
        return -1;

    for (nn = 0; nn < MAX_NUM_SENSORS; nn++)
        if (!strcmp(name, _sensorIds[nn].name))
            return _sensorIds[nn].id;

    return -1;
}


通过名字找到Id

打开sensor服务

static native_handle_t*
control__open_data_source(struct sensors_control_device_t *dev)
{
    SensorControl*  ctl = (void*)dev;
    native_handle_t* handle;

    if (ctl->fd < 0) {
        ctl->fd = qemud_channel_open(SENSORS_SERVICE_NAME);
    }
    D("%s: fd=%d", __FUNCTION__, ctl->fd);
    handle = native_handle_create(1, 0);
    handle->data[0] = dup(ctl->fd);
    return handle;
}

control__activate

通过sensor服务来激活某个sensor

control__set_delay 设置延迟

control__wake 设置唤醒

control__close 关闭

/** SENSORS DATA DEVICE
 **
 ** This one is used to read sensor data from the hardware.
 ** We implement this by simply reading the data from the
 ** emulator through the QEMUD channel.
 **/


从hardware上读取 sensor data

/** MODULE REGISTRATION SUPPORT
 **
 ** This is required so that hardware/libhardware/hardware.c
 ** will dlopen() this library appropriately.
 **/

/*
 * the following is the list of all supported sensors.
 * this table is used to build sSensorList declared below
 * according to which hardware sensors are reported as
 * available from the emulator (see get_sensors_list below)
 *
 * note: numerical values for maxRange/resolution/power were
 *       taken from the reference AK8976A implementation
 */
 

 

/*
 *  the qemud daemon program is only used within Android as a bridge
 *  between the emulator program and the emulated system. it really works as
 *  a simple stream multiplexer that works as follows:
 *
 *    - qemud is started by init following instructions in
 *      /system/etc/init.goldfish.rc (i.e. it is never started on real devices)
 
      被init 进程启动  
 *
 *    - qemud communicates with the emulator program through a single serial
 
 *      port, whose name is passed through a kernel boot parameter
 *      (e.g. android.qemud=ttyS1)
 *
 *    - qemud binds one unix local stream socket (/dev/socket/qemud, created
 *      by init through /system/etc/init.goldfish.rc).

 *
 *
 *      emulator <==serial==> qemud <---> /dev/socket/qemud <-+--> client1
 *                                                            |
 *                                                            +--> client2
 
 
    串口 本地域socket进行通信

 *
 *   - the special channel index 0 is used by the emulator and qemud only.
 *     other channel numbers correspond to clients. More specifically,
 *     connection are created like this:
 *
 *     * the client connects to /dev/socket/qemud
 *
 *     * the client sends the service name through the socket, as
 *            <service-name>
 *
 *     * qemud creates a "Client" object internally, assigns it an
 *       internal unique channel number > 0, then sends a connection
 *       initiation request to the emulator (i.e. through channel 0):
 *
 *           connect:<id>:<name>

       
 
 *
 *       where <name> is the service name, and <id> is a 2-hexchar
 *       number corresponding to the channel number.
 *
 *     * in case of success, the emulator responds through channel 0
 *       with:
 *
 *           ok:connect:<id>
 *
 *       after this, all messages between the client and the emulator
 *       are passed in pass-through mode.
 *
 *     * if the emulator refuses the service connection, it will
 *       send the following through channel 0:
 *
 *           ko:connect:<id>:reason-for-failure
 *
 *     * If the client closes the connection, qemud sends the following
 *       to the emulator:
 *
 *           disconnect:<id>
 *
 *       The same message is the opposite direction if the emulator
 *       chooses to close the connection.
 *
 *     * any command sent through channel 0 to the emulator that is
 *       not properly recognized will be answered by:
 *
 *           ko:unknown command
 *
 *
 *  Internally, the daemon maintains a "Client" object for each client
 *  connection (i.e. accepting socket connection).
 */
 


fd_setnonblock  设置非阻塞

fd_accept 监听某个地址

looper_init 创建一个epoll

looper_done 释放一个epoll

looper_find 返回指定句柄上一个hook

looper_grow 扩充2倍加4个

qemu=1 console=ttyS0 android.checkjni=1 android.qemud=ttyS1 android.ndns=1

multiplexer_init

打开串口

    /* initialize the serial reader/writer */
    recv.user  = m;
    recv.post  = (PostFunc)  multiplexer_serial_receive;
    recv.close = (CloseFunc) multiplexer_serial_close;

    serial_init( m->serial, fd, m->fdhandlers, &recv );
   
    看一下串口的读写
   
    /* a function called when an incoming packet comes from the serial port */
static void
multiplexer_serial_receive( Multiplexer*  mult, Packet*  p )
{
    Client*  client;

    T("%s: channel=%d '%.*s'", __FUNCTION__, p->channel, p->len, p->data);

    if (p->channel == CHANNEL_CONTROL) {
        multiplexer_handle_control(mult, p);
        return;
    }

    client = multiplexer_find_client(mult, p->channel);
    if (client != NULL) {
        client_send(client, p);
        return;
    }

    D("%s: discarding packet for unknown channel %d", __FUNCTION__, p->channel);
    packet_free(&p);
}

多通道
通过通道来查找Client ?
通道控制时间什么?
ok:connect:通道号
解析这个串

static Client*
multiplexer_find_client( Multiplexer*  mult, int  channel )
{
    Client* c = mult->clients;

    for ( ; c != NULL; c = c->next ) {
        if (c->channel == channel)
            return c;
    }
    return NULL;
}

通过channel 找到Client

转发的时候

/* send data to a client */
static void
client_send( Client*  c, Packet*  p )
{
    client_dump(c, p, __FUNCTION__);
    fdhandler_enqueue(c->fdhandler, p);
}

本质上也就是也就是一个中转站而已

通过文件名来查找进程Id

struct DexSymList {
    DexSymList  *next;
    DexSym      sym;
};


符号的这样一个单链表

 


// This function creates the pathname to the a specific trace file.  The
// string space is allocated in this routine and must be freed by the
// caller.
static char *CreateTracePath(const char *filename, const char *ext)
{
    char *fname;
    const char *base_start, *base_end;
    int ii, len, base_len, dir_len, path_len, qtrace_len;

    // Handle error cases
    if (filename == NULL || *filename == 0 || strcmp(filename, "/") == 0)
        return NULL;

    // Ignore a trailing slash, if any
    len = strlen(filename);
    if (filename[len - 1] == '/')
        len -= 1;

    // Find the basename.  We don't use basename(3) because there are
    // different behaviors for GNU and Posix in the case where the
    // last character is a slash.
    base_start = base_end = &filename[len];
    for (ii = 0; ii < len; ++ii) {
        base_start -= 1;
        if (*base_start == '/') {
            base_start += 1;
            break;
        }
    }
    base_len = base_end - base_start;
    dir_len = len - base_len;
    qtrace_len = strlen("/qtrace");

    // Create space for the pathname: "/dir/basename/qtrace.ext"
    // The "ext" string already contains the dot, so just add a byte
    // for the terminating zero.
    path_len = dir_len + base_len + qtrace_len + strlen(ext) + 1;
    fname = new char[path_len];
    if (dir_len > 0)
        strncpy(fname, filename, dir_len);
    fname[dir_len] = 0;
    strncat(fname, base_start, base_len);
    strcat(fname, "/qtrace");
    strcat(fname, ext);
    return fname;
}

 

在c++templates这本书里,作者是如此陈述的:

1.   类模板:该类是一个模板,他代表的是:整个类家族的参数化描述。

2.   模板类:通常被用在下面几个方面:

                    a     作为类模板的同义词
                    b     从模板产生的类
                    c     具有一个template-id名称的类

注意这个区别


具有template-id名称的类


struct TraceReaderEmptyStruct {
};

 


template <class T = TraceReaderEmptyStruct>
class TraceReader : public TraceReaderBase {
  public:

    struct region_entry;
    typedef struct symbol_entry : public T {
        typedef region_entry region_type;

        // Define flag values
        static const uint32_t kIsPlt = 0x01;
        static const uint32_t kIsVectorStart = 0x02;
        static const uint32_t kIsVectorTable = (kIsPlt | kIsVectorStart);
        static const uint32_t kIsInterpreter = 0x04;
        static const uint32_t kIsMethod = 0x08;

        uint32_t        addr;

        // This may hold the name of the interpreted method instead of
        // the name of the native function if the native function is a
        // virtual machine interpreter.
        const char      *name;

        // The symbol for the virtual machine interpreter, or NULL
        symbol_entry    *vm_sym;
        region_type     *region;
        uint32_t        flags;
    } symbol_type;


符号类型

在某个区域查找某个符号

MakePrivateCopy 本质上就是一个指针拷贝

 

        // The "regions" array below is a pointer to array of pointers to
        // regions.  The size of the pointer array is kInitialNumRegions,
        // but grows if needed.  There is a separate region for each mmap
        // call which includes shared libraries as well as .dex and .jar
        // files.  In addition, there is a region for the main executable
        // for this process, as well as a few regions for the kernel.
        //
        // If a child process is a clone of a parent process, the
        // regions array is unused.  Instead, the "addr_manager" pointer is
        // used to find the process that is the address space manager for
        // both the parent and child processes.
       
       
        //dex 文件和jar文件
       
       


template<class T>
TraceReader<T>::TraceReader()
{
    static PidEvent event_no_action;

    cached_pid_ = -1;
    cached_func_ = NULL;

    memset(&unknown_, 0, sizeof(symbol_type));
    unknown_.name = "(unknown)";
    next_pid_ = 0;

    memset(&event_no_action, 0, sizeof(PidEvent));
    event_no_action.rec_type = kPidNoAction;
    next_pid_event_ = event_no_action;
    for (int ii = 1; ii < kNumPids; ++ii)
        processes_[ii] = NULL;
    current_ = new ProcessState;
    processes_[0] = current_;
    next_method_.time = 0;
    next_method_.addr = 0;
    next_method_.flags = 0;
    function_start_time_ = 0;
    root_ = "";
    hash_ = new HashTable<region_type*>(512);
    AddPredefinedRegions(current_);
    demangle_ = true;
}

traceReader的构造函数

还是从通道跟踪

qemud_channel_open

在qume 目录下查找看看

ADB的架构分析

分为2部分

adb和一个adbd 

在服务器上的为一个adbd

整个adb分为4个部分

模拟器运行的几个关键img

 ·ramdisk.img启动系统的ramdisk镜像
·system.img初始化好的系统镜像
·userdata.img初始化好的用户数据分区镜像

10.0.2.2  访问本机服务的地址

 

注意模拟器的内核镜像位置

android-sdk-windows\android-sdk-windows\platforms\android-7\images


hw.lcd.density=160
sdcard.size=200M
skin.name=HVGA
skin.path=platforms\android-7\skins\HVGA
image.sysdir.1=platforms\android-7\images\

虚拟机的相关信息位置

应该是遍历目录下得所有文件就可以了

配置 和image路径

typedef struct {
#include "android/avd/hw-config-defs.h"
} AndroidHwConfig;


模拟器的配置初始化

 

你可能感兴趣的:(android,function,struct,api,sqlite,service)