Root Phone

  要在 root 手機上寫 root 專用 APP,首先要會在 linux 系統下使用指令操作檔案,相關的檔案操作指令可以去 google "鳥哥",那位 linux 大師當在下還在讀高中時就在寫 linux 指令教學網頁了。

  在了解了基本的 linux 系統指令後,接下來就是把你的APP當做一個 linux 指令輸入 APP 來用,首先是像下面例子一樣,在 APP 啟動後自動開啟 root 程序,然後執行 root 手機才能做的事:把 /data/data/ 下的檔案修改權限成666!

... import 省略 ... (編譯不過請用 eclipse 的自動 import 功能幫你解決!)

protected Process _process = null;
protected DataOutputStream _outputStream = null;
protected DataInputStream _inputStream = null;
@Override
protected void onCreate(Bundle savedInstanceState)
{
	super.onCreate(savedInstanceState);
	SetupMain();
		
	//取得ROOT權限
	try 
	{
		_process = Runtime.getRuntime().exec("su");
		_outputStream = new DataOutputStream(_process.getOutputStream());
		_inputStream = new DataInputStream(_process.getInputStream());
	} 
	catch (IOException e)
	{
		// TODO Auto-generated catch block
		e.printStackTrace();
	}
		
	UnlockFile("/data/data/com.madhead.tos.zh/shared_prefs/","com.madhead.tos.zh.xml");
}

 

  在下的 UnlockFile 主要是將 /data/data/ 下的檔案權限打開,這邊在下直接拿手邊就有的 "神魔之塔" APP資料夾下的關卡資料 XML 檔案做例子,讓此 APP 或其他 APP 可以直接讀寫裡面的檔案。值得注意的是,由於是指令輸入,所以要等待指令跑完才能執行下一步,不然會有競賽的可能導致不預期的錯誤。在下這邊是使用一個確認視窗讓下一步不是馬上執行。如果很在意檔案被改權限可以在 onDestroy 函式裡將檔案的權限復原 (一般是660)。

private void UnlockFile(String sFilePath, String sFileName)
{
	if(!Write("su -c chmod 666 "+ sFilePath + sFileName +"\n"))
	{
		new AlertDialog.Builder(MainActivity.this)
		.setTitle("無法讀取!")
		.setMessage(sFilePath + sFileName + "\n無此檔案或異常終止")
		.setPositiveButton("OK", new DialogInterface.OnClickListener()
		{
			public void onClick( DialogInterface d, int i )
			{}
		}
		).show();
				
		return;
	}
	else
	{
		new AlertDialog.Builder(MainActivity.this)
		.setTitle("檔案授權成功!")
		.setMessage("請按確認進行下一步!")
		.setPositiveButton("OK", new DialogInterface.OnClickListener()
		{
			public void onClick( DialogInterface d, int i )
			{
				// DOTO 開始對該檔案進行讀寫
			}
		}
		).show();
	}
}

 

  由於此APP經常使用指令做事,所以在下將執行指令的程式碼用一個函式 Write 包起來。

public boolean Write(String sCommand)
{
	boolean bResult = false;
	if(_outputStream == null)
	{}
	else
	{	
		try 
		{
			_outputStream.writeBytes(sCommand);
			_outputStream.flush();	// 將指令刷進機器裡執行
		
			bResult = true;
		} 
		catch (IOException e) 
		{}
	}
	return bResult;
}

 

  有 Write 當然也有個 Read ,不過跟前面提過的注意事項一樣,Read 不能馬上在 Write 後面執行,看是要用的確認視窗檔著或是自行做定時檢查指令是否已執行完函式。Read 會把指令執行過程的輸出字串抓出來,之後可以針對換行做 Token 就可以在進一步做細部資訊處理。

public String Read()
{
	String sResult = "";
	if(_inputStream == null)
	{}
	else
	{
		int size = 0;
		byte[] buffer = new byte[1024];
		try 
		{
			do 
			{
				size = _inputStream.read(buffer);
				if(size > 0)
				{
					String sTemp = new String(buffer, 0, size, HTTP.UTF_8);
					sResult += sTemp;
				}
	
			}while(_inputStream.available() > 0);
		} 
		catch (IOException e) 
		{}
	}
	return sResult;
}

 

  基本上 Read 要拿來讀檔是要是用 cat 指令( ex : Write("su -c chmod 666 "+ sFilePath + sFileName +"\n") )後再接著跑的,這樣可以完全不用改檔案權限,只是像是 XML 檔之類的就要自己從頭開始建構 Reader 而不能使用 dom 之類的內建函式庫幫你讀檔,算是有利有弊看個人喜好!

 

  下面舉個使用 cat 指令加 Read 的讀檔方式,使用 String 型別內建的 split 函式可以將整串問字以特定字串 ( ex:"\n", 換行符號 ) 做區隔並轉出一個字串陣列。

String TempResults = Read();
String[] Token = TempResults.split("\n");

 

  另外,如果要存取外部記憶卡,記得要在 AndroidManifest.xml 裡加上以下這條。
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />

創作者介紹

折翼之流

G毛 發表在 痞客邦 PIXNET 留言(0) 人氣()