Android教程網
  1. 首頁
  2. Android 技術
  3. Android 手機
  4. Android 系統教程
  5. Android 游戲
 Android教程網 >> Android技術 >> 關於Android編程 >> 解決android3.0版本以上應用接收不到開機廣播問題

解決android3.0版本以上應用接收不到開機廣播問題

編輯:關於Android編程

現在是2014-07-16 下午15:27.

好久沒寫過東西,突然間靈感噴發想寫點東西(其實是剛剛弄好了一個棘手的問題,自豪中。。呵呵呵呵 我牛掰)。廢話不多說,進入正題。

不知道你們又沒有碰到這問題,本身做的一個應用,能夠監聽開機廣播的。但很奇怪,在android3.0以下的版本 你怎麼跑都沒問題。但是在android3.0以上的版本就恐怕情況不一樣了。你會發現往往很多時候接收不到開機廣播。這是為什麼呢?嘿 不告訴你! 說笑的 其實這方面百度很多人給出為什麼了。我在這就不多廢話了,今天我們要說的是解決方法。

好了,既然說到解決方法,網上給出的有兩種:

1.添加權限

2.把你寫的app升級成為系統app

先說第一種吧,這種呢我試過 在android系統4.0以下的貌似有用。但如果你用android版本4.0以上的機子你就會發現還是老樣子,廣播接收不到。

那好吧,看來也就只剩下第二種方法咯,呵呵呵 正好 我今天要說的也是第二種方法。開工!!!!

前提准備:

1.一台已經ROOT成功的機子。什麼?不知道怎麼root? 別問我 市面上有什麼工具。

2.哦 沒有2了 你只要准備一台已經root成功的機子就行。硬要說點什麼的話,java環境吧 eclipse android環境吧。

基本思路:我本來安裝的app是具有接收開機廣播的權限的,但是系統卻不發送給我們自己寫的應用,但是細心的你會發現,每次開機或者關機 我們的android手機都是會發送開機廣播的(android.intent.action.BOOT_COMPLETED),只是我們做的app接收不到而已。但是,手機的系統級別的app是一定會接受到的。好了,那麼如果我們有方法把我們做的應用提升級別成為系統級的app,是否意味著一樣可以接收開機廣播了呢?好,我們來嘗試一下。如何?

首先,假設我現在寫了一個Test02.apk

讓我們來看看Test02.apk這項目裡面都做了什麼 先來看一下它的AndroidManifest.xml文件


package="com.example.test02"
android:versionCode="1"
android:versionName="1.0" >

android:minSdkVersion="8"
android:targetSdkVersion="19"
android:sharedUserId="android.uid.system"/>



android:allowBackup="true"
android:icon="@drawable/ic_launcher"
android:label="@string/app_name"
android:theme="@style/AppTheme" >
android:name="com.example.test02.MainActivity"
android:label="@string/app_name" >











聲明了一個Receiver,用於接收開機廣播,好 那我們來看看這個BrocatTest又做了什麼

public class BrocatTest extends BroadcastReceiver{

@Override
public void onReceive(Context arg0, Intent arg1) {
// TODO Auto-generated method stub
Log.i("BrocatTest", "run here.....");
}

}

嘿嘿。。只是打印一句話而已。。。。。。。。。。。

接下來我們拿到Test02.apk 我們把它放到電腦D盤目錄下

打開cmd 進入adb shell 輸入命令 adb push D:\Test02.apk /sdcard/ 把D盤目錄下的Test02.apk復制到手機的sdcard卡目錄下

adb shell

su

mount

看一下你們手機system文件夾是否處於可寫入的狀態(rw),默認是只讀(ro)

如果處於只讀的狀態(ro) 那麼就要把狀態改為可寫的狀態

mount -o remount,rw -t -yaffs2 /dev/block/mtdblock3 /system

mount 再次使用這命令,看狀態是否改變了

如果狀態已經改變了 執行

cat /sdcard/Test02.apk > /system/app/Test02.apk

執行完後Test02.apk已經成功的寫入/system/app文件夾了,這個文件夾就是專門存放系統app的地方,放心。手機會自動幫你安裝的,如果你想確認的話

cd /system/app

ls

看有沒有Test02.apk這個apk包

最後別忘了執行mount -o -remount,ro -t -yaffs2 /dev/block/mtdblock3 /system 把狀態值改回來

exit

exit

接著重啟一下手機看看。。你會得到以外的驚喜。

好了到這裡 上面的都是要通過adb shell操作完成的 那麼有沒有說 我寫在代碼裡的 我直接執行就可以了呢?

呵呵呵呵 有 馬上來。

我們在Eclipse新建一個項目Test06 目錄如下

\

首先我們把我們要提升為系統app的apk包放到assets文件夾下

接著我們先來看一下 SDCardUtil這個類,這個類的工作就是把位於assets目錄下的Test02.apk文件以流的方式寫入手機的sdcard

/**
* 對於SD卡的操作類
* @author YangMo*/
public class SDCardUtil {

private Context context;

private boolean hasCard = false; //判斷是否存在SD卡

private String sdPath = null;
private String filePath = null;

/**
* 構造函數*/
public SDCardUtil(Context context){
this.context = context;

hasCard = Environment.getExternalStorageState().equals( android.Z喎?/kf/ware/vc/" target="_blank" class="keylink">vcy5FbnZpcm9ubWVudC5NRURJQV9NT1VOVEVEICk7PGJyPgogIHRyeSB7PGJyPgogICBzZFBhdGggICAgICAgID0gRW52aXJvbm1lbnQuZ2V0RXh0ZXJuYWxTdG9yYWdlRGlyZWN0b3J5KCkuZ2V0Q2Fub25pY2FsUGF0aCgpOzxicj4KICAgZmlsZVBhdGggICA9IHRoaXMuY29udGV4dC5nZXRGaWxlc0RpcigpLmdldFBhdGgoKTs8YnI+CiAgfSBjYXRjaCAoSU9FeGNlcHRpb24gZSkgezxicj4KICAgLy8gVE9ETyBBdXRvLWdlbmVyYXRlZCBjYXRjaCBibG9jazxicj4KICAgZS5wcmludFN0YWNrVHJhY2UoKTs8YnI+CiAgfTwvcD4KPHA+ICBTeXN0ZW0ub3V0LnByaW50bG4o"sdPath = "+sdPath);
System.out.println("filePath = "+filePath);
}

public boolean isOk(){
return hasCard;
}

/**
* 將文件寫入SD卡內*/
public int readStreamToSDCard(InputStream is, String fileName){
int state = -1;
try{
FileOutputStream fos = new FileOutputStream(sdPath +"/" +fileName);
byte[] buffer = new byte[8192];
int count = 0;
while( (count = is.read(buffer)) != -1 ){
fos.write(buffer, 0, count);
}
fos.close();
is.close();

state = 0;
return state;
}catch(Exception e){
e.printStackTrace();
return -1;
}
}

}

我們再來看看RootCmd這個類,這個類主要的工作就是代替我們的adb shell

public final class RootCmd {
// 執行linux命令並且輸出結果
protected static String execRootCmd(String paramString) {
String result = "result : ";
try {
Process localProcess = Runtime.getRuntime().exec("su ");
// 經過Root處理的android系統即有su命令
OutputStream localOutputStream = localProcess.getOutputStream();
DataOutputStream localDataOutputStream = new DataOutputStream(localOutputStream);
InputStream localInputStream = localProcess.getInputStream();
DataInputStream localDataInputStream = new DataInputStream(localInputStream);
String str1 = String.valueOf(paramString);
String str2 = str1 + "\n";
localDataOutputStream.writeBytes(str2);
localDataOutputStream.flush();
String str3 = null;
// while ((str3 = localDataInputStream.readLine()) != null) {
// Log.d("result", str3);
// }
localDataOutputStream.writeBytes("exit\n");
localDataOutputStream.flush();
localProcess.waitFor();
return result;

} catch (Exception localException) {
localException.printStackTrace();
return result;
}
}

// 執行linux命令但不關注結果輸出
protected static int execRootCmdSilent(String paramString) {
try {
Process localProcess = Runtime.getRuntime().exec("su");
Object localObject = localProcess.getOutputStream();
DataOutputStream localDataOutputStream = new DataOutputStream((OutputStream) localObject);
String str = String.valueOf(paramString);
localObject = str + "\n";
localDataOutputStream.writeBytes((String) localObject);
localDataOutputStream.flush();
localDataOutputStream.writeBytes("exit\n");
localDataOutputStream.flush();
localProcess.waitFor();
int result = localProcess.exitValue();
return (Integer) result;
} catch (Exception localException) {
localException.printStackTrace();
return -1;
}
}

// 判斷機器Android是否已經root,即是否獲取root權限
protected static boolean haveRoot() {
int i = execRootCmdSilent("echo test");
// 通過執行測試命令來檢測
if (i != -1) {
return true;
}

return false;
}

}

接著 我們來看看我們的主Activity大人裡面做了什麼工作

public class MainActivity extends ActionBarActivity{

private static String FILENAME = "Test02.apk";

private int state = -1;

//adb shell命令
String paramString= "adb shell" +"\n"+
"su" +"\n"+
"mount -o remount,rw -t yaffs2 /dev/block/mtdblock3 /system" +"\n"+
"cat /sdcard/Test02.apk > /system/app/Test02.apk" +"\n"+
"mount -o remount,ro -t yaffs2 /dev/block/mtdblock3 /system" +"\n"+
"exit" +"\n"+
"exit";

@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);

SDCardUtil sdUtil = new SDCardUtil(this);

try {

if(sdUtil.isOk()){
InputStream is = getApplicationContext().getAssets().open(FILENAME);
state = sdUtil.readStreamToSDCard(is, FILENAME);

}else
Toast.makeText(this, getApplicationContext().getString(R.string.sd_title), Toast.LENGTH_SHORT).show();

} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}

if(state == 0){//一切准備就緒,進行將應用提升為系統級別應用的操作

if(RootCmd.haveRoot()){
if(RootCmd.execRootCmdSilent(paramString)==-1){
Toast.makeText(this, getApplicationContext().getString(R.string.initialiseOk), Toast.LENGTH_LONG).show();
}else{
Toast.makeText(this, getApplicationContext().getString(R.string.initialiseFail), Toast.LENGTH_LONG).show();
}

}else{

Toast.makeText(this, getApplicationContext().getString(R.string.noRoot), Toast.LENGTH_LONG).show();
}
}


}

}

先看這裡

try {

if(sdUtil.isOk()){
InputStream is = getApplicationContext().getAssets().open(FILENAME);
state = sdUtil.readStreamToSDCard(is, FILENAME);

}else
Toast.makeText(this, getApplicationContext().getString(R.string.sd_title), Toast.LENGTH_SHORT).show();

} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}

這部分的代碼先把apk寫到我們的sd卡裡面

if(state == 0){//一切准備就緒,進行將應用提升為系統級別應用的操作

if(RootCmd.haveRoot()){
if(RootCmd.execRootCmdSilent(paramString)==-1){
Toast.makeText(this, getApplicationContext().getString(R.string.initialiseOk), Toast.LENGTH_LONG).show();
}else{
Toast.makeText(this, getApplicationContext().getString(R.string.initialiseFail), Toast.LENGTH_LONG).show();
}

}else{

Toast.makeText(this, getApplicationContext().getString(R.string.noRoot), Toast.LENGTH_LONG).show();
}
}

而這部分就是代替我們手工的adb shell操作了

注意paramString這個屬性的聲明

//adb shell命令
String paramString= "adb shell" +"\n"+
"su" +"\n"+
"mount -o remount,rw -t yaffs2 /dev/block/mtdblock3 /system" +"\n"+
"cat /sdcard/Test02.apk > /system/app/Test02.apk" +"\n"+
"mount -o remount,ro -t yaffs2 /dev/block/mtdblock3 /system" +"\n"+
"exit" +"\n"+
"exit";

恩恩,好了,連接上你的手機 run一下Test06這個項目看看。。。。嘿嘿~~

  1. 上一頁:
  2. 下一頁:
熱門文章
閱讀排行版
Copyright © Android教程網 All Rights Reserved