RK3399 Android7.1 系统打印方案(一)编译
Android默认实现了打印的框架,使用PrintManager+PrintManagerService
但是有些系统裁剪了打印服务
一.packages\apps\Settings\src\com\android\settings\SettingsActivity.java
setTileEnabled(new ComponentName(packageName, Settings.PrintSettingsActivity.class.getName()), pm.hasSystemFeature(PackageManager.FEATURE_PRINTING), isAdmin, pm); private void setTileEnabled(ComponentName component, boolean enabled, boolean isAdmin, PackageManager pm) { if (UserHandle.MU_ENABLED && !isAdmin && getPackageName().equals(component.getPackageName()) && !ArrayUtils.contains(SETTINGS_FOR_RESTRICTED, component.getClassName())) { enabled = false; } setTileEnabled(component, enabled); }
hasSystemFeature(String string).通过该函数判断系统是否有特定的模块功能
PackageManager pm = context.getPackageManager(); if (!pm.hasSystemFeature(PackageManager.FEATURE_PRINTING)) { Log.d("gatsby", "Feature android.software.print not available"); }
frameworks\base\services\core\java\com\android\server\pm\PackageManagerService.java
@Override public boolean hasSystemFeature(String name, int version) { synchronized (mPackages) { final FeatureInfo feat = mAvailableFeatures.get(name); if (feat == null) { return false; } else { return feat.version >= version; } } }
mAvailableFeatures
public PackageManagerService(Context context, Installer installer, …………………… SystemConfig systemConfig = SystemConfig.getInstance(); mGlobalGids = systemConfig.getGlobalGids(); mSystemPermissions = systemConfig.getSystemPermissions(); mAvailableFeatures = systemConfig.getAvailableFeatures();
这个列表读取的是/sytem/etc/permissions下面的xml文件的feature节点
SystemConfig() { // Read configuration from system readPermissions(Environment.buildPath( Environment.getRootDirectory(), "etc", "sysconfig"), ALLOW_ALL); // Read configuration from the old permissions dir readPermissions(Environment.buildPath( Environment.getRootDirectory(), "etc", "permissions"), ALLOW_ALL); // Allow ODM to customize system configs around libs, features and apps int odmPermissionFlag = ALLOW_LIBS | ALLOW_FEATURES | ALLOW_APP_CONFIGS; readPermissions(Environment.buildPath( Environment.getOdmDirectory(), "etc", "sysconfig"), odmPermissionFlag); readPermissions(Environment.buildPath( Environment.getOdmDirectory(), "etc", "permissions"), odmPermissionFlag); // Only allow OEM to customize features readPermissions(Environment.buildPath( Environment.getOemDirectory(), "etc", "sysconfig"), ALLOW_FEATURES); readPermissions(Environment.buildPath( Environment.getOemDirectory(), "etc", "permissions"), ALLOW_FEATURES); }
二.frameworks\native\data\etc\tablet_core_hardware.xml 加入print feature
<!-- basic system services --> <feature name="android.software.app_widgets" /> <feature name="android.software.voice_recognizers" /> <feature name="android.software.backup" /> <feature name="android.software.home_screen" /> <feature name="android.software.input_methods" /> <feature name="android.software.print" />
三.惠普打印机
打印测试demo HPprintsdksample.apk https://github.com/mobileprint/android-print-sdk
1.1.rk3399 打印测试demo 异常 找补不到图片资源
09-22 15:11:29.738 I/ActivityManager( 514): Displayed com.android.printspooler/.ui.PrintActivity: +246ms 09-22 15:11:29.747 D/skia ( 2888): ---- fAsset->read(8192) returned 0 09-22 15:11:29.747 D/skia ( 2888): --- SkAndroidCodec::NewFromStream returned null 09-22 15:11:29.748 D/AndroidRuntime( 2888): Shutting down VM --------- beginning of crash 09-22 15:11:29.749 E/AndroidRuntime( 2888): FATAL EXCEPTION: main 09-22 15:11:29.749 E/AndroidRuntime( 2888): Process: com.android.printspooler, PID: 2888 09-22 15:11:29.749 E/AndroidRuntime( 2888): android.view.InflateException: Binary XML file line #113: Binary XML file line #273: Error inflating class android.widget.ImageView 09-22 15:11:29.749 E/AndroidRuntime( 2888): Caused by: android.view.InflateException: Binary XML file line #273: Error inflating class android.widget.ImageView 09-22 15:11:29.749 E/AndroidRuntime( 2888): Caused by: java.lang.reflect.InvocationTargetException 09-22 15:11:29.749 E/AndroidRuntime( 2888): at java.lang.reflect.Constructor.newInstance0(Native Method) 09-22 15:11:29.749 E/AndroidRuntime( 2888): at java.lang.reflect.Constructor.newInstance(Constructor.java:430) 09-22 15:11:29.749 E/AndroidRuntime( 2888): at android.view.LayoutInflater.createView(LayoutInflater.java:645) 09-22 15:11:29.749 E/AndroidRuntime( 2888): at com.android.internal.policy.PhoneLayoutInflater.onCreateView(PhoneLayoutInflater.java:58) 09-22 15:11:29.749 E/AndroidRuntime( 2888): at android.view.LayoutInflater.onCreateView(LayoutInflater.java:717) 09-22 15:11:29.749 E/AndroidRuntime( 2888): at android.view.LayoutInflater.createViewFromTag(LayoutInflater.java:785) 09-22 15:11:29.749 E/AndroidRuntime( 2888): at android.view.LayoutInflater.createViewFromTag(LayoutInflater.java:727) 09-22 15:11:29.749 E/AndroidRuntime( 2888): at android.view.LayoutInflater.rInflate(LayoutInflater.java:858) 09-22 15:11:29.749 E/AndroidRuntime( 2888): at android.view.LayoutInflater.rInflateChildren(LayoutInflater.java:821) 09-22 15:11:29.749 E/AndroidRuntime( 2888): at android.view.LayoutInflater.rInflate(LayoutInflater.java:861) 09-22 15:11:29.749 E/AndroidRuntime( 2888): at android.view.LayoutInflater.rInflateChildren(LayoutInflater.java:821) 09-22 15:11:29.749 E/AndroidRuntime( 2888): at android.view.LayoutInflater.parseInclude(LayoutInflater.java:994) 09-22 15:11:29.749 E/AndroidRuntime( 2888): at android.view.LayoutInflater.rInflate(LayoutInflater.java:854) 09-22 15:11:29.749 E/AndroidRuntime( 2888): at android.view.LayoutInflater.rInflateChildren(LayoutInflater.java:821) 09-22 15:11:29.749 E/AndroidRuntime( 2888): at android.view.LayoutInflater.inflate(LayoutInflater.java:518) 09-22 15:11:29.749 E/AndroidRuntime( 2888): at android.view.LayoutInflater.inflate(LayoutInflater.java:426) 09-22 15:11:29.749 E/AndroidRuntime( 2888): at android.view.LayoutInflater.inflate(LayoutInflater.java:377) 09-22 15:11:29.749 E/AndroidRuntime( 2888): at com.android.internal.policy.PhoneWindow.setContentView(PhoneWindow.java:415) 09-22 15:11:29.749 E/AndroidRuntime( 2888): at android.app.Activity.setContentView(Activity.java:2428) 09-22 15:11:29.749 E/AndroidRuntime( 2888): at com.android.printspooler.ui.PrintActivity.onPrinterRegistryReady(PrintActivity.java:303) 09-22 15:11:29.749 E/AndroidRuntime( 2888): at com.android.printspooler.ui.PrintActivity.-com_android_printspooler_ui_PrintActivity_lambda$2(PrintActivity.java:295) 09-22 15:11:29.749 E/AndroidRuntime( 2888): at com.android.printspooler.ui.PrintActivity$-void_-com_android_printspooler_ui_PrintActivity_lambda$1_android_os_IBinder_documentAdapter_LambdaImpl0.run(PrintActivity.java) 09-22 15:11:29.749 E/AndroidRuntime( 2888): at android.os.Handler.handleCallback(Handler.java:755) 09-22 15:11:29.749 E/AndroidRuntime( 2888): at android.os.Handler.dispatchMessage(Handler.java:95) 09-22 15:11:29.749 E/AndroidRuntime( 2888): at android.os.Looper.loop(Looper.java:154) 09-22 15:11:29.749 E/AndroidRuntime( 2888): at android.app.ActivityThread.main(ActivityThread.java:6157) 09-22 15:11:29.749 E/AndroidRuntime( 2888): at java.lang.reflect.Method.invoke(Native Method) 09-22 15:11:29.749 E/AndroidRuntime( 2888): at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:912) 09-22 15:11:29.749 E/AndroidRuntime( 2888): at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:802) 09-22 15:11:29.749 E/AndroidRuntime( 2888): Caused by: android.content.res.Resources$NotFoundException: Drawable com.android.printspooler:drawable/ic_expand_more with resource ID #0x7f020005 09-22 15:11:29.749 E/AndroidRuntime( 2888): Caused by: android.content.res.Resources$NotFoundException: File res/drawable/ic_expand_more.xml from drawable resource ID #0x7f020005 09-22 15:11:29.749 E/AndroidRuntime( 2888): at android.content.res.ResourcesImpl.loadDrawableForCookie(ResourcesImpl.java:725) 09-22 15:11:29.749 E/AndroidRuntime( 2888): at android.content.res.ResourcesImpl.loadDrawable(ResourcesImpl.java:571) 09-22 15:11:29.749 E/AndroidRuntime( 2888): at android.content.res.Resources.loadDrawable(Resources.java:858) 09-22 15:11:29.749 E/AndroidRuntime( 2888): at android.content.res.TypedArray.getDrawable(TypedArray.java:928) 09-22 15:11:29.749 E/AndroidRuntime( 2888): at android.view.View.<init>(View.java:4202) 09-22 15:11:29.749 E/AndroidRuntime( 2888): at android.widget.ImageView.<init>(ImageView.java:155) 09-22 15:11:29.749 E/AndroidRuntime( 2888): at android.widget.ImageView.<init>(ImageView.java:150) 09-22 15:11:29.749 E/AndroidRuntime( 2888): at android.widget.ImageView.<init>(ImageView.java:146) 09-22 15:11:29.749 E/AndroidRuntime( 2888): at java.lang.reflect.Constructor.newInstance0(Native Method) 09-22 15:11:29.749 E/AndroidRuntime( 2888): at java.lang.reflect.Constructor.newInstance(Constructor.java:430) 09-22 15:11:29.749 E/AndroidRuntime( 2888): at android.view.LayoutInflater.createView(LayoutInflater.java:645) 09-22 15:11:29.749 E/AndroidRuntime( 2888): at com.android.internal.policy.PhoneLayoutInflater.onCreateView(PhoneLayoutInflater.java:58) 09-22 15:11:29.749 E/AndroidRuntime( 2888): at android.view.LayoutInflater.onCreateView(LayoutInflater.java:717) 09-22 15:11:29.749 E/AndroidRuntime( 2888): at android.view.LayoutInflater.createViewFromTag(LayoutInflater.java:785) 09-22 15:11:29.749 E/AndroidRuntime( 2888): at android.view.LayoutInflater.createViewFromTag(LayoutInflater.java:727) 09-22 15:11:29.749 E/AndroidRuntime( 2888): at android.view.LayoutInflater.rInflate(LayoutInflater.java:858) 09-22 15:11:29.749 E/AndroidRuntime( 2888): at android.view.LayoutInflater.rInflateChildren(LayoutInflater.java:821) 09-22 15:11:29.749 E/AndroidRuntime( 2888): at android.view.LayoutInflater.rInflate(LayoutInflater.java:861) 09-22 15:11:29.749 E/AndroidRuntime( 2888): at android.view.LayoutInflater.rInflateChildren(LayoutInflater.java:821) 09-22 15:11:29.749 E/AndroidRuntime( 2888): at android.view.LayoutInflater.parseInclude(LayoutInflater.java:994) 09-22 15:11:29.749 E/AndroidRuntime( 2888): at android.view.LayoutInflater.rInflate(LayoutInflater.java:854) 09-22 15:11:29.749 E/AndroidRuntime( 2888): at android.view.LayoutInflater.rInflateChildren(LayoutInflater.java:821) 09-22 15:11:29.749 E/AndroidRuntime( 2888): at android.view.LayoutInflater.inflate(LayoutInflater.java:518) 09-22 15:11:29.749 E/AndroidRuntime( 2888): at android.view.LayoutInflater.inflate(LayoutInflater.java:426) 09-22 15:11:29.749 E/AndroidRuntime( 2888): at android.view.LayoutInflater.inflate(LayoutInflater.java:377) 09-22 15:11:29.749 E/AndroidRuntime( 2888): at com.android.internal.policy.PhoneWindow.setContentView(PhoneWindow.java:415) 09-22 15:11:29.749 E/AndroidRuntime( 2888): at android.app.Activity.setContentView(Activity.java:2428) 09-22 15:11:29.749 E/AndroidRuntime( 2888): at com.android.printspooler.ui.PrintActivity.onPrinterRegistryReady(PrintActivity.java:303) 09-22 15:11:29.749 E/AndroidRuntime( 2888): at com.android.printspooler.ui.PrintActivity.-com_android_printspooler_ui_PrintActivity_lambda$2(PrintActivity.java:295) 09-22 15:11:29.749 E/AndroidRuntime( 2888): at com.android.printspooler.ui.PrintActivity$-void_-com_android_printspooler_ui_PrintActivity_lambda$1_android_os_IBinder_documentAdapter_LambdaImpl0.run(PrintActivity.java) 09-22 15:11:29.749 E/AndroidRuntime( 2888): at android.os.Handler.handleCallback(Handler.java:755) 09-22 15:11:29.749 E/AndroidRuntime( 2888): at android.os.Handler.dispatchMessage(Handler.java:95) 09-22 15:11:29.749 E/AndroidRuntime( 2888): at android.os.Looper.loop(Looper.java:154) 09-22 15:11:29.749 E/AndroidRuntime( 2888): at android.app.ActivityThread.main(ActivityThread.java:6157) 09-22 15:11:29.749 E/AndroidRuntime( 2888): at java.lang.reflect.Method.invoke(Native Method) 09-22 15:11:29.749 E/AndroidRuntime( 2888): at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:912) 09-22 15:11:29.749 E/AndroidRuntime( 2888): at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:802) 09-22 15:11:29.749 E/AndroidRuntime( 2888): Caused by: org.xmlpull.v1.XmlPullParserException: Binary XML file line #22: <bitmap> requires a valid 'src' attribute 09-22 15:11:29.749 E/AndroidRuntime( 2888): at android.graphics.drawable.BitmapDrawable.updateStateFromTypedArray(BitmapDrawable.java:787) 09-22 15:11:29.749 E/AndroidRuntime( 2888): at android.graphics.drawable.BitmapDrawable.inflate(BitmapDrawable.java:747) 09-22 15:11:29.749 E/AndroidRuntime( 2888): at android.graphics.drawable.DrawableInflater.inflateFromXml(DrawableInflater.java:130) 09-22 15:11:29.749 E/AndroidRuntime( 2888): at android.graphics.drawable.Drawable.createFromXmlInner(Drawable.java:1227) 09-22 15:11:29.749 E/AndroidRuntime( 2888): at android.graphics.drawable.StateListDrawable.inflateChildElements(StateListDrawable.java:188) 09-22 15:11:29.749 E/AndroidRuntime( 2888): at android.graphics.drawable.StateListDrawable.inflate(StateListDrawable.java:116) 09-22 15:11:29.749 E/AndroidRuntime( 2888): at android.graphics.drawable.DrawableInflater.inflateFromXml(DrawableInflater.java:130) 09-22 15:11:29.749 E/AndroidRuntime( 2888): at android.graphics.drawable.Drawable.createFromXmlInner(Drawable.java:1227) 09-22 15:11:29.749 E/AndroidRuntime( 2888): at android.graphics.drawable.Drawable.createFromXml(Drawable.java:1200) 09-22 15:11:29.749 E/AndroidRuntime( 2888): at android.content.res.ResourcesImpl.loadDrawableForCookie(ResourcesImpl.java:715) 09-22 15:11:29.749 E/AndroidRuntime( 2888): ... 36 more 09-22 15:11:29.757 W/ActivityManager( 514): Force finishing activity com.android.printspooler/.ui.PrintActivity 09-22 15:11:29.760 W/ActivityManager( 514): Force finishing activity com.hp.mss.printsdksample/.activity.MainActivity 09-22 15:11:29.775 I/Process ( 2888): Sending signal. PID: 2888 SIG: 9 09-22 15:11:29.794 D/OpenGLRenderer( 2023): endAllActiveAnimators on 0x7f4ef8a800 (RippleDrawable) with handle 0x7f58536960 09-22 15:11:29.813 W/InputDispatcher( 514): channel '9f5c3d6 com.android.printspooler/com.android.printspooler.ui.PrintActivity (server)' ~ Consumer closed input channel or an error occurred. events=0x9 09-22 15:11:29.813 E/InputDispatcher( 514): channel '9f5c3d6 com.android.printspooler/com.android.printspooler.ui.PrintActivity (server)' ~ Channel is unrecoverably broken and will be disposed! 09-22 15:11:29.825 D/GraphicsStats( 514): Buffer count: 10 09-22 15:11:29.825 I/WindowManager( 514): WIN DEATH: Window{9f5c3d6 u0 com.android.printspooler/com.android.printspooler.ui.PrintActivity} 09-22 15:11:29.825 W/InputDispatcher( 514): Attempted to unregister already unregistered input channel '9f5c3d6 com.android.printspooler/com.android.printspooler.ui.PrintActivity (server)' 09-22 15:11:29.826 I/ActivityManager( 514): Process com.android.printspooler (pid 2888) has died 09-22 15:11:29.826 D/ActivityManager( 514): cleanUpApplicationRecord -- 2888 09-22 15:11:29.827 W/ActivityManager( 514): Scheduling restart of crashed service com.android.printspooler/.model.PrintSpoolerService in 1000ms 09-22 15:11:29.827 D/RemotePrintSpooler( 514): Error clearing print spooler client 09-22 15:11:29.827 D/RemotePrintSpooler( 514): android.os.DeadObjectException 09-22 15:11:29.827 D/RemotePrintSpooler( 514): at android.os.BinderProxy.transactNative(Native Method) 09-22 15:11:29.827 D/RemotePrintSpooler( 514): at android.os.BinderProxy.transact(Binder.java:617) 09-22 15:11:29.827 D/RemotePrintSpooler( 514): at android.print.IPrintSpooler$Stub$Proxy.setClient(IPrintSpooler.java:647) 09-22 15:11:29.827 D/RemotePrintSpooler( 514): at com.android.server.print.RemotePrintSpooler.clearClientLocked(RemotePrintSpooler.java:679) 09-22 15:11:29.827 D/RemotePrintSpooler( 514): at com.android.server.print.RemotePrintSpooler.-wrap0(RemotePrintSpooler.java) 09-22 15:11:29.827 D/RemotePrintSpooler( 514): at com.android.server.print.RemotePrintSpooler$MyServiceConnection.onServiceDisconnected(RemotePrintSpooler.java:711) 09-22 15:11:29.827 D/RemotePrintSpooler( 514): at android.app.LoadedApk$ServiceDispatcher.doDeath(LoadedApk.java:1469) 09-22 15:11:29.827 D/RemotePrintSpooler( 514): at android.app.LoadedApk$ServiceDispatcher$RunConnection.run(LoadedApk.java:1483) 09-22 15:11:29.827 D/RemotePrintSpooler( 514): at android.os.Handler.handleCallback(Handler.java:755) 09-22 15:11:29.827 D/RemotePrintSpooler( 514): at android.os.Handler.dispatchMessage(Handler.java:95) 09-22 15:11:29.827 D/RemotePrintSpooler( 514): at android.os.Looper.loop(Looper.java:154) 09-22 15:11:29.827 D/RemotePrintSpooler( 514): at com.android.server.SystemServer.run(SystemServer.java:359) 09-22 15:11:29.827 D/RemotePrintSpooler( 514): at com.android.server.SystemServer.main(SystemServer.java:226) 09-22 15:11:29.827 D/RemotePrintSpooler( 514): at java.lang.reflect.Method.invoke(Native Method) 09-22 15:11:29.827 D/RemotePrintSpooler( 514): at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:912) 09-22 15:11:29.827 D/RemotePrintSpooler( 514): at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:802) 09-22 15:11:29.830 W/System.err( 1690): java.lang.IllegalStateException: Observer com.hp.android.printservice.service.o$h$a@197f3db was not registered. 09-22 15:11:29.830 W/System.err( 1690): at android.database.Observable.unregisterObserver(Observable.java:69) 09-22 15:11:29.831 W/System.err( 1690): at android.widget.BaseAdapter.unregisterDataSetObserver(BaseAdapter.java:42) 09-22 15:11:29.831 W/System.err( 1690): at com.hp.android.printservice.service.o$h.onStopPrinterDiscovery(PrintServiceHelperBase.java:4) 09-22 15:11:29.831 W/System.err( 1690): at android.printservice.PrinterDiscoverySession.stopPrinterDiscovery(PrinterDiscoverySession.java:511) 09-22 15:11:29.831 W/System.err( 1690): at android.printservice.PrintService$ServiceHandler.handleMessage(PrintService.java:498) 09-22 15:11:29.831 W/System.err( 1690): at android.os.Handler.dispatchMessage(Handler.java:102) 09-22 15:11:29.831 W/System.err( 1690): at android.os.Looper.loop(Looper.java:154) 09-22 15:11:29.831 W/System.err( 1690): at android.app.ActivityThread.main(ActivityThread.java:6157) 09-22 15:11:29.831 W/System.err( 1690): at java.lang.reflect.Method.invoke(Native Method) 09-22 15:11:29.831 W/System.err( 1690): at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:912) 09-22 15:11:29.831 W/System.err( 1690): at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:802) 09-22 15:11:29.832 I/art ( 1154): Ignoring second debugger -- accepting and dropping 09-22 15:11:29.848 I/art ( 514): Ignoring second debugger -- accepting and dropping 09-22 15:11:29.856 I/art ( 708): Ignoring second debugger -- accepting and dropping
1.2. PrintSpooler
系统打印是通过一个系统apk实现的,叫做com.android.printspooler,位置在/system/app/PrintSpooler/中
这个apk的另外一个作用是接收来自用户APP的打印请求。用户APP的打印请求先被PrintManger通过PrintJob方式封装,
然后通过Intent唤起PrintSpooler的PrintActivity进行预览。如果打印机设备厂商实现了Print Plugin并提供apk安装到系统,
那么PrintSpooler就可以找到对应打印机驱动进行打印。
Android系统提供的这个打印框架尽管简单,但是接口功能局限,不能实现很多自定义的需求。
1.3. Caused by: android.content.res.Resources$NotFoundException: File res/drawable/ic_expand_more.xml from drawable resource ID #0x7f020005
1.4.解决法案
device\rockchip\common\device.mk
PRODUCT_AAPT_CONFIG ?= normal large xlarge hdpi xhdpi xxhdpi PRODUCT_AAPT_PREF_CONFIG ?= xhdpi PRODUCT_LOCALES := en_US zh_TW zh_CN
device\rockchip\rk3399\rk3399_all.mk
#PRODUCT_AAPT_CONFIG := normal large mdpi tvdpi hdpi xhdpi #PRODUCT_AAPT_PREF_CONFIG := hdpi