如今是2014-07-16 下午15:27.

好久没写过东西,突然间灵感喷发想写点东西(事实上是刚刚弄好了一个棘手的问题,自豪中。。呵呵呵呵 我牛掰)。废话不多说,进入正题。

不知道你们又没有碰到这问题,本身做的一个应用,可以监听开机广播的。但非常奇怪,在android3.0下面的版本号 你怎么跑都没问题。可是在android3.0以上的版本号就恐怕情况不一样了。你会发现往往非常多时候接收不到开机广播。这是为什么呢?嘿 不告诉你! 说笑的 事实上这方面百度非常多人给出为什么了。我在这就不多废话了,今天我们要说的是解决方法。

好了,既然说到解决方法,网上给出的有两种:

1.加入权限<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />

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文件

<?xml version="1.0" encoding="utf-8"?>

<manifest xmlns:android="http://schemas.android.com/apk/res/android"

    package="com.example.test02"

    android:versionCode="1"

    android:versionName="1.0" >

<uses-sdk

        android:minSdkVersion="8"

        android:targetSdkVersion="19"

        android:sharedUserId="android.uid.system"/>

<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED"/>

   

    <application

        android:allowBackup="true"

        android:icon="@drawable/ic_launcher"

        android:label="@string/app_name"

        android:theme="@style/AppTheme" >

        <activity

            android:name="com.example.test02.MainActivity"

            android:label="@string/app_name" >

            <intent-filter>

                <action android:name="android.intent.action.MAIN" />

<category android:name="android.intent.category.LAUNCHER" />

            </intent-filter>

        </activity>

       

        <receiver android:name="com.example.test02.BrocatTest">

            <intent-filter>

                <action android:name="android.intent.action.BOOT_COMPLETED"/>

                <category android:name="android.intent.category.HOME"/>

            </intent-filter>

        </receiver>

    </application>

</manifest>

声明了一个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.os.Environment.MEDIA_MOUNTED );

  try {

   sdPath        = Environment.getExternalStorageDirectory().getCanonicalPath();

   filePath   = this.context.getFilesDir().getPath();

  } catch (IOException e) {

   // TODO Auto-generated catch block

   e.printStackTrace();

  }

System.out.println("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这个项目看看。。。。嘿嘿~~

解决android3.0版本号以上应用接收不到开机广播问题的更多相关文章

  1. 解决Android3.0之后不能在主线程中进行HTTP请求

    感谢大佬:https://www.cnblogs.com/falzy/p/5763848.html 在Android3.0以后,会发现,只要是写在主线程(就是Activity)中的HTTP请求,运行时 ...

  2. iOS 9 平台上 AFNetworking 框架 3.0 版本号解决的问题和问题解决

    iOS 9 平台上 AFNetworking 框架 3.0 版本号解决的问题和问题解决 太阳火神的漂亮人生 (http://blog.csdn.net/opengl_es) 本文遵循"署名- ...

  3. android圆角View实现及不同版本这间的兼容(android3.0过后的版本)

    http://blog.csdn.net/lovecluo/article/details/8710174 在做我们自己的APP的时候,为了让APP看起来更加的好看,我们就需要将我们的自己的View做 ...

  4. VoltDB公布4.0版本号,大步提高内存实时分析速度,进军操作数据库市场

    号称世界上最快的关系数据库的VoltDB与2014年1月29号(美国东部时间)公布下一代数据库4.0版本号.新的版本号有非常多地方的改进,大步挺高系统性能.在过去的13年,VoltdDB号称自己公司较 ...

  5. 【Android】Android 4.0 无法接收开机广播的问题

    [Android]Android 4.0 无法接收开机广播的问题   前面的文章 Android 开机广播的使用 中 已经提到Android的开机启动,但是在Android 4.0 有时可以接收到开机 ...

  6. Mybatis分页插件2.0版本号公布

    项目地址:http://git.oschina.net/free/Mybatis_PageHelper 软件介绍:http://www.oschina.net/p/mybatis_pagehelper ...

  7. cookie工具类,解决servlet3.0以前不能添加httpOnly属性的问题

    最近在解决XSS注入的问题,由于使用的servlet版本是2.5,不支持httpOnly的属性,故做了个工具类来实现cookie的httpOnly的功能.全类如下: /** * cookie工具类,解 ...

  8. Android3.0中ActionBar的新特性

    1. ActionBar(活动栏)替代了显示在屏幕顶端的标题栏.主要负责显示菜单,widget,导航等功能,主要包括:@  显示选项菜单中的菜单项到活动栏:@  添加可交互的视图到活动栏作为活动视图: ...

  9. Spark 1.0.0版本号公布

    前言 今天Spark最终跨出了里程碑的一步,1.0.0版本号的公布标志着Spark已经进入1.0时代.1.0.0版本号不仅增加了非常多新特性,而且提供了更好的API支持.Spark SQL作为一个新的 ...

随机推荐

  1. (一)----使用HttpClient发送HTTP请求(通过get方法获取数据)

    (一)----使用HttpClient发送HTTP请求(通过get方法获取数据) 一.HTTP协议初探: HTTP(Hypertext Transfer Protocol)中文 “超文本传输协议”,是 ...

  2. C++智能指针--weak_ptr

    weak_ptr是对对象的一种弱引用,它不会添加对象的引用计数.weak_ptr和shared_ptr之间能够相互转换.shared_ptr能够直接赋值给week_ptr,week_ptr可通过调用l ...

  3. Java NIO实战之聊天室

    在工作之余花了两个星期看完了<Java NIO>.整体来说这本书把NIO写的非常具体,没有过多的废话,讲的都是重点,仅仅是翻译的中文版看的确实吃力.英文水平太低也没办法,总算也坚持看完了. ...

  4. codeforces 659B Qualifying Contest

    题目链接:http://codeforces.com/problemset/problem/659/B 题意: n个人,m个区.给出n个人的姓名(保证不相同),属于的区域,所得分数.从每个区域中选出成 ...

  5. DelphiXE7中创建WebService(服务端+客户端) good

    相关资料:http://www.2ccc.com/news/Html/?1507.html DelphiXE7新建WebService具体操作:1.打开“DelphiXE7”->“File”-& ...

  6. HP MSA2312 ERROR

    司在用的hp MAS2312存储其中一台每天都会报一个错误 EVENT:Vdisk verification failed. Command failed. (error code: 1) 2 err ...

  7. ios应用接入微信开放平台

    前几天试了一下服务端接入微信公众平台,昨天又看了一下APP接入开放平台 开放平台和公众平台的差别 公众平台针对的是公众账号,除了提供管理后台之外.也开放了若干接口,让微信server和开发人员自己的应 ...

  8. 使用KnockoutJs+Bootstrap实现分页

    [后端人员耍前端系列]KnockoutJs篇:使用KnockoutJs+Bootstrap实现分页   一.引言 由于最近公司的系统需要改版,改版的新系统我打算使用KnockoutJs来制作Web前端 ...

  9. 外语学习强烈推荐Rosetta Stone

    外语学习强烈推荐Rosetta Stone 外语学习强烈推荐Rosetta Stone

  10. Nagios监控系统的安装

    环境:centOS 6.5 X86 64位 nagios-4.08 步骤: 1.  最小化安装系统 2.  修改安全特性 关闭SELINUX     SELINUX=disabled 清除iptabl ...