首页 文章 精选 留言 我的

精选列表

搜索[远程],共10000篇文章
优秀的个人博客,低调大师

Android Service学习之AIDL, Parcelable和远程服务

AIDL的作用 由于每个应用程序都运行在自己的进程空间,并且可以从应用程序UI运行另一个服务进程,而且经常会在不同的进程间传递对象。在Android平台,一个进程通常不能访问另一个进程的内存空间,所以要想对话,需要将对象分解成操作系统可以理解的基本单元,并且有序的通过进程边界。 通过代码来实现这个数据传输过程是冗长乏味的,Android提供了AIDL工具来处理这项工作。 AIDL (Android Interface Definition Language) 是一种IDL 语言,用于生成可以在Android设备上两个进程之间进行进程间通信(interprocess communication, IPC)的代码。如果在一个进程中(例如Activity)要调用另一个进程中(例如Service)对象的操作,就可以使用AIDL生成可序列化的参数。 AIDL IPC机制是面向接口的,像COM或Corba一样,但是更加轻量级。它是使用代理类在客户端和实现端传递数据。 选择AIDL的使用场合 官方文档特别提醒我们何时使用AIDL是必要的: 只有你允许客户端从不同的应用程序为了进程间的通信而去访问你的service,以及想在你的service处理多线程。 如果不需要进行不同应用程序间的并发通信(IPC),you should create your interface by implementing a Binder;或者你想进行IPC,但不需要处理多线程的,则implement your interface using a Messenger。无论如何,在使用AIDL前,必须要理解如何绑定service——bindService。 在设计AIDL接口前,要提醒的是,调用AIDL接口是直接的方法调用的,不是我们所想象的调用是发生在线程里。而调用(call)来自local进程或者remote进程,有什么区别呢?尤其是以下情况(引用原文,不作翻译了,以免翻译有误): Calls made from the local process are executed in the same thread that is making the call. If this is your main UI thread, that thread continues to execute in the AIDL interface. If it is another thread, that is the one that executes your code in the service. Thus, if only local threads are accessing the service, you can completely control which threads are executing in it (but if that is the case, then you shouldn't be using AIDL at all, but should instead create the interface byimplementing a Binder). Calls from a remote process are dispatched from a thread pool the platform maintains inside of your own process. You must be prepared for incoming calls from unknown threads, with multiple calls happening at the same time. In other words, an implementation of an AIDL interface must be completely thread-safe. Theonewaykeyword modifies the behavior of remote calls. When used, a remote call does not block; it simply sends the transaction data and immediately returns. The implementation of the interface eventually receives this as a regular call from theBinderthread pool as a normal remote call. Ifonewayis used with a local call, there is no impact and the call is still synchronous. 定义AIDL接口 AIDL接口文件,和普通的接口内容没有什么特别,只是它的扩展名为.aidl。保存在src目录下。 如果其他应用程序需要IPC,则那些应用程序的src也要带有这个文件。Android SDK tools就会在gen目录自动生成一个IBinder接口文件。service必须适当地实现这个IBinder接口。那么客户端程序就能绑定这个service并在IPC时从IBinder调用方法。 每个aidl文件只能定义一个接口,而且只能是接口的声明和方法的声明。 1.创建.aidl文件 AIDL使用简单的语法来声明接口,描述其方法以及方法的参数和返回值。这些参数和返回值可以是任何类型,甚至是其他AIDL生成的接口。 其中对于Java编程语言的基本数据类型 (int, long, char, boolean等),String和CharSequence,集合接口类型List和Map,不需要import 语句。 而如果需要在AIDL中使用其他AIDL接口类型,需要import,即使是在相同包结构下。AIDL允许传递实现Parcelable接口的类,需要import. 需要特别注意的是, 对于非基本数据类型,也不是String和CharSequence类型的,需要有方向指示,包括in、out和inout,in表示由客户端设置,out表示由服务端设置,inout是两者均可设置。 AIDL只支持接口方法,不能公开static变量。 例如 (IMyService.aidl): packagecom.demo; importcom.demo.Person; interfaceIMyService { voidsavePersonInfo(in Person person); List<Person> getAllPerson(); } 2.实现接口 创建一个类实现刚才那个aidl的接口: public classRemoteService extendsService { privateLinkedList<Person> personList = newLinkedList<Person>(); @Override publicIBinder onBind(Intent intent) { returnmBinder; } privatefinalIMyService.Stub mBinder =newIMyService.Stub(){ @Override public voidsavePersonInfo(Person person) throwsRemoteException { if(person != null){ personList.add(person); } } @Override publicList<Person> getAllPerson() throwsRemoteException { returnpersonList; } }; } 这里会看到有一个名为IMyService.Stub类,查看aidl文件生成的Java文件源代码就能发现有这么一段代码: /** Local-side IPC implementation stub class. */ public static abstract classStub extendsandroid.os.Binder implementscom.demo.IMyService 原来Stub类就是继承于Binder类,也就是说RemoteService类和普通的Service类没什么不同,只是所返回的IBinder对象比较特别,是一个实现了AIDL接口的Binder。 接下来就是关于所传递的数据Bean——Person类,是一个序列化的类,这里使用Parcelable 接口来序列化,是Android提供的一个比Serializable 效率更高的序列化类。 Parcelable需要实现三个函数: 1) void writeToParcel(Parcel dest, int flags)将需要序列化存储的数据写入外部提供的Parcel对象dest。而看了网上的代码例子,个人猜测,读取Parcel数据的次序要和这里的write次序一致,否则可能会读错数据。具体情况我没试验过! 2) describeContents()没搞懂有什么用,反正直接返回0也可以 3) static final Parcelable.Creator对象CREATOR这个CREATOR命名是固定的,而它对应的接口有两个方法: createFromParcel(Parcel source) 实现从source创建出JavaBean实例的功能 newArray(int size) 创建一个类型为T,长度为size的数组,仅一句话(return new T[size])即可。估计本方法是供外部类反序列化本类数组使用。 仔细观察Person类的代码和上面所说的内容: public classPerson implementsParcelable { privateString name; privateString telNumber; private intage; publicPerson() {} publicPerson(Parcel pl){ name = pl.readString(); telNumber = pl.readString(); age = pl.readInt(); } publicString getName() { returnname; } public voidsetName(String name) { this.name = name; } publicString getTelNumber() { returntelNumber; } public voidsetTelNumber(String telNumber) { this.telNumber = telNumber; } public intgetAge() { returnage; } public voidsetAge( intage) { this.age = age; } @Override publicintdescribeContents() { return0; } @Override publicvoidwriteToParcel(Parcel dest,intflags) { dest.writeString(name); dest.writeString(telNumber); dest.writeInt(age); } publicstaticfinalParcelable.Creator<Person> CREATOR =newParcelable.Creator<Person>(){ @Override publicPerson createFromParcel(Parcel source) { returnnewPerson(source);} @Override publicPerson[] newArray( intsize) { returnnewPerson[size];} }; } 然后创建Person.aidl文件,注意这里的parcelable和原来实现的Parcelable 接口,开头的字母p一个小写一个大写: packagecom.demo; parcelable Person; 对于实现AIDL接口,官方还提醒我们: 1. 调用者是不能保证在主线程执行的,所以从一调用的开始就需要考虑多线程处理,以及确保线程安全; 2. IPC调用是同步的。如果你知道一个IPC服务需要超过几毫秒的时间才能完成地话,你应该避免在Activity的主线程中调用。也就是IPC调用会挂起应用程序导致界面失去响应,这种情况应该考虑单独开启一个线程来处理。 3. 抛出的异常是不能返回给调用者(跨进程抛异常处理是不可取的)。 3. 客户端获取接口 客户端如何获取AIDL接口呢?通过IMyService.Stub.asInterface(service)来得到IMyService对象: privateIMyService mRemoteService; privateServiceConnection mRemoteConnection = newServiceConnection() { public voidonServiceConnected(ComponentName className, IBinder service) { mRemoteService = IMyService.Stub.asInterface(service); } public voidonServiceDisconnected(ComponentName className) { mRemoteService = null; } }; 在生成的IMyService.java里面会找到这样的代码: /** * Cast an IBinder object into an com.demo.IMyService interface, * generating a proxy if needed. */ public staticcom.demo.IMyService asInterface(android.os.IBinder obj) {...} 而service的绑定没有什么不同: if(mIsRemoteBound) { unbindService(mRemoteConnection); } else{ bindService( newIntent( "com.demo.IMyService"), mRemoteConnection, Context.BIND_AUTO_CREATE); } mIsRemoteBound = !mIsRemoteBound; 通过IPC调用/传递数据 客户端绑定service后就能通过IPC来调用/传递数据了,直接调用service对象的接口方法: addPersonButton.setOnClickListener( newView.OnClickListener(){ private intindex = 0; @Override public voidonClick(View view) { Person person = newPerson(); index = index + 1; person.setName( "Person"+ index); person.setAge(20); person.setTelNumber( "123456"); try{ mRemoteService.savePersonInfo(person); }catch(RemoteException e) { e.printStackTrace(); }} }); listPersonButton.setOnClickListener( newView.OnClickListener(){ @Override public voidonClick(View view) { List<Person> list = null; try{ list = mRemoteService.getAllPerson(); }catch(RemoteException e) { e.printStackTrace(); } if(list != null){ StringBuilder text = newStringBuilder(); for(Person person : list){ text.append( "\nPerson name:"); text.append(person.getName()); text.append( "\n age :"); text.append(person.getAge()); text.append( "\n tel number:"); text.append(person.getTelNumber()); } inputPersonEdit.setText(text); } else{ Toast.makeText(ServiceActivity. this, "get data error", Toast.LENGTH_SHORT).show(); } } }); Permission权限 如果Service在AndroidManifest.xml中声明了全局的强制的访问权限,其他引用必须声明权限才能来start,stop或bind这个service. 另外,service可以通过权限来保护她的IPC方法调用,通过调用checkCallingPermission(String)方法来确保可以执行这个操作。 AndroidManifest.xml的Service元素 < service android:name =".RemoteService" android:process=":remote" > < intent-filter > < action android:name ="com.demo.IMyService" /> </ intent-filter > </ service > 这里的android:process=":remote",一开始我没有添加的,在同一个程序里使用IPC,即同一个程序作为客户端/服务器端,结果运行mRemoteService = IMyService.Stub.asInterface(service);时提示空指针异常。观察了人家的在不同程序里进行IPC的代码,也是没有这个android:process=":remote"的。后来在官方文档 http://androidappdocs.appspot.com/guide/topics/manifest/service-element.html里了解到(留意第二段文字): android:processThe name of the process where the service is to run. Normally, all components of an application run in the default process created for the application. It has the same name as the application package. The <application> element's process attribute can set a different default for all components. But component can override the default with its own process attribute, allowing you to spread your application across multiple processes. If the name assigned to this attribute begins with a colon (':'), a new process, private to the application, is created when it's needed and the service runs in that process. If the process name begins with a lowercase character, the service will run in a global process of that name, provided that it has permission to do so. This allows components in different applications to share a process, reducing resource usage. 也就是说android:process=":remote",代表在应用程序里,当需要该service时,会自动创建新的进程。而如果是android:process="remote",没有“:”分号的,则创建全局进程,不同的应用程序共享该进程。 以上内容结合了不少网络文章,包括来自 http://blog.csdn.net/caowenbin的译文, http://terryblog.blog.51cto.com/1764499/382457, http://4225953-163-com.iteye.com/blog/792997以及Android的官方网站文档。 本文转自 Icansoft 51CTO博客,原文链接:http://blog.51cto.com/android/537684

优秀的个人博客,低调大师

搭建手机APP远程监控物联网云平台

目前常见的水质在线监测仪器生产商有:美国哈希HACH 德国E+H 以色列Blue I 德国科泽kuntze 加拿大AVVOR、德国阿尔道斯ALLDOS、上海博取、河北科瑞达等。采集的水质参数包括温度、PH、电导率、浊度、余氯等。 数据统计:可在线实时24小时连续的采集和记录监测点位的各种水质状况,以数字、图形和图像等多种方式进行实时显示和记录存储监测信息,监测点位可多达上百个点。 故障报警:当出现被监控点位数据异常时可自动发出报警信号,报警方式包括:现场多媒体声光报警、网络客户端报警、手机短信息报警等。 Web监控:管理人员打开电脑,登陆平台即可看到所属的设备运行状况,整个过程无需安装软件。一切就像网上冲浪那样方便。 APP监控:将设备放到口袋里,无论身处何地,打开手机即可查看和控制水质监测设备。 设备发布:环保局或者小区物业门可以通过EMCP平台将水质监测设备进行发布,生成二维码张贴在公共区域、官方网站或者宣传海报上,民众可通过手机扫描得知水质实时情况。 冗余设计:系统设计时预留有接口,可随时增加硬件设备,系统只要做少量的改动即可,可以在很短的时间内完成。

优秀的个人博客,低调大师

从 "No module named pyspark" 到远程提交 spark 任务

版权声明:本文为半吊子子全栈工匠(wireless_com,同公众号)原创文章,未经允许不得转载。 https://blog.csdn.net/wireless_com/article/details/51170246 能在本地Mac环境用python提交spark 任务会方便很多,但是在安装了 spark-1.6-bin-without-hadoop (spark.apache.org/download) 之后,在python 中 “import pyspark”会报“no module named pyspark” 错误。 没错,这种错误都是 路径问题。 为了本地使用spark,需要在~/.bash_profile 中增加两个环境变量:SPARK_HOME 以及必知的PYTHONPATH export SPARK_HOME=/Users/abc/Documents/spark-1.6.0-bin-without-hadoop #这是spark 的安装路径 export PYTHONPATH=$SPARK_HOME/python:$SPARK_HOME/python/lib/py4j-0.8.2.1-src.zip:$PYTHONPATH 注:Py4J 有点像 Python 版的 JNI,通过它,Python 程序可以利用 Python 解释器直接调用Java虚拟机中的 Java 对象,也可以让 Java 调用 Python 对象。 然后,别忘了,source~/.bash_profile 让它生效。 运行 python shell, from pyspark import SparkContext 都可以了么, 但是 当你单独执行pyspark 或者 在python 中初始化SparkConf 等其它类的时候,又报错了 "Exception in thread "main" java.lang.NoClassDefFoundError: org/apache/hadoop/fs/FSDataInputStream" spark 访问FS 时库文件丢失,看来spark 和hadoop 的结合还需要指明更多的纽带,简单的换一下 spark distribution吧。将 spark-1.6.0-bin-without-hadoop 换成 spark-1.6.0-bin-hadoop2.6,然后更新 .bash_profile 中SPARK_HOME 的路径。 直接运行pyspark: $ pyspark Python 2.7.11 (default, Mar 1 2016, 18:40:10) [GCC 4.2.1 Compatible Apple LLVM 7.0.2 (clang-700.1.81)] on darwin Type "help", "copyright", "credits" or "license" for more information. 16/04/16 21:41:02 INFO spark.SparkContext: Running Spark version 1.6.0 16/04/16 21:41:05 WARN util.NativeCodeLoader: Unable to load native-hadoop library for your platform... using builtin-java classes where applicable 16/04/16 21:41:05 INFO spark.SecurityManager: Changing view acls to: abel,hdfs 16/04/16 21:41:05 INFO spark.SecurityManager: Changing modify acls to: abel,hdfs 16/04/16 21:41:05 INFO spark.SecurityManager: SecurityManager: authentication disabled; ui acls disabled; users with view permissions: Set(abel, hdfs); users with modify permissions: Set(abel, hdfs) 16/04/16 21:41:06 INFO util.Utils: Successfully started service 'sparkDriver' on port 55162. 16/04/16 21:41:06 INFO slf4j.Slf4jLogger: Slf4jLogger started 16/04/16 21:41:06 INFO Remoting: Starting remoting 16/04/16 21:41:07 INFO Remoting: Remoting started; listening on addresses :[akka.tcp://sparkDriverActorSystem@192.168.1.106:55165] 16/04/16 21:41:07 INFO util.Utils: Successfully started service 'sparkDriverActorSystem' on port 55165. 16/04/16 21:41:07 INFO spark.SparkEnv: Registering MapOutputTracker 16/04/16 21:41:07 INFO spark.SparkEnv: Registering BlockManagerMaster 16/04/16 21:41:07 INFO storage.DiskBlockManager: Created local directory at /private/var/folders/wk/fxn2zdyd7rz8rm66rst4h15w0000gn/T/blockmgr-6de54d08-31c9-430e-ac3c-9f3e0635e486 16/04/16 21:41:07 INFO storage.MemoryStore: MemoryStore started with capacity 511.5 MB 16/04/16 21:41:07 INFO spark.SparkEnv: Registering OutputCommitCoordinator 16/04/16 21:41:07 INFO server.Server: jetty-8.y.z-SNAPSHOT 16/04/16 21:41:07 INFO server.AbstractConnector: Started SelectChannelConnector@0.0.0.0:4040 16/04/16 21:41:07 INFO util.Utils: Successfully started service 'SparkUI' on port 4040. 16/04/16 21:41:07 INFO ui.SparkUI: Started SparkUI at http://192.168.1.106:4040 16/04/16 21:41:07 INFO executor.Executor: Starting executor ID driver on host localhost 16/04/16 21:41:07 INFO util.Utils: Successfully started service 'org.apache.spark.network.netty.NettyBlockTransferService' on port 55167. 16/04/16 21:41:07 INFO netty.NettyBlockTransferService: Server created on 55167 16/04/16 21:41:07 INFO storage.BlockManagerMaster: Trying to register BlockManager 16/04/16 21:41:07 INFO storage.BlockManagerMasterEndpoint: Registering block manager localhost:55167 with 511.5 MB RAM, BlockManagerId(driver, localhost, 55167) 16/04/16 21:41:07 INFO storage.BlockManagerMaster: Registered BlockManager Welcome to ____ __ / __/__ ___ _____/ /__ _\ \/ _ \/ _ `/ __/ '_/ /__ / .__/\_,_/_/ /_/\_\ version 1.6.0 /_/ Using Python version 2.7.11 (default, Mar 1 2016 18:40:10) SparkContext available as sc, HiveContext available as sqlContext.>>> OK, 至此,pyspark 算是在本机的MAC 环境中可以基本上正常工作了。

资源下载

更多资源
Mario

Mario

马里奥是站在游戏界顶峰的超人气多面角色。马里奥靠吃蘑菇成长,特征是大鼻子、头戴帽子、身穿背带裤,还留着胡子。与他的双胞胎兄弟路易基一起,长年担任任天堂的招牌角色。

Nacos

Nacos

Nacos /nɑ:kəʊs/ 是 Dynamic Naming and Configuration Service 的首字母简称,一个易于构建 AI Agent 应用的动态服务发现、配置管理和AI智能体管理平台。Nacos 致力于帮助您发现、配置和管理微服务及AI智能体应用。Nacos 提供了一组简单易用的特性集,帮助您快速实现动态服务发现、服务配置、服务元数据、流量管理。Nacos 帮助您更敏捷和容易地构建、交付和管理微服务平台。

Spring

Spring

Spring框架(Spring Framework)是由Rod Johnson于2002年提出的开源Java企业级应用框架,旨在通过使用JavaBean替代传统EJB实现方式降低企业级编程开发的复杂性。该框架基于简单性、可测试性和松耦合性设计理念,提供核心容器、应用上下文、数据访问集成等模块,支持整合Hibernate、Struts等第三方框架,其适用范围不仅限于服务器端开发,绝大多数Java应用均可从中受益。

Sublime Text

Sublime Text

Sublime Text具有漂亮的用户界面和强大的功能,例如代码缩略图,Python的插件,代码段等。还可自定义键绑定,菜单和工具栏。Sublime Text 的主要功能包括:拼写检查,书签,完整的 Python API , Goto 功能,即时项目切换,多选择,多窗口等等。Sublime Text 是一个跨平台的编辑器,同时支持Windows、Linux、Mac OS X等操作系统。