Android之getSystemService方法实现详解

一、概述


Android应用层获取系统java层的service, 用到getSystemService这个API。getSystemService方法定义于context类, 但context类是一个抽象类,它的具


体实现在contextImpl类中, getSystemService方法在contextImpl类中的代码如下:

 

   @Override

   public Object getSystemService(String name) {

       ServiceFetcher fetcher = SYSTEM_SERVICE_MAP.get(name);

       return fetcher == null ? null : fetcher.getService(this);

}


 二、ServiceFetcher类

 

   /*package*/ static class ServiceFetcher {

       int mContextCacheIndex = -1;

 

       /**

        * Main entrypoint; only override if you don't need caching.

        */

       public Object getService(ContextImpl ctx) {

           ArrayList<Object> cache = ctx.mServiceCache;

           Object service;

           synchronized (cache) {

                if (cache.size() == 0) {

                    // Initialize the cachevector on first access.

                    // At this pointsNextPerContextServiceCacheIndex

                    // is the number ofpotential services that are

                    // cached per-Context.

                   for (int i = 0; i <sNextPerContextServiceCacheIndex; i++) {

                        cache.add(null);

                    }

                } else {

                    service =cache.get(mContextCacheIndex);

                    if (service != null) {

                        return service;

                    }

                }

                service = createService(ctx);

                cache.set(mContextCacheIndex,service);

                return service;

           }

       }

 

       /**

        * Override this to create a new per-Context instance of the

        * service.  getService() willhandle locking and caching.

        */

       public Object createService(ContextImpl ctx) {

           throw new RuntimeException("Not implemented");

       }

    }

 

 

ServiceFetcher类是一个辅助,用于获取系统中的service, 这个类比较简单,只定义了getService和createService方法。每个java层的service, 如wifiservice,


 activitymanagerservice等都会建立一个ServiceFetcher类的对象,这个对象会重载createService方法,并且这个对象会通过contextImpl类中的registerService


方法添加到SYSTEM_SERVICE_MAP(详见下文)这个hashmap变量中。

 

registerService方法代码如下:

 

    private static void registerService(StringserviceName, ServiceFetcher fetcher) {

        if (!(fetcher instanceofStaticServiceFetcher)) {

            fetcher.mContextCacheIndex =sNextPerContextServiceCacheIndex++;

        }

        SYSTEM_SERVICE_MAP.put(serviceName,fetcher);

    } 


在contextImpl类的静态块中会完成所有java层的service添加到SYSTEM_SERVICE_MAP的操作, 代码如下:

 

static {

        registerService(ACCESSIBILITY_SERVICE,new ServiceFetcher() {

                public ObjectgetService(ContextImpl ctx) {

                    returnAccessibilityManager.getInstance(ctx);

                }});

 

        registerService(ALARM_SERVICE, newStaticServiceFetcher() {

                public ObjectcreateStaticService() {

                    IBinder b =ServiceManager.getService(ALARM_SERVICE);

                    IAlarmManager service =IAlarmManager.Stub.asInterface(b);

                    return newAlarmManager(service);

                }});

……

}

 

要明白ServiceFetcher的作用,只要明白createService和getService方法。createService方法本身没有实现,需要重载来实现的,下面是一个重载的例子。


        registerService(ALARM_SERVICE, new StaticServiceFetcher() {

                publicObject createStaticService() {

                   IBinder b = ServiceManager.getService(ALARM_SERVICE);

                   IAlarmManager service = IAlarmManager.Stub.asInterface(b);

                   return new AlarmManager(service);

                }});


如果读者对android的binder机制比较熟悉的话,很快就明白这几行代码的目的是获得AlarmManagerService的代理对象,然后以这个代理对象为参数构造


AlarmManager对象,也就是说createService方法最后返回了AlarmManger对象。至于getService方法,阅读一下getService方法的源码,不难看出该方法先在


一个用于cache功能的arraylist中查找service,如果没有找到,就通过createSystem方法创建一个,并返回。



由上可知,ServiceFetcher的作用是通过createService方法获得xxxManager对象,然后通过getService方法返回给上层。


 

三、SYSTEM_SERVICE_MAP变量

 

SYSTEM_SERVICE_MAP是一个hashmap变量,存放的是service名称与service对应的servicefetcher

 

    private static final HashMap<String,ServiceFetcher> SYSTEM_SERVICE_MAP =

            new HashMap<String,ServiceFetcher>();

 

 

四、 总结


好了,了解以上内容后,我们再来看getSystemService方法的实现,

 

   @Override

   public Object getSystemService(String name) {

       ServiceFetcher fetcher = SYSTEM_SERVICE_MAP.get(name);

       return fetcher == null ? null : fetcher.getService(this);

}

 


首先,通过传入的service name从SYSTEM_SERVICE_MAP这个hashmap中获得一个ServiceFetcher对象,这个对象同一个service绑定。


然后,通过上面获得的ServiceFetcher的getService方法取得一个xxxManager对象(每个java层的service都实现了一个xxxManager类,这个类为该service


封装API供应用层调用)。


这样,应用层就可以通过这个xxxManager来使用对应的service提供的功能。


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Android倒车轨迹线的实现方法可以分为两种,一种是使用Camera2 API获取摄像头预览画面并在上面绘制轨迹线,另一种是使用第三方库实现。 1. 使用Camera2 API获取摄像头预览画面并在上面绘制轨迹线 首先需要在AndroidManifest.xml文件中添加摄像头权限: ```xml <uses-permission android:name="android.permission.CAMERA" /> ``` 然后在布局文件中添加TextureView控件用于预览摄像头画面: ```xml <TextureView android:id="@+id/textureView" android:layout_width="match_parent" android:layout_height="match_parent" /> ``` 接下来,在Activity中获取TextureView控件并打开后置摄像头: ```java private TextureView textureView; private CameraDevice cameraDevice; private CameraCaptureSession cameraCaptureSession; private CaptureRequest.Builder captureRequestBuilder; private HandlerThread backgroundThread; private Handler backgroundHandler; private Size imageDimension; private void openCamera() { CameraManager manager = (CameraManager) getSystemService(Context.CAMERA_SERVICE); try { String cameraId = manager.getCameraIdList()[0]; CameraCharacteristics characteristics = manager.getCameraCharacteristics(cameraId); StreamConfigurationMap map = characteristics.get(CameraCharacteristics.SCALER_STREAM_CONFIGURATION_MAP); imageDimension = map.getOutputSizes(SurfaceTexture.class)[0]; manager.openCamera(cameraId, stateCallback, null); } catch (CameraAccessException e) { e.printStackTrace(); } } private final CameraDevice.StateCallback stateCallback = new CameraDevice.StateCallback() { @Override public void onOpened(@NonNull CameraDevice camera) { cameraDevice = camera; createCameraPreview(); } @Override public void onDisconnected(@NonNull CameraDevice camera) { cameraDevice.close(); } @Override public void onError(@NonNull CameraDevice camera, int error) { cameraDevice.close(); cameraDevice = null; } }; private void createCameraPreview() { SurfaceTexture texture = textureView.getSurfaceTexture(); texture.setDefaultBufferSize(imageDimension.getWidth(), imageDimension.getHeight()); Surface surface = new Surface(texture); try { captureRequestBuilder = cameraDevice.createCaptureRequest(CameraDevice.TEMPLATE_PREVIEW); captureRequestBuilder.addTarget(surface); cameraDevice.createCaptureSession(Collections.singletonList(surface), new CameraCaptureSession.StateCallback() { @Override public void onConfigured(@NonNull CameraCaptureSession session) { if (cameraDevice == null) return; cameraCaptureSession = session; updatePreview(); } @Override public void onConfigureFailed(@NonNull CameraCaptureSession session) { } }, null); } catch (CameraAccessException e) { e.printStackTrace(); } } private void updatePreview() { if (cameraDevice == null) return; captureRequestBuilder.set(CaptureRequest.CONTROL_MODE, CameraMetadata.CONTROL_MODE_AUTO); try { cameraCaptureSession.setRepeatingRequest(captureRequestBuilder.build(), null, backgroundHandler); } catch (CameraAccessException e) { e.printStackTrace(); } } ``` 以上代码中,首先通过CameraManager获取后置摄像头的ID,然后获取该摄像头的特性和输出尺寸,在onOpened()方法中创建CameraCaptureSession并设置预览画面,最后在updatePreview()方法中更新预览画面。 接下来,可以在预览画面上绘制倒车轨迹线。通过TextureView控件获取画布并绘制轨迹线: ```java private void drawPath() { Paint paint = new Paint(); paint.setStyle(Paint.Style.STROKE); paint.setStrokeWidth(5); paint.setColor(Color.RED); Bitmap bitmap = textureView.getBitmap(); Canvas canvas = textureView.lockCanvas(); canvas.drawBitmap(bitmap, 0, 0, null); Path path = new Path(); path.moveTo(0, textureView.getHeight() / 2); path.lineTo(textureView.getWidth(), textureView.getHeight() / 2); canvas.drawPath(path, paint); textureView.unlockCanvasAndPost(canvas); } ``` 以上代码中,首先获取TextureView控件的Bitmap对象,然后获取画布并绘制预览画面,最后绘制轨迹线并释放画布。 2. 使用第三方库实现 除了使用Camera2 API自行实现倒车轨迹线外,也可以使用第三方库实现。常用的第三方库有CameraView和CameraKit-Android。 以CameraView为例,首先需要在build.gradle文件中添加依赖: ```groovy implementation 'com.otaliastudios:cameraview:2.7.2' ``` 然后在布局文件中添加CameraView控件: ```xml <com.otaliastudios.cameraview.CameraView android:id="@+id/cameraView" android:layout_width="match_parent" android:layout_height="match_parent" /> ``` 接下来,在Activity中获取CameraView控件并设置预览画面: ```java private CameraView cameraView; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); cameraView = findViewById(R.id.cameraView); cameraView.setLifecycleOwner(this); cameraView.addFrameProcessor(frame -> drawPath()); } ``` 以上代码中,首先获取CameraView控件并设置生命周期,然后添加FrameProcessor用于在预览画面上绘制倒车轨迹线。 最后,实现drawPath()方法绘制倒车轨迹线: ```java private void drawPath() { Paint paint = new Paint(); paint.setStyle(Paint.Style.STROKE); paint.setStrokeWidth(5); paint.setColor(Color.RED); Bitmap bitmap = cameraView.getBitmap(); Canvas canvas = cameraView.getPreviewCanvas(); Path path = new Path(); path.moveTo(0, cameraView.getHeight() / 2); path.lineTo(cameraView.getWidth(), cameraView.getHeight() / 2); canvas.drawPath(path, paint); } ``` 以上代码中,首先获取CameraView控件的Bitmap对象,然后获取预览画面的画布并绘制轨迹线。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值