首页 > 其他分享 >Android之Service设置android:process作用

Android之Service设置android:process作用

时间:2023-04-26 15:00:10浏览次数:47  
标签:Service service process Application 进程 Android data android

原文地址 blog.csdn.net

在AndroidManifest.xml中定义service时会看到这样的代码android:process=”:remote”,例如:



1.  <service
2.      android:
3.      android:enabled="true"
4.      android:exported="false"
5.      android:process=":remote" />


这个代码是什么意思呢?

我们先来了解一下Service在AndroidManifest.xml中的声明语法,其格式如下:

<service android:enabled=["true" | "false"]
    android:exported=["true" | "false"]
    android:icon="drawable resource"
    android:isolatedProcess=["true" | "false"]
    android:label="string resource"
    android:
    android:permission="string"
    android:process="string" >
    . . .

  • android:exported:代表是否能被其他应用隐式调用,其默认值是由service中有无intent-filter决定的,如果有intent-filter,默认值为true,否则为false。为false的情况下,即使有intent-filter匹配,也无法打开,即无法被其他应用隐式调用。
  • android:name:对应Service类名
  • android:permission:是权限声明
  • android:process:是否需要在单独的进程中运行,当设置为android:process=”:remote”时,代表Service在单独的进程中运行。注意“:”很重要,它的意思是指要在当前进程名称前面附加上当前的包名,所以“remote”和”:remote”不是同一个意思,前者的进程名称为:remote,而后者的进程名称为:App-packageName:remote。
  • android:isolatedProcess :设置 true 意味着,服务会在一个特殊的进程下运行,这个进程与系统其他进程分开且没有自己的权限。与其通信的唯一途径是通过服务的API(bind and start)。
  • android:enabled:是否可以被系统实例化,默认为 true因为父标签 也有 enable 属性,所以必须两个都为默认值 true 的情况下服务才会被激活,否则不会激活。

1)默认情况(不指定process属性)

1、一个app只运行在一个进程中,进程名字为包名。
2、一个service(所有组件都一样)只作为一个线程运行在app的进程中,没有自己独立的进程。

2)****设置android:process="xxxx"后

1、设置了这行代码,系统就会为service创建新的进程

service将运行在这个新的独立的进程,它所在的apk依旧运行在原来进程。这样就实现了Android使用多进程
2、属性值可以随意定义
       xxxx是自定义的,上面代码的remote是随便写的
3、当属性值以冒号开头   :,如 android:process  = “ :xxxx ”
       表示:将为 app 创建一个私有进程,其他 app 无法访问,进程名称是:包名: xxxx
4、当属性值以小写字母开头,如 android:process = “xxxx”
       表示:这个进程是对外公开的,其他app可以访问它,进程名称是:xxxx

注意:a) 和四大组件节点都可设置
             b)设置 可以指定app的进程名称
             c)若 节点和四大组件都设置了android:process="xxx:xxxx"属性,以组件的属性为准

下面援引官方说明文档:

3)多进程引发的问题

静态成员和单例失效:每个进程保持各自的静态成员和单例,相互独立。
线程同步机制失效:每个进程有自己的线程锁。
SharedPreferences可靠性下降:不支持并发写,会出现脏数据
Application多次创建:不同进程跑在不同虚拟机,每个虚拟机启动会创建自己的Application,自定义Application时生命周期会混乱。
综上,不同进程拥有各自独立的虚拟机,Application,内存空间,由此引发一系列问题,因此在跨进程通信开发时,要注意避开上述问题。

重点来了,因为设置了 android:process 属性将组件运行到另一个进程,相当于另一个应用程序,所以在另一个线程中也将新建一个 Application 的实例。因此,每新建一个进程 Application 的 onCreate 都将被调用一次。 如果在 Application 的 onCreate 中有许多初始化工作并且需要根据进程来区分的,那就需要特别注意了。

让我们到 Framework 中看看新建进程的逻辑,请打开老罗的博客 : Android系统在新进程中启动自定义服务过程(startService)的原理分析

详细介绍了新进程启动的过程,其中我们重点看到 Step 17. ActivityThread.handleCreateService中

`1.  public final class ActivityThread {  

3.      ......  

5.      private final void handleCreateService(CreateServiceData data) {  
6.          // If we are getting ready to gc after going to the background, well  
7.          // we are back active so skip it.  
8.          unscheduleGcIdler();  

10.          LoadedApk packageInfo = getPackageInfoNoCheck(  
11.              data.info.applicationInfo);  
12.          Service service = null;  
13.          try {  
14.              java.lang.ClassLoader cl = packageInfo.getClassLoader();  
15.              service = (Service) cl.loadClass(data.info.name).newInstance();  
16.          } catch (Exception e) {  
17.              if (!mInstrumentation.onException(service, e)) {  
18.                  throw new RuntimeException(  
19.                      "Unable to instantiate service " + data.info.name  
20.                      + ": " + e.toString(), e);  
21.              }  
22.          }  

24.          try {  
25.              if (localLOGV) Slog.v(TAG, "Creating service " + data.info.name);  

27.              ContextImpl context = new ContextImpl();  
28.              context.init(packageInfo, null, this);  

30.              Application app = packageInfo.makeApplication(false, mInstrumentation);  
31.              context.setOuterContext(service);  
32.              service.attach(context, this, data.info.name, data.token, app,  
33.                  ActivityManagerNative.getDefault());  
34.              service.onCreate();  
35.              mServices.put(data.token, service);  
36.              try {  
37.                  ActivityManagerNative.getDefault().serviceDoneExecuting(  
38.                      data.token, 0, 0, 0);  
39.              } catch (RemoteException e) {  
40.                  // nothing to do.  
41.              }  

43.          } catch (Exception e) {  
44.              if (!mInstrumentation.onException(service, e)) {  
45.                  throw new RuntimeException(  
46.                      "Unable to create service " + data.info.name  
47.                          + ": " + e.toString(), e);  
48.              }  
49.          }  
50.      }  

52.      ......  

54.  }` ![](https://csdnimg.cn/release/blogv2/dist/pc/img/newCodeMoreWhite.png)

看到这行 Application app = packageInfo.makeApplication(false, mInstrumentation); 在这里创建了 Application 。

解决方案

获取当前运行进程的名称:



1.  方案1
2.  public static String getProcessName(Context cxt, int pid) {  
3.      ActivityManager am = (ActivityManager) cxt.getSystemService(Context.ACTIVITY_SERVICE);  
4.      List<RunningAppProcessInfo> runningApps = am.getRunningAppProcesses();  
5.      if (runningApps == null) {  
6.          return null;  
7.      }  
8.      for (RunningAppProcessInfo procInfo : runningApps) {  
9.          if (procInfo.pid == pid) {  
10.              return procInfo.processName;  
11.          }  
12.      }  
13.      return null;  
14.  }  
15.  目前网上主流的方法,但效率没有方案2高,感谢由王燚同学提供的方案2

17.  方案2
18.  public static String getProcessName() {
19.    try {
20.      File file = new File("/proc/" + android.os.Process.myPid() + "/" + "cmdline");
21.      BufferedReader mBufferedReader = new BufferedReader(new FileReader(file));
22.      String processName = mBufferedReader.readLine().trim();
23.      mBufferedReader.close();
24.      return processName;
25.    } catch (Exception e) {
26.      e.printStackTrace();
27.      return null;
28.    }
29.  }
30.  然后在 Application 的 onCreate 中获取进程名称并进行相应的判断,例如:

32.  String processName = getProcessName(this, android.os.Process.myPid());

34.  if (!TextUtils.isEmpty(processName) && processName.equals(this.getPackageName())) {//判断进程名,保证只有主进程运行
35.      //主进程初始化逻辑
36.      ....
37.  }


4)如何实现跨进程通讯?

使用AIDL

标签:Service,service,process,Application,进程,Android,data,android
From: https://www.cnblogs.com/cps666/p/17356092.html

相关文章

  • Android音频开发之音频基本概念
    原文地址www.jianshu.comAndroid音频开发之音频基本概念音频采集一般使用AudioRecod或者MediaRecord音频采集的来源是什么?MediaRecorder.AudioSource.MIC一般是麦克风采样率(单位:赫兹)每秒钟音频采样点个数(8000/44100Hz),模拟信号数字化的过程,用0101来表示的数......
  • Android音频开发之AudioTrack
    原文地址www.jianshu.com在前两节中分享了Android音频开发之音频基本概念和Android音频开发之音频采集,本文分享的是如何使用AudioTrack来播放使用AudioRecord采集后的PCM数据。构造AudioTrack实例publicAudioTrack(intstreamType,intsampleRateInHz,intcha......
  • Android音频开发之音频采集
    原文地址www.jianshu.comAndroid音频开发之音频采集在Android系统中,一般使用AudioRecord或者MediaRecord来采集音频。AudioRecord是一个比较偏底层的API,它可以获取到一帧帧PCM数据,之后可以对这些数据进行处理。而MediaRecorder是基于AudioRecorder的API(最......
  • python subprocess Popen非阻塞,读取adb日志
    简单版fromthreadingimportThreadfromqueueimportQueue,Emptyimportshlexif__name__=='__main__':print_hi('PyCharm')#Car().run()defenqueue_output(stdout,queue):withopen("www.log",'w......
  • Python中 os.popen、os.system和subprocess.popen方法介绍
    Python提供了多种与操作系统交互的方法,比如os模块中的popen和system方法,此外,Pythonsubprocess模块中的Popen类也提供了与操作系统交互的方法,使用起来更加灵活,本文将简单介绍这几种方法。目录os.popen方法os.system方法susbprocess.Popen方法替代os.popen()方法替代os.system......
  • Android 开发中打印日志
    在Android开发过程中,我们常常需要打印堆栈来定位问题或者调试问题,这里记录一下相关的方法。1.MTK平台1.1preloader 1.2LK 2.高通平台2.1sbl 2.2xbl 2.3abl  3.kernel  4.native层4.1打印堆栈 Android.bpcc_binary{name:"print_s......
  • Xamarin.Android给 EditText 添加焦点的扩展方法
    ///<summary>///定义了一个扩展方法SetFocus,作用是设置EditText控件的焦点,并可以选择全部选中或者仅选中最后一个字符///给EditText添加焦点的扩展方法,可选择是否全部选中///</summary>///<paramname="ed"></param>......
  • Android开发之一:10.0 USB弹窗权限流程解析
    1.新建activity,获取UsbManagerusbManager=(UsbManager)getSystemService(Context.USB_SERVICE)2.获取所以的USB设备HashMap<String,UsbDevice>map=usbManager.getDeviceList()3.过滤别的USB设备,拿到自己USB的USBDevice类,然后请求USB权限,usbManager.requestPermission(us......
  • 直播平台软件开发,一个简单的Android登录实现demo
    直播平台软件开发,一个简单的Android登录实现demo一、登录活动 packagecom.example.login; importandroid.content.Intent;importandroid.os.Bundle;importandroid.text.TextUtils;importandroid.view.View;importandroid.widget.Button;importandroid.widget.EditText......
  • Android源码在线查看网站
    一、aospxrefhttp://aospxref.com/优点:更新速度快缺点:历史版本较少二、androidxrefhttp://androidxref.com/优点:历史版本较多缺点:更新速度慢两者可搭配使用。非常便利三、Google在线源码上面两个的平台存在如下几点问题:搜索关键字困难且不精确,特别是对有括号和“_”的......