• 一个简单的 SQLite 的示例


    http://home.51.com/misoo1/diary/item/10052482.html

    数据库大家都知道,他是一组经过计算机整理后的数据,存储在一个或多个文件中,便于快速查询,分析的一种先进工具,同样,在Android中也有数据库,现有的应用有存贮联系人,MP3歌曲,将来还可作为如:网络服务器数据库,日志记录数据库,多媒体信息收集数据库,地图信息数据库等等,为此则编写一个应用 SQLite 数据库的简单示例。

    一、在 ndk 上 sqlite 的示例:
        在 android 中 已有 SQLite 库,使用方法与官方网站上的接口一致。如下则是一个使用SQLite接口写的C++示例代码:

    1.建立gmain_mysqlite.cpp
    /* -- START -- */
    #include <sqlite3.h>
    #include <stdio.h>

    static int _sql_callback(void * notused, int argc, char ** argv, char ** szColName)
    {
    int i;
    for ( i=0; i < argc; i++ )
    {
    printf( "%s = %s\n", szColName, argv == 0 ? "NUL" : argv );
    }
    return 0;
    }


    int main()
    {
        const char * sSQL1 = "create table users(userid varchar(20) PRIMARY KEY,age int,regtime datetime);";
        const char * sSQL2 = "insert into users values('guilh',29,'2009-7-16');";
        const char * sSQL3 = "select * from users;";

    sqlite3 * db = 0;
    char * pErrMsg = 0;

    int ret = 0;
    const char* const dbname = "gtest.db";
        
    //打开数据库,如果数据库不存在,会建立一个数据库
        ret = sqlite3_open(dbname, &db);

        if ( ret != SQLITE_OK )
        {
            printf("open error! : %s", sqlite3_errmsg(db));
            return(1);
        }

        printf("open db OK!\n");

        // 执行建表SQL
        sqlite3_exec( db, sSQL1, 0, 0, &pErrMsg );
        if ( ret != SQLITE_OK )
        {
            //fprintf(stderr, "SQL error: %s\n", pErrMsg);
            printf("SQL error: %s\n", pErrMsg);
            sqlite3_free(pErrMsg);
        }

        // 执行插入记录SQL
        sqlite3_exec( db, sSQL2, 0, 0, &pErrMsg);

        // 查询数据表
        sqlite3_exec( db, sSQL3, _sql_callback, 0, &pErrMsg);

        // 关闭数据库
        sqlite3_close(db);
        db = 0;

        return 0;
    }

    /* -- END -- */ 
    操作有五步:打开/创建数据库,创建数据表,插入记录,查询数据表并显示,关闭数据库。
    这里 _sql_callback 函数是个回调函数 可以从中取得查询内容。



    2.建立 gmain_mysqlite.cpp 的 Android.mk 
    (此文件存于 sources/mysqlite/testmysqlite/Android.mk)

    #### START ####
    LOCAL_PATH:= $(call my-dir)

    include $(CLEAR_VARS)
    include $(LOCAL_PATH)/../config.mk

    LOCAL_SRC_FILES:= \
    gmain_mysqlite.cpp

    LOCAL_CFLAGS := \
    -I$(ANDROID_FRAMEWORKS_BASE_INCLUDE) \
    -I$(ANDROID_SYSTEM_CORE_INCLUDE) \
    -I$(ANDROID_EXTERNAL_SQLITE_INCLUDE) \
    -I$(LOCAL_PROJECT_PATH)

    LOCAL_LDLIBS := \
    -L$(ANDROID_LIB) \
    -llog \
    -lsqlite \
    -licuuc \
    -licui18n \
    -licudata \
    -licuuc

    #$(info LOCAL_CFLAGS=$(LOCAL_CFLAGS))

    LOCAL_PRELINK_MODULE := false

    LOCAL_MODULE :=  testmysqlite.bin

    include $(BUILD_EXECUTABLE)

    ### END ###

    说明:
    这些使用到Android 下的 SQLite库,需要指定些环境变量。
    以上的各变量说明可参阅: 在NDK上建立第一个自己的项目 在此不在做说明。
    其中,include $(LOCAL_PATH)/../config.mk # 这里的 config 使用的是 sources/mysqlite/config.mk 此文件存有项目环境变量。来看一下这两个config.mk的变量设定。

    sources/mysqlite/config.mk
    #### START ####
    include usr/config/config.mk
    LOCAL_PROJECT_PATH := $(ROOT_SRC)/mysqlite
    ### END ###

    usr/config/config.mk
    ### START ###
    ROOT_PATH := $(PWD)
    ROOT_SRC := $(ROOT_PATH)/sources
    #此变量根据不同环境配置
    HOME_PATH := 

    ANDROID_SRC := $(HOME_PATH)/android
    ANDROID_FRAMEWORKS_BASE_INCLUDE := $(ANDROID_SRC)/frameworks/base/include
    ANDROID_SYSTEM_CORE_INCLUDE := $(ANDROID_SRC)/system/core/include
    ANDROID_DALVIK_INCLUDE := $(ANDROID_SRC)/dalvik/libnativehelper/include
    ANDROID_EXTERNAL := $(ANDROID_SRC)/external
    ANDROID_EXTERNAL_SQLITE_INCLUDE := $(ANDROID_EXTERNAL)/sqlite/dist

    ANDROID_LIB := $(ANDROID_SRC)/out/target/product/generic/system/lib

    ### END ###
    详细说明可参阅 借用 android 源码中的 logcat。
    至此重要部份就已完成,如果需要编译尝试,还需要增加相关项目目录及配置。

    二、 项目配置及目录结构:
    需要建立三个文件:default.propertie、Application.mk、sources/mysqlite/Android.mk
    apps/mysqlite/default.propertie
    #### START ####
    target=android-3
    ### END ###

    apps/mysqlite/Application.mk
    #### START ####
    APP_PROJECT_PATH := $(call my-dir)
    APP_MODULES := testmysqlite.bin
    ### END ###


    sources/mysqlite/Android.mk
    #### START ####
    #可寻找到当前目录下的所有子目录中的Android.mk
    include $(call all-subdir-makefiles)
    ### END ###



    至此可以看到整体结构如下:
    # java项目目录、编译启动文件存放位置、
    # 最终编译结果将从out目录中拷贝一份到apps目录下的 libs 目录中
    apps

    # C++项目目录
    sources

    # 用户自定义全局目录,如 config、include、lib等
    usr

    # 用户自定义全局配置makefile文件。
    usr/config/config.mk

    # mysqlite 项目下总makefile 和一个配置文件
    apps/mysqlite/default.propertie
    apps/mysqlite/Application.mk

    # mysqlite 项目下的文件
    sources/mysqlite/Android.mk
    sources/mysqlite/config.mk
    sources/mysqlite/testmysqlite/Android.mk
    sources/mysqlite/testmysqlite/gmain_mysqlite.cpp

    接下来在~/android-ndk-1.5_r1下进行编译并安装到sdk中测试,此时会遇到一个问题。
    因为 在SQLite打开/创建数据库操作时,需要 android 系统有可读写文件权限。
    如果没有设置权限,运行后会提示错误为 : unable to open database file 
    解决办法可用如下命令
    ~/android-sdk-linux_x86-1.5_r2/tools $adb shell
    # mount -o remount rw /

    然后在运行
    # /system/bin/testmysqlite.bin


    ======================================================

    一个简单的 Socket 的示例


    在Android 中会运用到各种对外传输,网络传输方式是其中之一,在未来的开发中可能会应用于网络传输,比如做为服务器使用,或是终端媒体设备等等,如下则是使用NDK编译运行于Android 中的一个简单的网络C/S程序示例。

    一、在 ndk 上 socket 的示例:
        从 android 的架构中可以得知,android是基于Linux 内核的一个操作系统,所以在Linux上的很多系统接口与在android上的系统接口基本是一致。则可用系统接口操作socket来完成 client /server 的网络通讯功能。

    1.建立服务端
    其操作过程:创建本地socket,绑定监听本地socket,然后进入循环,并挂起一直等待客户端的请求,当有请求来时,通过判断获得客户端 socket,然后建立子进程,在子进程里向客户端发送消息。

    服务端的代码如下: gmain_mynetserver.cpp
    /* -- START -- */
    #include <stdio.h>
    #include <stdlib.h>
    #include <errno.h>
    #include <string.h>
    #include <unistd.h>
    #include <netdb.h>
    #include <sys/types.h>
    #include <sys/socket.h>
    #include <sys/wait.h>
    #include <netinet/in.h>
    #include <arpa/inet.h>

    #define SERVPORT 3333 // 服务器监听端口号
    #define BACKLOG 10 //最大同时连接请求数

    int main()
    {
    int sockfd,client_fd;  // sockfd:监听socket;client_fd:数据传输socket
    struct sockaddr_in my_addr; // 本机地址信息
    struct sockaddr_in remote_addr; // 客户端地址信息

    // 创建监听 socket
    if ((sockfd = socket(AF_INET, SOCK_STREAM, 0)) == -1)
    {
    printf("socket create error!\n"); 
    return 1;
    }

    my_addr.sin_family=AF_INET;
    my_addr.sin_port=htons(SERVPORT);
    my_addr.sin_addr.s_addr = INADDR_ANY;
    bzero(&(my_addr.sin_zero),8);

    //绑定 socket
    if (bind(sockfd, (struct sockaddr *)&my_addr, sizeof(struct sockaddr)) == -1)
    {
    printf("bind error!\n");
    close(sockfd);
    return 1;
    }

    // 监听 socket
    if (listen(sockfd, BACKLOG) == -1) 
    {
    printf("listen error!\n");
    close(sockfd);
    return 1;
    }

    while ( true )
    {
    int sin_size = sizeof(struct sockaddr_in);
    // 获得客户端请求 socket
    if ((client_fd = accept(sockfd, (struct sockaddr *)&remote_addr, &sin_size)) == -1)
    {
    printf("accept error!\n");
    continue;
    }
    printf("received a connection from %s\n", inet_ntoa(remote_addr.sin_addr));

    if (!fork())  // 子进程代码段
    {
    // 向客户端发送消息
    if ( send(client_fd, "Hello, you are connected!\n", 26, 0) == -1)
    {
    printf("send error!");
    close(client_fd);
    close(sockfd);
    return 1;
    }
    // 关闭客户端socket
    close(client_fd);
    }
    }
    // 本地socket
    close(sockfd);
    return 1;
    }
    /* -- END -- */ 

    2.建立客户端
    其操作过程:创建本地socket,与服务端建立链接,然后接收服务端发来的消息。

    客户端的代码如下: gmain_mynetclient.cpp 
    /* -- START -- */
    #include <stdio.h>
    #include <stdlib.h>
    #include <errno.h>
    #include <string.h>
    #include <netdb.h>
    #include <unistd.h>
    #include <assert.h>
    #include <sys/types.h>
    #include <sys/socket.h>
    #include <netinet/in.h>

    #define SERVPORT 3333 // 服务端端口
    #define MAXDATASIZE 100 // 每次最大数据传输量

    int main(int argc, char *argv[])
    {
    int sockfd, recvbytes;
    char buf;
    struct hostent *host;
    struct sockaddr_in serv_addr;

    if (argc < 2)
    {
    fprintf(stderr,"Please enter the server's hostname!\n");
    return 1;
    }

    //获得输入的服务端IP地址
    if(( host = gethostbyname(argv[1])) == NULL)
    {
    herror("gethostbyname error!");
    return 1;
    }

    //创建本地socket 
    if ((sockfd = socket(AF_INET, SOCK_STREAM, 0)) == -1)
    {
    perror("socket create error!");
    return 1;
    }

    serv_addr.sin_family=AF_INET;
    serv_addr.sin_port=htons(SERVPORT);
    serv_addr.sin_addr = *((struct in_addr *)host->h_addr);
    bzero(&(serv_addr.sin_zero),8);
    //与服务端建立链接
    if (connect(sockfd, (struct sockaddr *)&serv_addr, sizeof(struct sockaddr)) == -1)
    {
    perror("connect error!");
    return 1;
    }

    // 接收数据
    if ((recvbytes=recv(sockfd, buf, MAXDATASIZE, 0)) ==-1)
    {
    perror("recv error !");
    return 1;
    }

    buf = '\0';
    printf("Received: %s",buf);

    // 关闭本地socket
    close(sockfd);
    return 0;
    }

    二、运行输出:
    先执行服务端执行程序 service.bin ,服务端会等待客户端连接
    然后在执行客户端执行程序 client.bin ,输入 client.bin <server IP>

    服务端接收到客户端请求后会显示"received a connection from <client IP>"
    此时服务端会向客户端发送消息。
    客户端则会显示服务端发来的消息 "Hello, you are connected!"

  • 相关阅读:
    网页打开qq
    正则表达式
    微信小程序 如何使用globalData
    微信小程序中常见的typeof cb == “function” && cb(that.globalData.userInfo)
    MongoDB
    Elasticsearch学习
    Kafka学习之路 (一)Kafka的简介
    mybatis sql语句中转义字符
    定时任务
    mybatis insert into 返回id,useGeneratedKeys,keyColumn,keyProperty,parameterType
  • 原文地址:https://www.cnblogs.com/sardine/p/2121853.html
Copyright © 2020-2023  润新知