2011年4月28日 星期四

Android應用程式權限問題

一切的起因都是因為android:sharedUserId="android.uid.system"這句指令
使用NDK編譯了一個執行檔D2MCEDaemon
想要直接使用Android應用程式開啟他,但是一直開不起來
後來找到了可以輸出system.out的程式所以才發現原來是權限不足

程式碼是從哪裡找到的已經忘記了
首先在註冊檔上加入android:sharedUserId="android.uid.system"




然後勒
寫一個可以執行底層命令的程式

public class TESTTPERMISSION extends Activity {
 private static final String TAG = "execCommand";
 
 /** Called when the activity is first created. */
 @Override
 public void onCreate(Bundle savedInstanceState) {
  super.onCreate(savedInstanceState);
  setContentView(R.layout.main);
  setTitle("This is Matrix.");
  
  runRootCommand("/data/local/bin/D2MCEDaemon");
 }
 
 public static boolean runRootCommand(String command) {
        Process process = null;
        DataOutputStream os = null;
            try {
            process = Runtime.getRuntime().exec(command);
           // Log.e("runRootCommand", "su");
            os = new DataOutputStream(process.getOutputStream());
           // os.writeBytes(command+"\n");
            Log.e("runRootCommand", command);
            //os.writeBytes("exit\n");
            os.flush();
            process.waitFor();
            
            String line = null;
            
   InputStream stderr = process.getErrorStream();
   InputStreamReader esr = new InputStreamReader(stderr);
   BufferedReader ebr = new BufferedReader(esr);
   System.out.println("");
   while ((line = ebr.readLine()) != null) {
    System.out.println(line);
    Log.e("runRootCommand", line);
   }
   System.out.println("");

   InputStream stdout = process.getInputStream();
   InputStreamReader osr = new InputStreamReader(stdout);
   BufferedReader obr = new BufferedReader(osr);
   System.out.println("");
   while ((line = obr.readLine()) != null) {
    System.out.println(line);
    Log.e("runRootCommand", line);
   }
   System.out.println("");

            int exitVal = process.waitFor ();
            System.out.println ("Process exitValue: " + exitVal);
            Log.e("runRootCommand", String.valueOf(exitVal));
                                          
            } catch (Exception e) {
                    Log.d("*** DEBUG ***", "Unexpected error - Here is what I know: "+e.getMessage());
                    return false;
            }
            finally {
                    try {
                            if (os != null) {
                                    os.close();
                            }
                            process.destroy();
                    } catch (Exception e) {
                            // nothing
                    }
            }
            return true;
    }

}



明顯的看見我們是想要執行runRootCommand("/data/local/bin/D2MCEDaemon");
這個Command
但是呢
第一個問題
如果沒加上這一行android:sharedUserId="android.uid.system"
他會說permission denied
這讓我頭痛了許多天
第二
加上了android:sharedUserId="android.uid.system"
卻出現
[2011...] Installation error: INSTALL_FAILED_SHARED_USER_INCOMPATIBLE
[2011...] Please check logcat output for more details.
[2011...] Launch canceled!
真的是氣死我了

麻煩的來了
網路上找了一些文章
像是
http://www.wretch.cc/blog/michaeloil/23398272
http://owen-hsu.blogspot.com/2010/09/android-apkuid.html
http://joshzhchen.blogspot.com/2010/09/androidshareduserid.html
http://blog.csdn.net/liujian885/archive/2010/03/22/5404834.aspx
完全看不懂
乖乖的自己去download Android source code之後卻一點頭緒也沒有
至於怎麼download source code
自己去android官網就有教學了
然後自己找了一些有關於signapk的文章
因為上面那些連結根本沒解釋什麼是signapk
好吧
找了一些
http://www.techwen.com/mobile/android/20101215/1422.html
http://www.bangchui.org/read.php?tid=11094
http://hi.baidu.com/langhongjian/blog/item/645a7d2427ecd1144c088d92.html

後來發現是sign的問題

先下載android source code
然後到 cd ~/AndroidSourceCode/build/tools/signapk
再來會看到SignApk.java
執行這一行javac SignApk.java
會出現SignApk$SignatureOutputStream.class和SignApk.class
建立目录s\com\android\signapk在signapk目錄底下
自己慢慢的mkdir
反正要建立完整
再來執行
jar cvfm signapk.jar SignApk.mf -C ./s .

然後會出現signapk.jar
這樣就OK拉~
然後利用Eclipse編譯APK
再專案上右鍵選擇Android tools->Export Unsigned Application Package
這樣就有APK拉~
然後回到linux的signapk目錄底下
執行java -jar signapk.jar platform.x509.pem platform.pk8 input.apk output.apk
大功告成
至於platform.x509.pem platform.pk8在AndroidSourceCode\build\target\product\security目錄底下

然後使用adb install output.apk
終於完成摟