首页 文章 精选 留言 我的

精选列表

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

Android开发学习笔记:数据存取之Preference浅析

一.Preference的简介 Preference(配置)提供了一种轻量级的数据存取方法,主要应用于数据比较少的配置信息。它以“key-value”(是一个Map)对的方式将数据保存在一个XML配置文件中,例如,手机的开机问候语,可以将其以Preference方式来进行配置。也可以保存一些用户个性化设置的字体、颜色、位置等参数信息。 二.Preference存取数据的方法 使用到的接口: SharedPreferences接口和SharedPreferences.Editor接口,它们都是来自于andorid.content包。 ①SharedPreferences接口提供保存数据的方法 我们可以调用Context.getSharedPreferences(String name,int mode)方法得到SharedPreferences接口。该方法的第一个参数是文件名称,第二个参数是操作模式。操作模式有三种: MODE_PRIVATE(私有) MODE_WORLD_READABLE(可读) MODE_WORLD_WRITEABLE(可写) SharedPreferences接口的常用方法 方法名称 方法描述 edit() 返回SharedPreferences的内部接口SharedPreferences.Editor contains(String key) 判断是否包含该键值 getAll() 返回所有配置信息Map getBoolean(String key,Boolean defValue) 获得一个boolean值 getFloat(String key,float defValue) 获得一个float值 getInt(String key,int defValue) 获得一个int值 getLong(String key,long defValue) 获得一个long值 getString(String key,String defValue) 获得一个String值 ②SharedPreferences.Editor接口提供获得数据的方法 SharedPreferences.Editor接口中的getString(String key,String defValue)、getInt(String key,int defValue)等。调用SharedPreferences的edit()方法返回SharedPreferences.Editor内部接口,该接口中提供了保存数据的方法,如putString(String key,String value)、pubInt(String key,int value)等,调用该接口的commit方法可以将数据进行保存。 SharedPreferences.Editor接口常用的方法 方法名称 方法描述 clear() 清楚所有值 commit() 保存 getAll() 返回所有配置信息Map putBoolean(String key,Boolean value) 保存一个boolean值 putFloat(String key,float value) 保存一个float值 putInt(String key,int value) 保存一个int值 putLong(String key,long value) 保存一个long值 putString(String key,String value) 保存一个String值 remove(String key) 删除该键对应的键 下面是保存临时记事本内容的例子 当我们在手机上用记事本编写备忘录,日志的时候,突然要返回接电话,看短信的时候。我们就要停止编写,退出去听接电话,看短信。然而,当我们打完电话或者看完短信回来的时候,发现刚刚编写的内容还在记事本上,这就是Preference的作用了。 创建一个Activity,在其中放置一个EditText保存短信内容,放置一个Button用于发送信息。在onCreate()中通过getSharedPreferences()方法获得SharedPreferences接口,调用接口的getString()方法,获得保存内容,将内容设置到EditText中。 在onStop()方法中保存内容,使用getSharedPreferences().edit()方法获得SharedPreferences.Editor接口,调用SharedPreferences.Editor的putString()方法保存短信内容,调用commit()方法提交内容。 MainActivity.java packagecom.android.preference; importandroid.app.Activity; importandroid.content.SharedPreferences; importandroid.os.Bundle; importandroid.widget.Button; importandroid.widget.EditText; publicclassMainActivityextendsActivity{ privateEditTextmyEditText; privateButtonbtn; privatestaticfinalStringTEMP_INFO="temp_info"; @Override publicvoidonCreate(BundlesavedInstanceState){ super.onCreate(savedInstanceState); setContentView(R.layout.main); myEditText=(EditText)findViewById(R.id.EditText1); btn=(Button)findViewById(R.id.Button1); //获得SharedPreferences实例 SharedPreferencessp=getSharedPreferences(TEMP_INFO,MODE_WORLD_READABLE); //从SharedPreferences获得备忘录的内容 Stringcontent=sp.getString("info_content",""); //在EditText中显示备忘录内容 myEditText.setText(content); } @Override protectedvoidonStop(){ super.onStop(); //获得编辑器 SharedPreferences.Editoreditor=getSharedPreferences(TEMP_INFO,MODE_WORLD_WRITEABLE).edit(); //将EditText中的文本内容添加到编辑器 editor.putString("info_content",myEditText.getText().toString()); //提交编辑器内容 editor.commit(); } } main.xml <?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:orientation="vertical" android:layout_width="fill_parent" android:layout_height="fill_parent" > <TextView android:layout_width="fill_parent" android:layout_height="wrap_content" android:text="备忘录" /> <EditText android:text="" android:id="@+id/EditText1" android:layout_width="fill_parent" android:layout_height="wrap_content" /> <Button android:id="@+id/Button1" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="保存" /> </LinearLayout> 效果图: 当我们退出屏幕再返回的时候,发现原来备忘录里编辑了一半的内容还在那里,其实它是把要保存的内容做诶XML文件保存在/data/data/package/shsared_prefs/下面了。 本文转自 lingdududu 51CTO博客,原文链接:http://blog.51cto.com/liangruijun/658521

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

Text-to-speech 入门与进阶学习笔记(android)

1,入门:让TEXT朗读起来 //1,先写一个用来检查tts是否安装的方法privatefinalstaticintCHECK_CODE=1; publicvoidcheckTts(){ IntentcheckIntent=newIntent();checkIntent.setAction(TextToSpeech.Engine.ACTION_CHECK_TTS_DATA); startActivityForResult(checkIntent,CHECK_CODE);} //创建一个TTS privateTextToSpeechmTts; //这个自己先去了解下onActivityResult是怎么回事,这里不作详解 @OverrideprotectedvoidonActivityResult(intrequestCode,intresultCode,Intentdata){ //TODOAuto-generatedmethodstubsuper.onActivityResult(requestCode,resultCode,data); if(requestCode==CHECK_CODE){ if(resultCode==TextToSpeech.Engine.CHECK_VOICE_DATA_PASS){ //成功创建一个TTS mTts=newTextToSpeech(this,this); }else{ //否则安装一个 IntentinstallIntent=newIntent();installIntent.setAction(TextToSpeech.Engine.ACTION_INSTALL_TTS_DATA);startActivity (installIntent);}}} //2,让TTS朗读起来 //onCreate方法中 //检查TTS是否正常checkTts(); //创建用组件privatespeakValue=(EditText) findViewById(R.id.speakValue); privatespeakButton=(Button) findViewById(R.id.sayHello); speakButton.setOnClickListener(newOnClickListener(){ @Override publicvoidonClick(Viewv){ //TODOAuto-generatedmethodstub Stringtext=speakValue.getText().toString(); Log.d("result","text--&gt;"+text);sayTts(text);}}); //TTs朗读用privatevoidsayTts(Stringtext){ //最简单的例子mTts.speak(text,TextToSpeech.QUEUE_FLUSH,null); } //补充,使用TTS朗读,一定要实现OnInitListener 接口 //TTs对象创建后初始化 @OverridepublicvoidonInit(intstatus){ if(status==TextToSpeech.SUCCESS){ //设置语言区域intresult=mTts.setLanguage(Locale.US); //如果是不支持语言 if(result==TextToSpeech.LANG_MISSING_DATA||result==TextToSpeech.LANG_NOT_SUPPORTED){ Log.e("error","不支持");}}} 就这么点代码就可以正常运行了… 2,进阶使用:改变我们朗读播放的类型,回调函数的使用与自定义文字发音 1,更改播放的流类型(暂且这样说,希望,有人解释一下) //更改播放使用的流类型 //在sayTts作以下修改 //TTs朗读用privatevoidsayTts(Stringtext){HashMap<String,String>myAlarm=newHashMap(); //把播放类型,通过闹钟流实现myHashAlarm.put(TextToSpeech.Engine.KEY_PARAM_STREAM,String.valueOf(AudioManager.STREAM_ALARM)); //你播放的tts在音频播放的闹钟类型流中mTts.speak(text,TextToSpeech.QUEUE_FLUSH,myAlarm); //英语原文是这样,我了解的就是以上我注释的内容 //我感觉不是很了解,希望有人帮帮 //OnAndroid,eachaudiostreamthatisplayedisassociatedwithone //streamtype,asdefinedinandroid.media.AudioManager.Foratalking //alarmclock,wewouldlikeourtexttobeplayedonthe //AudioManager.STREAM_ALARMstreamtypesothatitrespectsthealarm //settingstheuserhaschosenonthedevice. } 2,回调函数的使用 //在sayTts()中实现.. //需要实现OnUtteranceCompletedListener这个接口 //TTs朗读用 privateToasttoast;prvateContextcontext=getApplicationContext(); privatevoidsayTts(Stringtext){HashMap<String,String>myAlarm=newHashMap();mTts.setOnUtteranceCompletedListener(this); myAlarm.put(TextToSpeech.Engine.KEY_PARAM_UTTERANCE_ID,"metoo"); toast=Toast.makeText(context,"metoo",Toast.LENGTH_LONG); //最简单的例子mTts.speak(text,TextToSpeech.QUEUE_FLUSH,myAlarm);} //回调函数@OverridepublicvoidonUtteranceCompleted(StringutteranceId){speakPlayBack(utteranceId);} privatevoidspeakPlayBack(Stringstr){Log.d("result","playBack-->"+str);toast.show();} 3,录制TTS朗读保存到SD卡中 //把TTS朗读结果保存 privatevoidsayTofile(Stringtext){ HashMap<String,String>ttsRender=newHashMap<String,String>(); StringdestFileName="/sdcard/tts/"+text+".wav";ttsRender.put(TextToSpeech.Engine.KEY_PARAM_UTTERANCE_ID,text);mTts.synthesizeToFile(text,ttsRender,destFileName); } //在 你就可以看到你刚才朗读的Text被保存了 4,自定义Text发音 //自定义文字播放 privatevoidsayTrue(Stringtext){ StringdestFileName="/sdcard/tts/"+text+".wav";mTts.addSpeech(text,destFileName); mTts.speak(text,TextToSpeech.QUEUE_FLUSH,null);} //在onclick方法中运行sayTrue(); 亲测,MP3也可以播放… 5,销毁 @OverrideprotectedvoidonDestroy(){super.onDestroy(); if(mTts!=null){ mTts.stop(); mTts.shutdown();}}

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

ceph之openstack存储解决方案学习路线

ceph分布式存储搭建经历 http://strongit.blog.51cto.com/10020534/1739488 Ceph作为OpenStack后端存储 http://linuxnote.blog.51cto.com/9876511/1789924 eph常用命令 http://linuxnote.blog.51cto.com/9876511/1788361 Ceph使用块设备完整操作流程 http://linuxnote.blog.51cto.com/9876511/1788682 本文转自heavenseahill 51CTO博客,原文链接:http://blog.51cto.com/shower/1973642,如需转载请自行联系原作者

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

Android开发学习笔记:5大布局方式详解

Android中常用的5大布局方式有以下几种: 线性布局(LinearLayout):按照垂直或者水平方向布局的组件。 帧布局(FrameLayout):组件从屏幕左上方布局组件。 表格布局(TableLayout):按照行列方式布局组件。 相对布局(RelativeLayout):相对其它组件的布局方式。 绝对布局(AbsoluteLayout):按照绝对坐标来布局组件。 1. 线性布局 线性布局是Android开发中最常见的一种布局方式,它是按照垂直或者水平方向来布局,通过“android:orientation”属性可以设置线性布局的方向。属性值有垂直(vertical)和水平(horizontal)两种。 常用的属性: android:orientation:可以设置布局的方向 android:gravity:用来控制组件的对齐方式 layout_weight:控制各个组件在布局中的相对大小 第一个实例 ①效果图: ②核心代码如下: main.xml <?xmlversion="1.0"encoding="utf-8"?> <LinearLayoutxmlns:android="http://schemas.android.com/apk/res/android" android:orientation="vertical" android:layout_width="fill_parent" android:layout_height="fill_parent" > <LinearLayout android:layout_width="fill_parent" android:layout_height="wrap_content" android:orientation="vertical" > <EditText android:layout_width="fill_parent" android:layout_height="wrap_content" /> </LinearLayout> <LinearLayout android:layout_width="fill_parent" android:layout_height="wrap_content" android:orientation="horizontal" android:gravity="right" > <!--android:gravity="right"表示Button组件向右对齐--> <Button android:layout_height="wrap_content" android:layout_width="wrap_content" android:text="确定" /> <Button android:layout_height="wrap_content" android:layout_width="wrap_content" android:text="取消" /> </LinearLayout> </LinearLayout> 第二个实例 ①效果图: ②核心代码: mian.xml <?xmlversion="1.0"encoding="utf-8"?> <LinearLayoutxmlns:android="http://schemas.android.com/apk/res/android" android:orientation="vertical"android:layout_width="fill_parent" android:layout_height="fill_parent"> <LinearLayout android:orientation="horizontal" android:layout_width="fill_parent" android:layout_height="fill_parent" android:layout_weight="1"> <TextView android:text="red" android:gravity="center_horizontal" android:background="#aa0000" android:layout_width="wrap_content" android:layout_height="fill_parent" android:layout_weight="1" /> <!--android:gravity="center_horizontal"水平居中--> <!--layout_weight属性以控制各个控件在布局中的相对大小。layout_weight属性是一个非负整数值。 线性布局会根据该控件layout_weight值与其所处布局中所有控件layout_weight值之和的比值为该控件分配占用的区域。 例如,在水平布局的LinearLayout中有两个Button,这两个Button的layout_weight属性值都为1, 那么这两个按钮都会被拉伸到整个屏幕宽度的一半。如果layout_weight指为0,控件会按原大小显示,不会被拉伸; 对于其余layout_weight属性值大于0的控件,系统将会减去layout_weight属性值为0的控件的宽度或者高度, 再用剩余的宽度或高度按相应的比例来分配每一个控件显示的宽度或高度--> <TextView android:text="Teal" android:gravity="center_horizontal" android:background="#008080" android:layout_width="wrap_content" android:layout_height="fill_parent" android:layout_weight="1"/> <TextView android:text="blue" android:gravity="center_horizontal" android:background="#0000aa" android:layout_width="wrap_content" android:layout_height="fill_parent" android:layout_weight="1" /> <TextView android:text="orange" android:gravity="center_horizontal" android:background="#FFA500" android:layout_width="wrap_content" android:layout_height="fill_parent" android:layout_weight="1" /> </LinearLayout> <LinearLayout android:orientation="vertical" android:layout_width="fill_parent" android:layout_height="fill_parent" android:layout_weight="1"> <TextView android:text="rowone" android:textSize="15pt" android:background="#aa0000" android:layout_width="fill_parent" android:layout_height="wrap_content" android:layout_weight="1" /> <!----> <TextView android:text="rowtwo" android:textSize="15pt" android:background="#DDA0DD" android:layout_width="fill_parent" android:layout_height="wrap_content" android:layout_weight="1" /> <TextView android:text="rowthree" android:textSize="15pt" android:background="#008080" android:layout_width="fill_parent" android:layout_height="wrap_content" android:layout_weight="1" /> <TextView android:text="rowfour" android:textSize="15pt" android:background="#FFA500" android:layout_width="fill_parent" android:layout_height="wrap_content" android:layout_weight="1" /> </LinearLayout> </LinearLayout> 2. 帧布局 帧布局是从屏幕的左上角( 0,0)坐标开始布局,多个组件层叠排列,第一个添加的组件放到最底层,最后添加到框架中的视图显示在最上面。上一层的会覆盖下一层的控件。 简单的例子 ①效果图: ②核心代码: main.xml <?xmlversion="1.0"encoding="utf-8"?> <FrameLayoutxmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="fill_parent" android:layout_height="fill_parent" > <TextView android:layout_width="300dp" android:layout_height="300dp" android:background="#00BFFF" /> <TextView android:layout_width="260dp" android:layout_height="260dp" android:background="#FFC0CB" /> <TextView android:layout_width="220dp" android:layout_height="220dp" android:background="#0000FF" /> </FrameLayout> 3. 表格布局 表格布局是一个 ViewGroup以表格显示它的子视图(view)元素,即行和列标识一个视图的位置。 表格布局常用的属性如下: android:collapseColumns:隐藏指定的列 android:shrinkColumns:收缩指定的列以适合屏幕,不会挤出屏幕 android:stretchColumns:尽量把指定的列填充空白部分 android:layout_column:控件放在指定的列 android:layout_span:该控件所跨越的列数 简单的列子: ①效果图: ②核心代码: main.xml <?xmlversion="1.0"encoding="utf-8"?> <TableLayoutxmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="fill_parent" android:layout_height="fill_parent" > <TableRow> <Button android:text="Button1" /> <Button android:text="Button2" /> <Button android:text="Button3" /> </TableRow> <TableRow> <Button android:text="Button4" /> <Button android:layout_span="2" android:text="Button5" /> </TableRow> </TableLayout> 4. 相对布局 相对布局是按照组件之间的相对位置来布局,比如在某个组件的左边,右边,上面和下面等。 相对布局常用属性请参考我博客的: http://liangruijun.blog.51cto.com/3061169/631816 简单的例子 ①效果图: ②核心代码: main.xml <?xmlversion="1.0"encoding="utf-8"?> <RelativeLayoutxmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="fill_parent" android:layout_height="wrap_content" android:padding="10px" > <TextView android:id="@+id/tev1" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_marginBottom="30dp" android:text="PleaseTypeHere:" /> <EditText android:id="@+id/tx1" android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_below="@id/tev1" /> <Button android:id="@+id/btn1" android:layout_height="wrap_content" android:layout_width="wrap_content" android:layout_below="@id/tx1" android:layout_alignParentRight="true" android:text="确定" /> <Button android:id="@+id/btn2" android:layout_height="wrap_content" android:layout_width="wrap_content" android:layout_below="@id/tx1" android:layout_toLeftOf="@id/btn1" android:layout_marginRight="30dp" android:text="取消" /> </RelativeLayout> 5. 绝对布局 绝对布局通过指定子组件的确切 X,Y坐标来确定组件的位置,在Android2.0 API文档中标明该类已经过期,可以使用FrameLayout或者RelativeLayout来代替。所以这里不再详细介绍。 本文转自 lingdududu 51CTO博客,原文链接:http://blog.51cto.com/liangruijun/632532

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

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

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

[Android学习笔记六] Toast 更长时间显示

Android Toast是一种比较特殊的显示信息的机制,其没有焦点,并且显示一段时间之后就自动消失。Android 中提供的显示时长通过Toast.LENGHT_LONG和Toast.LENGTH_SHORT来指定,底层具体代表的时间长度分别是3.5s和2.0s。 本文介绍如何使得Toast显示的时间更长或者指定显示时间长度。 1. 基本用法代码示例 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 /** *Toast默认的长时间显示3.5s */ @OnClick (R.id.one_button) public void onClickOneButton(){ Toast.makeText( this , "HelloWorld" ,Toast.LENGTH_LONG).show(); } /** *Toast默认的短时间显示2.0s */ @OnClick (R.id.two_button) public void onClickTwoButton(){ Toast.makeText( this , "HelloWorld" ,Toast.LENGTH_SHORT).show(); } 2. 通过android.os.CountDownTimer类实现Toast的显示和消失 通过点击下图中的底端左Button使得Toast显示,右Button使得Toast消失。 代码示例: 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 /** *使用CountDownTimer实现Toast自定义时间显示 */ @Bind (R.id.three_textView) public TextViewthreeTextView; private ToastmCountDownTimeToast; public CountDownTimercdt= new CountDownTimer( 60 * 1000 , 1000 ){ @Override public void onTick( long millisUntilFinished){ threeTextView.setText( "Time剩余:" +(millisUntilFinished/ 1000 )+ "s" ); if ( null !=mCountDownTimeToast){ mCountDownTimeToast.show(); } } @Override public void onFinish(){ threeTextView.setText( "显示完成" ); if ( null !=mCountDownTimeToast){ mCountDownTimeToast.cancel(); } } }; @OnClick ({R.id.three_button_start,R.id.three_button_cancel}) public void onClickThreeButton(Viewv){ if ( null ==mCountDownTimeToast){ mCountDownTimeToast=makeToast( this ); mCountDownTimeToast.setGravity(Gravity.TOP|Gravity.LEFT, 30 , 30 ); } if (v.getId()==R.id.three_button_start){ cdt.start(); Log.d(TAG, "CountDownTimerstartshow" ); } if (v.getId()==R.id.three_button_cancel){ cdt.cancel(); threeTextView.setText( "取消" ); Log.d(TAG, "CountDownTimercancel" ); } } Toast对象的View布局文件(view_toast.xml) 1 2 3 4 5 6 7 8 9 <? xml version = "1.0" encoding = "utf-8" ?> < TextView xmlns:android = "http://schemas.android.com/apk/res/android" android:layout_width = "wrap_content" android:layout_height = "wrap_content" android:background = "#ef3939" android:orientation = "vertical" style = "@android:style/TextAppearance.DeviceDefault.Medium" android:gravity = "center_vertical|center_horizontal" android:padding = "10dp" android:text = "&quot;HelloWorld&quot;" android:textColor = "#f7f9fb" > </ TextView > 创建Toast对象(下文中创建Toast对象使用该方法) 1 2 3 4 5 6 7 public static ToastmakeToast(Contextcontext){ Toasttoast= new Toast(context); toast.setDuration(Toast.LENGTH_SHORT); TextViewview=(TextView)LayoutInflater.from(context).inflate(R.layout.view_toast, null ); toast.setView(view); return toast; } 上述代码通过CountDownTimer实现指定Toast显示时长和控制Toast显示与消失,重构之后代码如下: 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 public void showToast1( final Toasttoast, long duration){ final long SHORT= 2000 ; final long LONG= 3500 ; final long ONE_SECOND= 1000 ; final long d=duration<=SHORT?SHORT:duration>LONG?duration:LONG; new CountDownTimer(Math.max(d,duration),ONE_SECOND){ @Override public void onTick( long millisUntilFinished){ toast.show(); } @Override public void onFinish(){ toast.cancel(); } }.start(); } 3.通过Handler消息机制实现 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 public void showToast2( final Toasttoast, long duration){ final long SHORT= 2000 ; final long LONG= 3500 ; final long ONE_SECOND= 1000 ; final long d=duration<=SHORT?SHORT:duration>LONG?duration:LONG; final int what= 1 ; final Handlerhandler= new Handler(){ long remainder=d; @Override public void handleMessage(Messagemsg){ if (msg.what==what){ toast.show(); if (remainder>=ONE_SECOND){ remainder-=ONE_SECOND; sendEmptyMessageDelayed(what,ONE_SECOND); } else { removeMessages(what); } } } }; handler.sendEmptyMessage(what); } 其实这种实现和CountDownTimer实现的机制一样的。 4. Toast的指定时长显示其实就是不断的调用Toast的show()方法,其中show()方法中实现了将Toast对象添加到INotificationManager的Toast队列中去。具体细节可参见Toast(android.widget.Toast)源码。 5. 为什么要给Toast指定显示时长呢? 这或许不是个好主意。Toast的无焦点短时间自动消失机制就是为了给用户显示信息而不会产生较大干扰。如果长时间显示并且具有更多交互和事件处理,这就背离了Toast的本意,这样的场景可以考虑使用Notification,Dialog来实现。 使用Toast场景中更多的是关注其View和显示的位置,这可以实现更多有意思的东西,比如冒泡提示,使用向导等。在实践中则需要根据具体情况慎重选择和合理应用。 本文转自 secondriver 51CTO博客,原文链接:http://blog.51cto.com/aiilive/1717222,如需转载请自行联系原作者

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

[Android学习十一]Android开发单元测试

自从投入到Android Studio IDE之后基本上就赖着不走了。这里仅讨论AS(Android Studio)中Android单元测试。 开发一个Android应用单元测试这种程序员的自我修养和基本道德测试是必不可少的。其单元测试分为两块,一块是依赖Android API(平台)的单元测试,一块是不依赖Android API的单元测试。 1.不依赖AndroidAPI的单元测试 这一块就和通常开发JavaSE,EE应用的单元测试一样,测试框架更加需要自行选择即可。在通过AS创建Android应用模块时,默认在build.gradle文件中添加了测试库junit依赖。 如果在AS中使用不依赖AndroidAPI的单元测试,一图顶万言: 图一 图二 如图二所示,在Build Variants的Test Artifact设置为Unit tests之后,test源码目录呈现出IDEA风格的绿色目录。 这是就可以运行测试类或测试套件,比较容易就不多解释了。 2. 依赖Android API的单元测试 2.1 AS中配置Android单元测试 Android基于junit3框架提供了Android的单元测试框架,要在Android中使用单元测试就需要依赖android.test包下的具体类。下面是AS中配置Android单元测试的方法: 图三 2.2 Android单元测试示例 2.2.1 一个单元测试类: 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 package secondriver.heathfood.test; import android.test.InstrumentationTestCase; import com.orhanobut.logger.Logger; import secondriver.heathfood.App; import secondriver.heathfood.logic.TianGou; import secondriver.heathfood.pojo.FoodClassResult; import secondriver.heathfood.pojo.FoodDetail; import secondriver.heathfood.pojo.FoodDetailResult; /** *Author:secondriver *Created:2016/1/20 */ public class TestTianGou extends InstrumentationTestCase{ public TianGoutianGou; public void setUp(){ tianGou= new TianGou(App.restTemplate()); } public void test_queryFoodClassByParentId1(){ FoodClassResultresult=tianGou.queryFoodClassByParentId( 0 ); assertTrue(result.isStatus()); } } 关于Android的单元测试基类参见: http://www.oschina.net/question/54100_27061?fromerr=NydwIvQR。 http://www.uml.org.cn/mobiledev/201306074.asp 注意:Android单元测试的测试类写法遵循的是Junit3. 2.2.2 执行单元测试 在执行单元测试之前,讲Build Variant的Test Artifact设置为图一所示值。 执行Android Tester之后,输出截图: 图四 从截图上得知未授网络访问权权限。 2.2.3 AS中Android单元测试控制台 图五 在网上找关于Android单元测试的案例时,比较杂乱,遂作此文予以整理,Android单元测试如何去做当是另外的主题,需要参考android.test包中提供的具体类。 文中的android测试类的包直接创建在了main代码目录下,比较好的方式如下Android测试代码目录结构图: 图 六 本文转自 secondriver 51CTO博客,原文链接:http://blog.51cto.com/aiilive/1737254,如需转载请自行联系原作者

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

学习笔记-ELK5安装X-Pack

elk5和之前的版本不太一样,他将之前的三方插件集成到了xpack中,想要使用高级功能,必须安装xpack这个插件,但是这个xpack确实让人很头疼,如果配置不正确,es是收不到logstash传来的数据的,更别提Kibana能展示他了,根本就搜不到索引名称。 一、elasticsearch5按这X-Pack的步骤: 1、elasticsearch安装X-Pack: 在每个集群节点的运行ES_HOME里运行bin/elasticsearch-plugin install x-pack,我这里使用的是yum安装,所以ES_HOME是/usr/share/elasticsearch/。 1 bin /elasticsearch-plugin install x-pack 允许X-Pack创建上面的一系列索引。 2、重启elastcsearch服务 1 systemctlrestartelasticsearch 二、Kibana安装X-Pack 1、安装xpack 进入Kibana的安装目录,这里使用的是yum安装,在/usr/share/kibana下面,运行一下命令,在线安装: 1 2 3 cd /usr/share/kibana bin /kibana-plugin install x-pack systemctlrestartkibana 2、配置Kibana配置文件 将配置文件中下面两项取消注释: 这一个细节必须注意,重中之重,不然Kibana会连接不上es,密码是默认的Kibana登录密码,后续可以修改。 1 2 elasticsearch.username: "elastic" elasticsearch.password: "changeme" 3、登录Kibana 在浏览器上访问http://localhost:5601会出现一下页面,但是会出现认证登录。 三、登录认证 官网是这么说的,安装X-Pack后需要认证,而默认帐号:elastic,密码:changeme 四、添加logstash配置文件 1、添加logstash测试文件 在/etc/logstash/conf.d下面写一个测试文件 1 2 3 4 5 6 7 8 9 10 11 input{ stdin{} } output{ elasticsearch{ hosts=> "10.1.12.169:9200" index=> "test-messages-%{+YYYY.MM.dd}" user=> 'elastic' #需要在添加帐号密码,不然无法将数据传输到elasticsearch上 password=> 'changeme' } } 2、测试文件是否可用 1 2 [root@elkconf.d] #logstash-f/etc/logstash/conf.d/test.conf-t ConfigurationOK 3、测试输入是否成功 测试成功可以打开文件,输入进行测试了 1 2 3 4 [root@elkconf.d] #logstash-f/etc/logstash/conf.d/test.conf [root@elkconf.d] #logstash-f/etc/logstash/conf.d/test.conf Thestdinpluginisnowwaiting for input: helloworld 测试中多顶着es、logstash的日志,出了问题知道错在哪! 技术水平有限,先这么着吧。 本文转自 wangpengtai 51CTO博客,原文链接:http://blog.51cto.com/wangpengtai/1910397,如需转载请自行联系原作者

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

Hadoop概念学习系列之版本变迁(六)

至2012年5月,Apache Hadoop的四大分支构成了四个系列的Hadoop版本。 1. 0.20.X系列 0.20.X系列版本是最令用户感到疑惑的,因为它们具有的一些特性,trunk上没有;trunk上有的一些特性,0.20.X系列版本却没有。 2. 0.21.0/0.22.X系列 在这一版本中,将整个Hadoop项目分割成三个独立的模块,分别是Common、HDFS和MapReduce。 其中,HDFS和MapReduce都对Common模块有依赖性,但是MapReduce对HDFS并没有依赖性。那么,这样的话,MapReduce可以更容易地运行其他分布式文件系统,同时,模块间可以独立开发。 Common模块:最大的新特性是在测试方面上添加了Large-Scale Automated Test Framework 和 Fault Injection Framework 。 HDFS 模块 :主要增加的新特性包括支持追加操作与建立符号连接、 Secondary NameNode 改进(Secondary NameNode 被剔除,取而代之的是 Checkpoint Node,同 时添加一个 Backup Node 的角色,作为 NameNode 的冷备)、允许用户自定义 block 放置算法等。 MapReduce 模块 :在作业 API 方面,开始启动新 MapReduce API,但老的 API 仍然 兼容。 3. 0.23.X系列 0.23.X 是为了克服 Hadoop 在扩展性和框架通用性方面的不足而提出来的。它实际上 是一个全新的平台,包括分布式文件系统 HDFS Federation 和资源管理框架 YARN 两部分, 可对接入的各种计算框架(如 MapReduce、Spark等)进行统一管理。它的发行版自带 MapReduce 库,而该库集成了迄今为止所有的 MapReduce 新特性。 4. 2.X系列 同 0.23.X 系列一样,2.X 系列也属于下一代 Hadoop。与 0.23.X 系列相比,2.X 系列增 加了 NameNode HA 和 Wire-compatibility 等新特性。 本文转自大数据躺过的坑博客园博客,原文链接:http://www.cnblogs.com/zlslch/p/5058162.html,如需转载请自行联系原作者

资源下载

更多资源
Spring

Spring

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

Rocky Linux

Rocky Linux

Rocky Linux(中文名:洛基)是由Gregory Kurtzer于2020年12月发起的企业级Linux发行版,作为CentOS稳定版停止维护后与RHEL(Red Hat Enterprise Linux)完全兼容的开源替代方案,由社区拥有并管理,支持x86_64、aarch64等架构。其通过重新编译RHEL源代码提供长期稳定性,采用模块化包装和SELinux安全架构,默认包含GNOME桌面环境及XFS文件系统,支持十年生命周期更新。

Sublime Text

Sublime Text

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

WebStorm

WebStorm

WebStorm 是jetbrains公司旗下一款JavaScript 开发工具。目前已经被广大中国JS开发者誉为“Web前端开发神器”、“最强大的HTML5编辑器”、“最智能的JavaScript IDE”等。与IntelliJ IDEA同源,继承了IntelliJ IDEA强大的JS部分的功能。

用户登录
用户注册