close

 

在 Android 作業系統裡,  我們可以利用作業系統裡的FileObserver 進行 Process 之間的溝通. 

 

Check If File Exists

 

"Content.txt" 是我們 Process 之間溝通的檔案. 我們必須確認這個檔案是存在的, 然後才可以使用 FileObserver .  當 new File().isFile() 返回 TRUE 時, 表示該檔案存在; 反之; 返回 FALSE 時, 表示該檔案不存在. 

 

txtFile = new File("/mnt/asec/Content.txt");
if (!txtFile.isFile()) {
    Log.i("atgames", "file not exist");
} else {
   Log.i("atgames", "file exist");
}

 

RandomAccessFile

 

try {
    randomTxtFile = new RandomAccessFile(txtFile, "r");
} catch (FileNotFoundException e) {
    e.printStackTrace();
}

 

FileObserver

 

我們使用 new FileObserver().onEvent(int event, String path) 來處理當 "Content.txt" 檔案內容改變時的事件 (也就是 event == FileObserver.MODIFY) . 當檔案內容改變時我們要讀取檔案的內容; 需注意的是每一次 readLine() 之前都 seek(0) . 我喜歡將發生事件時的函數, 將它的開頭冠以 onXxx ; 在這裡我將它命名為 onFileObserver() ; 在這個函數裡面, 我們將處理來自於另一個 Process 改變 "Content.txt" 檔案的內容. 

 

設定 FileObserver 處理函數 onEvent() 以及 onFileObserver() 後, 我們還必須做一件事情: new FileObserver().startWatching() . startWatching() 以後作業系統才會 callBack 至 fileObserver.onEvent() . 

 

private File txtFile;
private RandomAccessFile randomTxtFile;

private void startFileObserver() {
    static int once = 0;

    txtFile = new File("/mnt/asec/Content.txt");
    if (!txtFile.isFile()) {
        Log.i("atgames", "file not exist");
        return;
    }
    if (0 == once) {
        Process process = null;
        DataOutputStream dataOutputStream = null;

        process = Runtime.getRuntime().exec("su");
        dataOutputStream = new DataOutputStream(process.getOutputStream());
        dataOutputStream.writeBytes("chmod 666 /mnt/asec/Content.txt\n");
        dataOutputStream.writeBytes("exit\n");
        dataOutputStream.flush();
        process.waitFor();
        once = 1;
    }

    try {
        randomTxtFile = new RandomAccessFile(txtFile, "r");
    } catch (FileNotFoundException e) {
        e.printStackTrace();
    }
    fileObserver = new FileObserver("/mnt/asec/Content.txt") {
        @Override
        public void onEvent(int event, String path) {
            if (event == FileObserver.MODIFY) {
                try {
                    randomTxtFile.seek(0);
                    onFileObserver(randomTxtFile.readLine());
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    };
    fileObserver.startWatching();
}
private void onFileObserver(String input){
    if(input == null)    return;
    ...
}

 

使用 "su"

 

我們使用 su 來改變檔案讀取權限, 代碼如下: 

 

Process process = null;
DataOutputStream dataOutputStream = null;

process = Runtime.getRuntime().exec("su");
dataOutputStream = new DataOutputStream(process.getOutputStream());
dataOutputStream.writeBytes("chmod 666 /mnt/asec/Content.txt\n");
dataOutputStream.writeBytes("exit\n");
dataOutputStream.flush();
process.waitFor();

 

Android 只有 root (AID_ROOT) 以及 shell (AID_SHELL) 可以使用 su 命令. 

 

http://www.netmite.com/android/mydroid/system/core/include/private/android_filesystem_config.h

 

...
static struct android_id_info android_ids[] = {
    { "root",      AID_ROOT, },
    { "system",    AID_SYSTEM, },
    { "radio",     AID_RADIO, },
    { "bluetooth", AID_BLUETOOTH, },
    { "graphics",  AID_GRAPHICS, },
    { "input",     AID_INPUT, },
    { "audio",     AID_AUDIO, },
    { "camera",    AID_CAMERA, },
    { "log",       AID_LOG, },
    { "compass",   AID_COMPASS, },
    { "mount",     AID_MOUNT, },
    { "wifi",      AID_WIFI, },
    { "dhcp",      AID_DHCP, },
    { "adb",       AID_ADB, },
    { "install",   AID_INSTALL, },
    { "media",     AID_MEDIA, },
    { "shell",     AID_SHELL, },
    { "cache",     AID_CACHE, },
    { "diag",      AID_DIAG, },
    { "net_bt_admin", AID_NET_BT_ADMIN, },
    { "net_bt",    AID_NET_BT, },
    { "inet",      AID_INET, }, 
    { "net_raw",   AID_NET_RAW, },
    { "misc",      AID_MISC, },
    { "nobody",    AID_NOBODY, },
};
...

 

為此你必須修改 su.c ; 它的代碼如下: 

 

https://android.googlesource.com/platform/system/extras/+/android-4.2.2_r1.2/su/su.c


如果你要修改 su.c , 請將 su.c 之 51,69行 mark 起來. 

 

/*
**
** Copyright 2008, The Android Open Source Project
**
** Licensed under the Apache License, Version 2.0 (the "License"); 
** you may not use this file except in compliance with the License. 
** You may obtain a copy of the License at 
**
**     http://www.apache.org/licenses/LICENSE-2.0 
**
** Unless required by applicable law or agreed to in writing, software 
** distributed under the License is distributed on an "AS IS" BASIS, 
** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 
** See the License for the specific language governing permissions and 
** limitations under the License.
*/
#define LOG_TAG "su"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <dirent.h>
#include <errno.h>
#include <unistd.h>
#include <time.h>
#include <pwd.h>
#include <private/android_filesystem_config.h>
/*
 * SU can be given a specific command to exec. UID _must_ be
 * specified for this (ie argc => 3).
 *
 * Usage:
 * su 1000
 * su 1000 ls -l
 */
int main(int argc, char **argv)
{
    struct passwd *pw;
    int uid, gid, myuid;
    /* Until we have something better, only root and the shell can use su. */
    myuid = getuid();
    if (myuid != AID_ROOT && myuid != AID_SHELL) {
        fprintf(stderr,"su: uid %d not allowed to su\n", myuid);
        //return 1;
    }
    if(argc < 2) {
        uid = gid = 0;
    } else {
        pw = getpwnam(argv[1]);
        if(pw == 0) {
            uid = gid = atoi(argv[1]);
        } else {
            uid = pw->pw_uid;
            gid = pw->pw_gid;
        }
    }
    if(setgid(gid) || setuid(uid)) {
        fprintf(stderr,"su: permission denied\n");
        //return 1;
    }
    /* User specified command for exec. */
    if (argc == 3 ) {
        if (execlp(argv[2], argv[2], NULL) < 0) {
            fprintf(stderr, "su: exec failed for %s Error:%s\n", argv[2],
                    strerror(errno));
            return -errno;
        }
    } else if (argc > 3) {
        /* Copy the rest of the args from main. */
        char *exec_args[argc - 1];
        memset(exec_args, 0, sizeof(exec_args));
        memcpy(exec_args, &argv[2], sizeof(exec_args));
        if (execvp(argv[2], exec_args) < 0) {
            fprintf(stderr, "su: exec failed for %s Error:%s\n", argv[2],
                    strerror(errno));
            return -errno;
        }
    }
    /* Default exec shell. */
    execlp("/system/bin/sh", "sh", NULL);
    fprintf(stderr, "su: exec failed\n");
    return 1;
}

 

 

 

 

HTML Link to an URL+Random number

 

<a href="http://lexra.pixnet.net/blog/post/289782841?1" onClick="this.href=this.href.split('?')[0]+'?'+new Date().getTime()">LINK</a>

 

 

 

 

 

 

 

 

arrow
arrow

    Lexra 發表在 痞客邦 留言(0) 人氣()