android开发实例大全,安卓开发的入门书籍大家推荐几本?
android开发实例大全,安卓开发的入门书籍大家推荐几本?详细介绍
本文目录一览: Android开发之ImageView播放GIF动画实例
Android开发之ImageView播放GIF动画实例
Android的原生控件并不支持播放GIF格式的图片,如果想在Android中显示一张GIF动态图片,可以利用 ImageView控件来完成,但是放进去之后,你会发现,ImageView它只会显示这张图片的第一帧,不会产生任何的动画效果。我们必须通过自定义控件的方式来实现ImageView播放GIF 图片的功能。
首先我们来编写一个PowerImageView控件,让它既能支持ImageView控件原生的所有功能,同时还可以播放GIF动态图片。
先新建一个项目PowerImageViewTest,这里使用Android 4.0+Eclipse。
由于是要自定义控件,会需要一些自定义的控件属性,因此我们需要在values目录下新建一个attrs.xml的文件,在这个文件中添加项目需要的自定义属性。
这里我们目前暂时只需要一个自动播放auto_play属性,XML文件代码如下:
这个文件完成之后,下面我们来开始编写主类PowerImageView类,由于PowerImageView类需要支持ImageView的所有功能,我们必须要让PowerImageView继承自ImageView,代码如下:
public class PowerImageView extends ImageView implements OnClickListener {
/**
* 播放GIF动画的关键类
*/
private Movie mMovie;
/**
* 开始播放按钮图片
*/
private Bitmap mStartButton;
/**
* 记录动画开始的时间
*/
private long mMovieStart;
/**
* GIF图片的宽度
*/
private int mImageWidth;
/**
* GIF图片的高度
*/
private int mImageHeight;
/**
* 图片是否正在播放
*/
private boolean isPlaying;
/**
* 是否允许自动播放
*/
private boolean isAutoPlay;
/**
* PowerImageView构造函数。
*
* @param context
*/
public PowerImageView(Context context) {
super(context);
}
/**
* PowerImageView构造函数。
*
* @param context
*/
public PowerImageView(Context context, AttributeSet attrs) {
this(context, attrs, 0);
}
/**
* PowerImageView构造函数,在这里完成所有必要的初始化操作。
*
* @param context
*/
public PowerImageView(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.PowerImageView);
int resourceId = getResourceId(a, context, attrs);
if (resourceId != 0) {
// 当资源id不等于0时,就去获取该资源的流
InputStream is = getResources().openRawResource(resourceId);
// 使用Movie类对流进行解码
mMovie = Movie.decodeStream(is);
if (mMovie != null) {
// 如果返回值不等于null,就说明这是一个GIF图片,下面获取是否自动播放的属性
isAutoPlay = a.getBoolean(R.styleable.PowerImageView_auto_play, false);
Bitmap bitmap = BitmapFactory.decodeStream(is);
mImageWidth = bitmap.getWidth();
mImageHeight = bitmap.getHeight();
bitmap.recycle();
if (!isAutoPlay) {
// 当不允许自动播放的时候,得到开始播放按钮的图片,并注册点击事件
mStartButton = BitmapFactory.decodeResource(getResources(),R.drawable.start_play);
setOnClickListener(this);
}
}
}
}
@Override
public void onClick(View v) {
if (v.getId() == getId()) {
// 当用户点击图片时,开始播放GIF动画
isPlaying = true;
invalidate();
}
}
@Override
protected void onDraw(Canvas canvas) {
if (mMovie == null) {
// mMovie等于null,说明是张普通的图片,则直接调用父类的onDraw()方法
super.onDraw(canvas);
} else {
// mMovie不等于null,说明是张GIF图片
if (isAutoPlay) {
// 如果允许自动播放,就调用playMovie()方法播放GIF动画
playMovie(canvas);
invalidate();
} else {
// 不允许自动播放时,判断当前图片是否正在播放
if (isPlaying) {
// 正在播放就继续调用playMovie()方法,一直到动画播放结束为止
if (playMovie(canvas)) {
isPlaying = false;
}
invalidate();
} else {
// 还没开始播放就只绘制GIF图片的第一帧,并绘制一个开始按钮
mMovie.setTime(0);
mMovie.draw(canvas, 0, 0);
int offsetW = (mImageWidth - mStartButton.getWidth()) / 2;
int offsetH = (mImageHeight - mStartButton.getHeight()) / 2;
canvas.drawBitmap(mStartButton, offsetW, offsetH, null);
}
}
}
}
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
if (mMovie != null) {
// 如果是GIF图片则重写设定PowerImageView的大小
setMeasuredDimension(mImageWidth, mImageHeight);
}
}
/**
* 开始播放GIF动画,播放完成返回true,未完成返回false。
*
* @param canvas
* @return 播放完成返回true,未完成返回false。
*/
private boolean playMovie(Canvas canvas) {
long now = SystemClock.uptimeMillis();
if (mMovieStart == 0) {
mMovieStart = now;
}
int duration = mMovie.duration();
if (duration == 0) {
duration = 1000;
}
int relTime = (int) ((now - mMovieStart) % duration);
mMovie.setTime(relTime);
mMovie.draw(canvas, 0, 0);
if ((now - mMovieStart) >= duration) {
mMovieStart = 0;
return true;
}
return false;
}
/**
* 通过Java反射,获取到src指定图片资源所对应的id。
*
* @param a
* @param context
* @param attrs
* @return 返回布局文件中指定图片资源所对应的id,没有指定任何图片资源就返回0。
*/
private int getResourceId(TypedArray a, Context context, AttributeSet attrs) {
try {
Field field = TypedArray.class.getDeclaredField("mValue");
field.setAccessible(true);
TypedValue typedValueObject = (TypedValue) field.get(a);
return typedValueObject.resourceId;
} catch (Exception e) {
e.printStackTrace();
} finally {
if (a != null) {
a.recycle();
}
}
return 0;
}
}
这个类的代码注释已经非常详细了,我再来简单地解释一下。可以看到,我们重写了ImageView中所有的构建函数,使得 PowerImageView的用法可以和ImageView完全相同。在构造函数中,则是对所有必要的数据进行了初始化操作。首先,我们调用了 getResourceId()方法去获取图片资源对应的id值,在getResourceId()方法内部是通过Java的反射机制来进行获取的。得到了图片资源的id后,我们将它转换成InputStream,然后传入到Movie.decodeStream()方法中以解码出Movie对象。如果得到的Movie对象等于null,说明这是一张普通的图片资源,就不再进行任何特殊处理,因为父类ImageView都帮我们处理好了。如果得到的 Movie对象不等于null,则说明这是一张GIF图片,接着就要去获取是否允许自动播放、图片的宽高等属性的值。如果不允许自动播放,还要给播放按钮 注册点击事件,默认是不允许自动播放的。
接下来会进入到onMeasure()方法中。在这个方法中我们进行判断,如果这是一张GIF图片,则需要将PowerImageView的宽高重定义,使得控件的大小刚好可以放得下这张GIF图片。
再往后就会进入到onDraw()方法中。在这个方法里同样先判断当前是一张普通的图片还是GIF图片,如果是普通的图片就直接调用 super.onDraw()方法交给ImageView去处理就好了。如果是GIF图片,则先判断该图是否允许自动播放,允许的话就调用 playMovie()方法去播放GIF图片就好,不允许的话则会先在PowerImageView中绘制该GIF图片的第一帧,并在图片上绘制一个播放 按钮,当用户点击了播放按钮时,再去调用playMovie()方法去播放GIF图片。
下面我们来看看playMovie()方法中是怎样播放GIF图片的吧。可以看到,首先会对动画开始的时间做下记录,然后对动画持续的时间做下记 录,接着使用当前的时间减去动画开始的时间,得到的时间就是此时PowerImageView应该显示的那一帧,然后借助Movie对象将这一帧绘制到屏 幕上即可。之后每次调用playMovie()方法都会绘制一帧图片,连贯起来也就形成了GIF动画。注意,这个方法是有返回值的,如果当前时间减去动画 开始时间大于了动画持续时间,那就说明动画播放完成了,返回true,否则返回false。
完成了PowerImageView的编写,下面我们就来看一看如何使用它吧,其实非常简单,打开或新建activity_main.xml,代码如下所示:
<relativelayout p=""
android:layout_width="match_parent"
android:layout_height="match_parent" >
<com.example.powerimageviewtest.powerimageview p=""
android:id="@+id/image_view"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerInParent="true"
android:src="@drawable/anim"
/>
可以看到,PowerImageView的用法和ImageView几乎完全一样,使用android:src属性来指定一张图片即可,这里指定的anim就是一张GIF图片。然后我们让PowerImageView在布局里居中显示MainActivity中的代码都是自动生成的,这里就不再贴出来了。在AndroidManifest.xml中还有一点需要注意,有些4.0 以上系统的手机启动了硬件加速功能之后会导致GIF动画播放不出来,因此我们需要在AndroidManifest.xml中去禁用硬件加速功能,可以通过指定android:hardwareAccelerated属性来完成,代码如下所示:
<manifest p=""
package="com.example.powerimageviewtest"
android:versionCode="1"
android:versionName="1.0" >
<uses-sdk p=""
android:minSdkVersion="14"
android:targetSdkVersion="17" />
android:allowBackup="true"
android:icon="@drawable/ic_launcher"
android:label="@string/app_name"
android:theme="@style/AppTheme"
android:hardwareAccelerated="false"
>
android:name="com.example.powerimageviewtest.MainActivity"
android:label="@string/app_name" >
现在可以来运行一下代码了,一打开程序你就会看到GIF图片的第一帧,点击图片之后就可以播放GIF动画了。
然后我们还可以通过修改activity_main.xml中的代码,给它加上允许自动播放的属性,代码如下所示:
<relativelayout p=""
xmlns:attr="http://schemas.android.com/apk/res/com.example.powerimageviewtest"
android:layout_width="match_parent"
android:layout_height="match_parent" >
<com.example.powerimageviewtest.powerimageview p=""
android:id="@+id/image_view"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerInParent="true"
android:src="@drawable/anim"
attr:auto_play="true"
/>
这里使用了刚才我们自定义的属性,通过attr:auto_play来启用和禁用自动播放功能。现在将auto_play属性指定成true后,PowerImageView上就不会再显示一个播放按钮,而是会循环地自动播放动画。不仅如此,PowerImageView还继承了ImageView原生的所有功能,只要指定的不是GIF图 片,PowerImageView表现的结果就和ImageView完全一致,现在我们来放一张普通的PNG图片,修改 activity_main.xml中的代码,如下所示:
<relativelayout p=""
android:layout_width="match_parent"
android:layout_height="match_parent" >
<com.example.powerimageviewtest.powerimageview p=""
android:id="@+id/image_view"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerInParent="true"
android:src="@drawable/myphoto"
/>
这里在src属性里面指定了一张名字为myphoto的PNG图片,图片在布局正中央显示出来了,正是普通ImageView所具备的功能。我们还可以在PowerImageView中指定android:scaleType等属性,用法和原生的ImageView完全一样。
Android编程经典200例的书本简介
内容提要Android编程经典200例(含DVD光盘1张) 本书通过200个经典实例全面、系统地介绍了Android平台下的软件开发知识,重点突出、涉及面广、实用性强,在实例的讲解过程中还详细分析了开发思路及侧重点,使读者达到举一反三的效果。全书分为14章,分别为:Android简介、Android简单控件的开发及应用、Android高级控件的开发及应用、手机用户界面、手机通信服务及手机控制、手机的自动服务功能、手机文件I/O与数据库的应用、手机网络应用、手机的Google服务功能、手机多媒体服务功能、Android手机的3D世界、手机特效开发、休闲游戏——Q版疯狂大炮、娱乐游戏——3D迷宫。
Android开发之蓝牙(Bluetooth)
在上一篇中有介绍了Wifi与网络连接处理 Android开发之WiFi与网络连接处理 下面,来继续说说Android中蓝牙的基本使用。
Bluetooth是目前使用的最广泛的无线通讯协议之一,主要针对短距离设备通讯(10米),常用于连接耳机、鼠标和移动通讯设备等。
值得一提的是: android4.2新增了部分新功能,但是对于Bluetooth熟悉的人或许开始头疼了,那就是Android4.2引入了一个新的蓝牙协议栈针BLE。谷歌和Broadcom之间的合作,开发新的蓝牙协议栈,取代了基于堆栈的Bluez。因此市场上出现了老设备的兼容问题,很多蓝牙设备在android4.2手机上不能正常使用。
BluetoothAdapter简单点来说就是代表了本设备(手机、电脑等)的蓝牙适配器对象。
first:we need permission 要操作蓝牙,先要在AndroidManifest.xml里加入权限
**下面来看看如何使用蓝牙。 **↓↓↓**** Demo已就绪:
返回值:如果设备具备蓝牙功能,返回BluetoothAdapter 实例;否则,返回null对象。
打开蓝牙设备的方式: 1.直接调用函数enable()去打开蓝牙设备 ; 2.系统API去打开蓝牙设备,该方式会弹出一个对话框样式的Activity供用户选择是否打开蓝牙设备。
注意: 1.如果蓝牙已经开启,不会弹出该Activity界面。2.在目前大多数Android手机中,是不支持在飞行模式下开启蓝牙的。如果蓝牙已经开启,那么蓝牙的开关 ,状态会随着飞行模式的状态而发生改变。
1. 搜索蓝牙设备 使用BluetoothAdapter的startDiscovery()方法来搜索蓝牙设备 startDiscovery()方法是一个异步方法,调用后会立即返回。该方法会进行对其他蓝牙设备的搜索,该过程会持续12秒。该方法调用后,搜索过程实际上是在一个System Service中进行的,所以可以调用cancelDiscovery()方法来停止搜索(该方法可以在未执行discovery请求时调用)。
系统开始搜索蓝牙设备 ^( *  ̄(oo) ̄ ) ^ 系统会发送以下三个广播:
2.扫描设备
3.定义广播接收器接收搜索结果
4.注册广播
获取附近的蓝牙设备
第一步建立连接:首先Android sdk(2.0以上版本)支持的蓝牙连接是通过BluetoothSocket建立连接,服务端BluetoothServerSocket和客户端(BluetoothSocket)需指定同样的UUID,才能建立连接,因为建立连接的方法会阻塞线程,所以服务器端和客户端都应启动新线程连接。
(这里的服务端和客户端是相对来说的) 两个蓝牙设备之间的连接,则必须实现服务端与客户端的机制。 当两个设备在同一个RFCOMM channel下分别拥有一个连接的BluetoothSocket,这两个设备才可以说是建立了连接。
服务端设备与客户端设备获取BluetoothSocket的途径是不同的。 1,服务端设备是通过accepted一个incoming connection来获取的, 2,客户端设备则是通过打开一个到服务端的RFCOMM channel来获取的。
服务端 通过调用BluetoothAdapter的listenUsingRfcommWithServiceRecord(String, UUID)方法来获取BluetoothServerSocket(UUID用于客户端与服务端之间的配对)
客户端 调用BluetoothService的createRfcommSocketToServiceRecord(UUID)方法获取BluetoothSocket(该UUID应该同于服务端的UUID)。 调用BluetoothSocket的connect()方法(该方法为block方法),如果UUID同服务端的UUID匹配,并且连接被服务端accept,则connect()方法返回。
数据传递,通过以上操作,就已经建立的BluetoothSocket连接了,数据传递无非是通过流的形式 获取流
该类就是关于远程蓝牙设备的一个描述。通过它可以和本地蓝牙设备---BluetoothAdapter连接通信。
好多东西我也不知道怎么描述,下面给出Demo: 刚好有刚学习的小伙伴问我ListView怎么用,那我就用ListView。
源码: RairDemo GitHub: https://github.com/Rairmmd/android-demo Coding: https://coding.net/u/Rair/p/RairDemo/git
android开发中怎样实现混音
android开发中怎样实现混音,实例代码如下:
[mw_shl_code=java,true]public class MixRunnable implements Runnable {
private MixRecorder context;
/**
* AudioRecord创建参数类
*
* @author christ
*/
private static class RecorderParameter {
// 音频获取源
private static int audioSource = MediaRecorder.AudioSource.MIC;
// 设置音频采样率,44100是目前的标准,但是某些设备仍然支持22050,16000,11025
private static final int sampleRateInHz = 44100;
// 设置音频的录制的声道CHANNEL_IN_STEREO为双声道,CHANNEL_CONFIGURATION_MONO为单声道
private static final int channelConfig = AudioFormat.CHANNEL_CONFIGURATION_MONO;
// 音频数据格式:PCM 16位每个样本。保证设备支持。PCM 8位每个样本。不一定能得到设备支持。
private static final int audioFormat = AudioFormat.ENCODING_PCM_16BIT;
// 缓冲区字节大小
private static int bufferSizeInBytes;
}
// 设置运行状态
private boolean isRunning = true;
// AudioRecord对象
private static AudioRecord recorder;
// 设置MediaPlayer对象
private static MediaPlayer mediaPlayer;
// 伴奏文件
private FileInputStream accompany;
// 原唱文件
private FileInputStream original;
// 得分
private int score;
private boolean isFirst = true;
/**
* 混音评分线程的构造方法
*
* @param accompany
* :伴奏文件路径
* @param original
* :原唱文件路径
* @throws FileNotFoundException
*/
public MixRunnable(MixRecorder context, String accompany, String original) throws FileNotFoundException {
this.context = context;
this.accompany = new FileInputStream(accompany);
this.original = new FileInputStream(original);
creatAudioRecord();
mediaPlayer = new MediaPlayer();
}
@Override
public void run() {
try {
// MediaPlayer准备
mediaPlayer.reset();
mediaPlayer.setDataSource("/sdcard/111.wav");
// mediaPlayer.setDataSource(accompany.getFD());
mediaPlayer.setOnCompletionListener(new OnCompletionListener() {
@Override
public void onCompletion(MediaPlayer mp) {
isRunning = false;
}
});
mediaPlayer.prepare();
// 跳过头
accompany.read(new byte[44]);
original.read(new byte[44]);
FileOutputStream fos = new FileOutputStream(new File("/sdcard/love.raw"));
// 开始读
byte[] sourceReader = new byte[RecorderParameter.bufferSizeInBytes * 2];
short[] sourceShortArray;
short[] audioReader = new short[sourceReader.length / 4];
mediaPlayer.start();
recorder.startRecording();
while (isRunning) {
int sourceReadSize = accompany.read(sourceReader, 0, sourceReader.length);
if (sourceReadSize < 0) {
isRunning = false;
continue;
}
sourceShortArray = byteToShortArray(sourceReader, sourceReadSize / 2);
recorder.read(audioReader, 0, audioReader.length);
short[] oneSecond = mixVoice(sourceShortArray, audioReader, sourceReadSize / 2);
byte[] outStream = new byte[oneSecond.length * 2];
for (int i = 0; i < oneSecond.length; i++) {
byte[] b = shortToByteArray(oneSecond);
outStream[2 * i] = b[0];
outStream[2 * i + 1] = b[1];
}
安卓开发的入门书籍大家推荐几本?
在这里将我收集的一些Android开发书籍,与大家分享:
1、介绍Android与GPhone的书籍
IntroductionToAndroid
Google官方文档,简要的介绍了Android的各个方面,值得大家看下。
下载:DownloadLink
GPhone说明书
是每个开发人员必须阅读的,关于GPhone的使用、功能,结合SDK看想必收获会更大。
下载:
2、经典开发书籍
Android编程入门教程andbook
andbook是我看到的最简单但最好的Android程序开发入门书籍,内容仅有60多页,图文并茂,如果你从来没有接触过Android开发,也完全可以通过阅读此书了解程序开发过程,甚至对APK程序的基本原理和AndroidUI界面开发有个清晰的认识,相信你花上几个小时读过后,一定会跃跃欲试加入Android开发行列,心动吧,那就行动吧。。。
英文原版下载:
中文版下载:
深入浅出Android_Google手持设备应用程序设计
入门书籍,作者写的很不错,可以在阅读SDK的同时阅读这本书,中间的一些使用介绍的非常清楚,最重要的是中文版的
GoogleAndroid应用框架原理与程式设计36技
最早介绍Android的中文书籍,台湾人写的繁体版的,看得有些影响,不过还是值得耐心阅读的
AndroidAProgrammer’sGuide
多个专家写的介绍Android的书籍,内容写的很不错,AsktheExpert部分针对一些问题作了详细的说明
AndroidEssentials
对Android介绍的比较全面,从安装到开发,应该有新版本了。
GoogleAndroidSDK开发范例大全(第2版)
以Android手机应用程序开发(采用AndroidSDK2.1)为主题,通过160多个范例全面且深度地整合了手机、网络及服务等多个开发领域,为读者提高程序设计功力提供了很大的帮助。
GoogleAndroid开发入门与实战
内容上覆盖了用Android开发的大部分场景,从Android基础介绍、环境搭建、SDK介绍、Market使用,到应用剖析、组件介绍、实例演示等方面。从技术实现上,讲解了5个Android平台下的完整综合实例及源代码分析,分别是RSS阅读器、基于GoogleMap的个人GPS、豆瓣网(Web2.0)客户端、在线音乐播放器、手机信息助手,为初学者学习与实践结合提供了很好的指导。
Android平台开发之旅
涵盖了Android平台1.5到2.2版本的主要功能特性,立足实际的开发案例,介绍了Android手机平台开发的基础概念、实用技术和应用模式。主要内容包括:平台基础、开发环境搭建、程序框架、高级界面和底层界面设计、文件系统管理、网络通信、无线通信、多媒体编程、个人信息管理、电话系统、数据库应用、XML应用和地图应用。开发实例多达120例。
如何成为Android高手
成为一名真正的Android高手必须掌握和遵循的一些准则:
1,学会懒惰
2,精通Android体系架构、MVC、常见的设计模式、控制反转(IoC)
3,编写可重用、可扩展、可维护、灵活性高的代码
4,高效的编写高效的代码
安卓开发的入门书籍大家推荐几本?
如果是想做应用 推荐你看android应用开发揭秘 android开发入门与实战
如果是想做游戏,你就找一下android游戏开发宝典
如果是想了解系统 ,定制系统 你可以找一些关于框架方面的书。名字具体我忘记了。
也可以百度HI 我,这里有些资料可以发给你,希望能帮助到你
望采纳。
Android开发入门与实战、android开发揭秘、android从入门到精通
Android学习入门书籍推荐
Android编程入门教程andbook
andbook 是我看到的最简单但最好的Android 程序开发入门书籍,内容仅有60 多页,图文并
茂,如果你从来没有接触过Android 开发,也完全可以通过阅读此书了解程序开发过程,甚
至对APK 程序的基本原理和Android UI 界面开发有个清晰的认识,相信你花上几个小时读
过后,一定会跃跃欲试加入Android 开发行列,心动吧,那就行动吧。。。
深入浅出Android–Google手持设备应用程序设计
入门书籍,作者写的很不错,可以在阅读SDK 的同时阅读这本书,中间的一些使用介绍的
非常清楚,最重要的是中文版的
GoogleAndroid应用框架原理与程式设计36技
最早介绍Android 的中文书籍,台湾人写的繁体版的,看得有些影响,不过还是值得耐心阅
读的
AndroidAProgrammer’s Guide
多个专家写的介绍Android 的书籍,内容写的很不错,Ask the Expert 部分针对一些问题作
了详细的说明
Android Essentials
对Android 介绍的比较全面,从安装到开发,应该有新版本了。
GoogleAndroid SDK开发范例大全(第2版)
以Android 手机应用程序开发(采用AndroidSDK2.1)为主题,通过160多个范例全面且深
度地整合了手机、网络及服务等多个开发领域,为读者提高程序设计功力提供了很大的帮助。
GoogleAndroid开发入门与实战
内容上覆盖了用Android 开发的大部分场景,从Android 基础介绍、环境搭建、SDK 介绍、
Market 使用,到应用剖析、组件介绍、实例演示等方面。从技术实现上,讲解了5个Android
平台下的完整综合实例及源代码分析,分别是RSS 阅读器、基于Google Map 的个人GPS、
豆瓣网(Web 2.0)客户端、在线音乐播放器、手机信息助手,为初学者学习与实践结合提
供了很好的指导。
Android平台开发之旅
涵盖了Android 平台1.5到2.2版本的主要功能特性,立足实际的开发案例,介绍了Android
手机平台开发的基础概念、实用技术和应用模式。主要内容包括:平台基础、开发环境搭
建、程序框架、高级界面和底层界面设计、文件系统管理、网络通信、无线通信、多媒体编
程、个人信息管理、电话系统、数据库应用、XML 应用和地图应用。开发实例多达120例。
如何成为Android高手
成为一名真正的Android 高手必须掌握和遵循的一些准则:
1,学会懒惰
2,精通Android 体系架构、MVC、常见的设计模式、控制反转(IoC)
3,编写可重用、可扩展、可维护、灵活性高的代码
4,高效的编写高效的代码
5,学会至少一门服务器端开发技术
Android开发指南中文版之应用程序框架
Android SDK1.5版的英文开发资料Android Development Guide 中应用程序框架部分的翻译
PDF 文件。
1、《GoogleAndroidSDK开发范例大全》
《GoogleAndroidSDK开发范例大全》是2010年人民邮电出版社出版的图书。全书共分10章,主要以范例集的方式来讲述Android的知识点,详细介绍了开发Android的人机交互界面、Android常用的开发控件、使用Android手机收发短信等通信服务。
2、《Android软件安全权威指南》
本书主要介绍Android平台上的软件安全技术。从平台搭建和语言基础开始,循序渐进地讲解了Android平台上的软件攻防技术。本书共12章,系统地讲解了与Android软件安全相关的环境搭建、文件格式、静态分析、动态调试、Hook与注入、软件保护技术、软件壳等多个主题。
3、《Android开发精要》
《Android开发精要》是2012年机械工业出版社出版的图书,作者是范怀宇。该书讲述的是如何才能写出贴近Android设计理念、能够更加高效和可靠运行的Android应用,通过Android的源代码去了解其底层实现细节是最重要的方法之一。
4、《Android应用性能优化》
《Android应用性能优化》是2012年人民邮电出版社出版的图书,作者是[法] Hervé Guihot。本书主要介绍如何快速高效地优化应用,让应用变得稳定高效。
5、《Android应用UI设计模式》
《Android应用UI设计模式》面向Android 4.0+操作系统,是市面上第一本深入解析Android界面设计的佳作。《Android应用UI设计模式》从适用于移动设备和平板的通用模式以及Android UI设计指南出发。
参考资料来源:
百度百科—《GoogleAndroidSDK开发范例大全》
百度百科—《Android软件安全权威指南》
百度百科—《Android开发精要》
百度百科—《Android应用性能优化》
百度百科—《Android应用UI设计模式》
Android开发入门与实战的作品目录
第1章 掀起你的盖头来—初识Android1.1 认识Android1.2 Android的背景1.2.1 Android的历史1.2.2 Android的发展1.3 我的Android我做主1.3.1 开发基于Android平台的应用1.3.2 参加Android开发者大赛1.3.3 个人英雄主义再现—得到更多人的认可和尊重1.3.4 获得应有的收益—Android Market1.4 真实体验—Android 模拟器1.4.1 初识庐山真面目—模拟器概述1.4.2 模拟器和真机的区别1.4.3 模拟器使用注意事项1.5 更上一层楼,加入Android开发社区1.6 本章小结第2章 工欲善其事 必先利其器—搭建Android开发环境2.1 你的爱机胜任吗—开发Android应用前的准备2.1.1 Android开发系统要求2.1.2 Android软件开发包2.1.3 其他注意事项2.2 Wwindow开发环境搭建2.2.1 JDK、Eclipse、Android SDK软件安装2.2.2 SDK的家在哪里—设定 Android SDK Home2.2.3 真的准备好了吗—开发环境验证2.3 Linux一族— Ubuntu开发环境搭建2.3.2 设定 Android SDK Home2.4 Mac OS一族—苹果开发环境搭建2.5 本章小结第3章 清点可用资本—Android SDK介绍3.1 Android SDK基础3.2 深入探寻Android SDK的密码3.2.1 Android SDK目录的骨架3.2.2 android.jar及内部结构3.2.3 SDK文档及阅读技巧3.2.4 先来热热身—Android SDK例子解析3.2.5 小李飞刀—Android SDK提供的工具介绍3.3 重中之重—Android 典型包分析3.3.1 开发的基石—Android API核心开发包介绍3.3.2 拓展开发外延—Android可选API介绍3.4 本章小结第4章 赚钱的市场—Android Market及应用发布4.1 Google Market产生背景与目的4.2 体验“选货”的乐趣—在G1上体验Market的使用4.3 Android开发活动及特色应用4.3.1 开发应用的领域4.3.2 Android Market特色应用4.4 你也可以做东家—申请M arket帐号4.4.1 卖东西要先入伙—准备工作4.4.2 入伙过程—申请4.5 开张了—在Market上发布应用4.5.1 发布时可能遇到的错误4.5.2 卖东西也要签名—生成签名文件4.5.3 项目打包、签名和发布4.6 本章小结第5章 千里之行 始于足下—第一个应用HelloWorld5.1 HelloWorld应用分析5.1.1 新建一个Android工程5.1.2 填写工程的信息5.1.3 编程实现5.1.4 运行项目5.2 调试项目5.2.1 设置断点5.2.2 Debug 项目5.2.3 断点调试5.3 本章小结第6章 磨刀不误砍柴工—Android应用程序结构介绍第7章 良好的学习开端—Android基本组件介绍第8章 移动信息仓库—Android的数据存储操作第9章 我来“广播”你的“意图”—Intents和Broadcast面对面第10章 一切为用户服务—Service应用实例第11章 循序渐进—开发Android应用的基本步骤第12章 Android综合案例一—RSS阅读器实例第13章 综合案例二—基于Google API开发个人移动地图第14章 综合案例三—基于Android的豆瓣网(Web 2.0)移动客户端开发第15章 综合案例四—在线音乐播放器第16章 综合案例五—手机信息查看助手
Android开发之Java设计模式基础篇
今天我们就Android开发中的一些设计模式做一些基础性的掌握,本次就Android项目的架构设计相关内容做分析:1. 静态工厂方法静态工厂方法可以算是工厂方法加单例模式的整合在Android平台上,由于Android的Context可以很好的传递实例,静态工厂方法可以提到传统的类构造器,对于一些逻辑的服务提供类可以考虑这样的设计,比如文件下载、图片裁剪等操作。2. Java的类访问权限对于程序的可靠性而言,成员变量尽量私有,通过暴漏公开的方法来访问这些私有成员,提供类似getXXX和setXXX这样的方法,不仅是Java,这点C#对于属性的操作概念在Dot Net上已经深入人心,好处就是可以阻止继承后的访问换乱问题。3. 使用枚举替代常量Java在JDK 1.5开始加入了enum枚举类,相对于常规的final int这样的定义一些常量更简单安全,毕竟常量是一堆类似整形的数值,打印起来没有过多的意义,枚举对于继承后访问的清晰度可以很好的杜绝隐患发生。4. 使用列表优先于数组Java的集合类很方便,使用List类的列表在开销上比Object [ ] 这样的数组大,但是对于泛型的支持而言更好用强大。也可以避免一些不必要的错误,比如cwjObject [] obj= new int[1];obj[1] = "android开发网测试"; //这样会在运行时抛出类似ArrayStoreException这样的异常。而使用列表则为:ListcwjObject obj=new ArrayListint();obj.add("android123测试"); // 由于传入列表的是字符串,和构造时类型的int不同,在编译时就提示错误,可以避免一些不必要的情况发生。5. Java的foreach代替forJava的foreach仍然使用for来写,这点和C#直接用foreach关键字有点不同,但是使用方法是一样的,除了更简洁外,其实foreach比传统的for更加优化,比如传统的for第二个限制位,一般访问属性或方法,比如说for (int x=0;xobj.size();x++) //这句的限制符号每次都会执行obj.size() 方法,当然Android开发网相信size()方法访问的是一个数组的length属性,活着是for (int y=0;yobj.length;y++) //这里同样每次循环都执行obj.length对于Java VM的开销主要由这个obj的长度决定的,而Android SDK文档的推荐方式是int nSize=obj.size() 或 int nSize=obj.lengthfor (int z=0;znSize;z++) ,但是这还不是最优的方法,下面Android123给大家更好的foreach方式的替代方法:for (SmartObject singleObj : SmartObjectArray){singleObj.setName("cwj"); 或 singleObject.strName="cwj";}有关Android开发中的Java设计模式技巧,希望国内Android开发者打好Java基础,别扎堆实现铺天盖地的应用,目前不说恶意软件问题,就大部分的软件设计质量令人担忧,还有很多应用基本上就是J2EE或J2SE开源项目的移植版。
基于android系统的手机游戏的开发
如果你有兴趣为Android平台开发游戏,有很多你需要了解的东西。如果你有过游戏开发经验,那么转移到移动平台上来将不是特别困难。你主要只需学习其架构以及API就行了。如果你是一名游戏开发新手,我总结了一张列表,上面有你必需知道的东西,供你起步用。这些知识适用于很多类型的游戏,包括动作类、策略类、模拟类和益智类。Android是一个基于Java的环境。这对初学者来说是个好消息,因为相对于C,Java被广泛认为是一门更容易上手的语言,它是移动开发的规范。Google也做了一件出色的工作,它将API文档化并提供示例代码供使用。其中有个叫做APIDemos的示例几乎展示了所有API的功能。如果你熟悉Java并且用过Eclipse,要让你的第一个应用跑起来那是相当简单。如果你以前从没写过代码,在你前进路上还要学习很多,但别气馁。
获取SDK
新手上路的第一步便是获取AndroidSDK(软件开发工具包)。SDK里有一个核心类库,一个模拟器,一些工具和示例代码。我强烈建议使用Eclipse和AndroidEclipse插件。如果你玩Android的话,EclipseIDE对Java开发者来说很好用。如果这是你第一次开发Java项目,你可能会需要下载全套JDK,它里面包括签名和部署你的应用程序的一些工具。
学习应用程序架构
别急着一头扎进开发的海洋里,理解Android应用程序架构是很重要的。如果你不学一下,你设计出来的游戏在线下将很难调试。你将需要理解、Activities、Intents以及它们怎样相互联系。Google提供了很多有用的架构信息。真正重要的是要理解为什么你的游戏需要多于一个的Activity,以及什么才是设计一个有良好用户体验的游戏。要理解这些,首先要了解什么是Activity生命周期。
学习Activity生命周期
Activity生命周期由Android操作系统来管理。你的activity创建、恢复、暂停、销毁都受操作系统的支配。正确处理这些事件是很重要的,这样应用程序才能表现良好,做用户认为正确的事。在你设计你的游戏之前了解所有这些是如何工作的是件好事,因为以后你可以为自己节省调试时间和昂贵的重新设计时间。对大多数应用来说,默认的设置将工作正常,但对于游戏,你可能需要考虑将标志打开。当设置为默认时,Android在它认为合适时会创建activity的新实例。对于游戏来说,你可能只需要一个游戏activity的实例。这对于你要怎样管理事务的状态有些影响,但对于我来说,这解决了一些资源管理的问题,应予以考虑。
主循环
根据你写的游戏的类型,你可能需要也可能不需要一个主循环。如果你的游戏不依赖于时间或者它仅仅对用户所做的加以回应,并且不做任何视觉上的改变,永远等待着用户的输入,那么你就不需要主循环。如果你写的是动作类游戏或者带有动画、定时器或任何自动操作的游戏,你应该认真考虑下使用主循环。
游戏的主循环以一个特定的顺序通常尽可能多的在每秒钟内“滴答”提醒子系统运行。你的主循环需要在它自己的线程里运行,原因是Android有一个主用户界面线程,如果你不运行自己的线程,用户界面线程将会被你的游戏所阻塞,这会导致Android操作系统无法正常的更新任务。执行的顺序通常如下:状态,输入,人工智能,物理,动画,声音,录像。
更新状态意思是管理状态转换,例如游戏的结束、人物的选择或下一个级别。很多时候你需要在某个状态上等上几秒钟,而状态管理应该处理这种延迟,并且在时间过了之后设置成下一个状态。
输入是指用户按下的任何键、对于滚动条的移动或者用户的触摸。在处理物理之前处理这些是很重要的,因为很多时候输入会影响到物理层,因而首先处理输入将会使游戏的反应更加良好。在Android里,输入事件从主用户界面线程而来,因此你必须写代码将输入放入缓冲区,这样你的主循环可以在需要的时刻就从缓冲区里取到它。这并非难事。首先为下一个用户输入定义一个域,然后将或函数设为接到一个用户动作就放到那个域里,有这两步就够了。如果对于给定游戏的状态,这是一个合法的输入操作,那么所有输入需要在那一刻做的更新操作都已经定下来了,剩下来就让物理去关心怎样响应输入吧。
人工智能所做的类似于用户在决定下一个要“按”哪个按钮。学习怎样写人工智能程序超出了这篇文章的范围,但大体的意思是人工智能会按照用户的意图来按按钮。这些也有待物理去处理和响应吧。
物理可能是也可能不是真正的物理。对于动作类游戏来说,关键点是要考虑到上一次更新的时间、正在更新的当前时间、用户输入以及人工智能,并且决定它们朝着什么方向发展和是否会发生冲突。对于一个你可视化地抓取一些部件并滑动它们的游戏来说,物理就是这个游戏中滑动部件或者使之放入合适的位置的部分。对于一个小游戏来说,物理即使这个游戏中决定答案是错还是对的部分。你可能将其命名为其他东西,但每个游戏都有一个作为游戏引擎的红肉部分(译者注:可能是主体部分的意思),在这篇文章里,我把这部分称为物理。
动画并非像在游戏里放入会动的gif图片那样简单。你需要使得游戏能在恰当的时间画出每一帧。这并没有听起来那么困难。保留一些像isDancing、danceFrame和那样的状态域,那样动画更新便能决定是否可以切换到下一帧去了。动画更新真正做的事就那么多。真正来显示动画的变化是由录像更新来处理的。
声音更新要处理触发声音、停止声音、音量变化以及音调变化。正常情况下当写游戏的时候,声音更新会产生一些传往声音缓冲区的字节流,但是Android能够管理自己的声音,因而你的选择将是使用SoundPool或者MediaPlayer。它们都需要小心处理以免出错,但你要知道,因为一些底层实现细节,小型、低比特率的声音文件将带来最佳的性能和稳定性。
录像更新要考虑游戏的状态、角色的位置、分数、状态等等,并将一切画到屏幕上。如果使用主循环,你可能需要使用SurfaceView,并做一个“推”绘制。对于其他视图,视图本身能够调用绘制操作,主循环不必处理。SurfaceView每秒产生的帧数最多,最适合于一些有动画或屏幕上有运动部件的游戏。录像更新所要做的工作是获取游戏的状态,并及时地为这个状态绘制图像。其他的自动化操作最好由不同的更新任务来处理。
3D还是2D?
在开始写游戏之前,你要决定是做3D的还是2D的。2D游戏有一个低得多的学习曲线,一般更容易获得良好的性能。3D游戏需要更深入的数学技能,并且如果你不在意的话会有性能问题产生。如果你打算画比方框和圆圈更复杂的图形,还需要会使用3DStudio和Maya那样的建模工具。Android支持OpenGL用来3D编程,并且在OpenGL方面有很多很好的教程可供学习。
建立简单、高质量的方法
上手时,要确保你整个游戏不要就用一个庞大而冗长的方法。如果你遵循我上面描述的主循环模式,这将相当简单。每个你写的方法应当完成一个非常特定的任务,并且它就应该无差错地那样做。举例来说,如果你需要洗一副纸牌,你应该写一个“”的方法,并且该方法就应该只做这一件事。
这是一个适用于任何软件开发的编码实践,但对于游戏开发来说这尤为重要。在一个有状态的、实时的系统里,调试将变得非常困难。使你的方法尽量的小,一般的经验法则是每个方法有且仅有一个目的(译者注:完成且仅完成一个功能)。如果你要为一个场景用编程方式画一个背景,你可能需要一个叫做“”的方法。诸如此类的任务能够很快完成,因而你可以按照搭积木的方法来开发你的游戏,而你能够继续添加你要的功能,并且不会使得这一切难以理解。
最重要的是效率!
性能是任何游戏的主要问题。我们的目标是使得游戏的反应越快越好,看起来越流畅越好。某些方法如Canvas.drawLine比较慢。并且要将屏幕大小的位图画到主画布上,每一帧都是代价昂贵的。如何权衡对于达到最佳性能很有必要。确保管理好你的资源,使用技巧来以最少量的CPU资源完成你的任务。如果性能不好的话,即使是最好的游戏玩起来也没劲。人们一般对于游戏卡或者响应慢几乎难以容忍。
提示和技巧
看一下SDK中的示例LunarLander。它使用SurfaceView,这对于一个每秒需要处理最多帧的游戏来说是合适的。如果你要做3D,示例中有GLView可以处理3D显示的很多初始化工作。对LightRacer来说,我不得不优化把所有东西都画出来这种方法,否则帧率将会大大地降低。我只在视图初始化的时候把背景画进一个位图里一次。路径放在它们自己的位图里,随着车手的前进而更新。这两个位图在每一帧里都被画进主画布中去,车手画在顶端,到最后会有一个爆炸。这种技术使得游戏运行在一个可以玩的程度。
如果适用的话,使得你的位图的大小精确等于你打算画到屏幕上的大小,这也是个好的实践。这么做了以后就需要缩放,可以节省CPU资源。
在游戏中始终一致的位图配置(如RGBA8888)。这将会通过减少不同格式之间转换的时间来节省图形库的CPU时间。
如果你决定开发3D游戏但没有3D方面的知识,你需要挑选一两本3D游戏编程方面的书并学习线性代数。你最少要理解点积、叉积、向量、单元向量、法线、矩阵和变换。这方面我遇到的最好的书是叫《3D游戏编程和计算机图形学数学》。
声音文件要小而且低比特率。需要加载的越少,加载速度越快,游戏所需内存越少。
声音使用OGG文件,图片使用PNG文件。
确保释放所有媒体播放器,当Activity销毁时空出所有的资源。这能保证垃圾收集器清除了所有东西,也能保证在两次游戏开始之间没有内存泄露。
加入Android谷歌小组,寻求社区支持。这里有人可以在开发过程中给你帮助。
最重要的是,花时间测试再测试,确保每一小部分都如你所愿地工作。改善游戏是整个开发中最耗时最困难的部分。如果你匆匆将其推向市场,你很可能会使用户们失望,你会感到你的努力都白费了。你不可能使所有人都喜欢你写的东西,但你至少要尽量发布你最高质量的作品。
android开发SPP经典蓝牙
Android 开发SPP经典蓝牙。
1、传统蓝牙采用的是SPP(Serial Port Profile)协议进行数据传输。
2、SPP的UUID:00001101-0000-1000-8000-00805F9B34FB
3、手机一般以客户端的角色主动连接SPP协议设备
概念:
BluetoothAdapter:
本地蓝牙适配器,是所有蓝牙交互的入口,表示蓝牙设备自身的一个蓝牙适配器,整个系统只有一个蓝牙适配器,通过他可以发现其他蓝牙设备,查询绑定(配对)设备列表,使用MAC地址实例化BluetoothDevice以及创建BluetoothServerSocket用来侦听来自其他设备的通信。
myBluetoothAdapter = BluetoothAdapter.getDefaultAdapter();//获取默认的蓝牙Adapter
BluetoothDevice:
远程的蓝牙设备。
private static BluetoothDevice myDevice;
myDevice = myBluetoothAdapter.getRemoteDevice(BDAddr);//获取远程设备,通过蓝牙的MAC地址来获取一个远程对象
两种连接方式
BluetoothSocket
客户端:调用BluetoothDevice的createRfcommSocketToServiceRecord()可以获取该对象;调用connect()方法可以建立连接。
private static BluetoothSocket mySocket = null;
private static final UUID SPP_UUID = UUID.fromString("00001101-0000-1000-8000-00805F9B34FB");
Method m = myDevice.getClass().getMethod("createRfcommSocket", new Class[] {int.class});//由BluetoothDevice衍生出BluetoothSocket, createRfcommSocket来选择连接的服务和协议
mySocket = (BluetoothSocket) m.invoke(myDevice, 1);
BluetoothServerSocket:
服务端:通过BluetoothServerSocket对象可以创建BluetoothSocket对象,调用BluetoothServerSocket的accept()的方法可以得到改对象。
开发流程:
1:声明权限:
2:启动和关闭蓝牙
获取蓝牙适配器,使用close()接口可以关闭蓝牙适配器
myBluetoothAdapter = BluetoothAdapter.getDefaultAdapter();//获取默认的蓝牙Adapter
启动蓝牙
if (!blueadapter.isEnabled())
? ? ? ? //判断本机蓝牙是否打开
? ? ? ? {//如果没打开,则打开蓝牙
? ? ? ? blueadapter.enable();
? ? ? ? }
3.使用BlueAdatper搜索?
使用bluetoothAdapter搜索设备,bluetoothAdapter.startDiscovery()在搜索过程中,系统会发出三个广播信息:?
ACTION_DISCOVERY_START:开始搜索?
ACTION_DISCOVERY_FINISHED:搜索结束?
ACTION_FOUND:找到设备
if (bluetoothAdapter.isDiscovering()) {
? ? ? ? bluetoothAdapter.cancelDiscovery();//如果蓝牙设备未连接则取消搜索
? ? }
? ? bluetoothAdapter.startDiscovery();
}
4:(1)通过注册广播获取搜索到的设备。
IntentFilter intentFilter = new IntentFilter();
intentFilter.addAction(BluetoothDevice.ACTION_FOUND);//找到设备广播
intentFilter.addAction(BluetoothAdapter.ACTION_DISCOVERY_FINISHED);//搜索完成广播
registerReceiver(receiver, intentFilter);//注册广播接收器
// receiver
private final BroadcastReceiver receiver = new BroadcastReceiver(){
? ? @Override
? ? public void onReceive(Context context, Intent intent) {
? ? ? ? String action = intent.getAction();
? ? ? ? if (BluetoothDevice.ACTION_FOUND.equals(action)) {
? ? ? ? ? ? // find a device
? ? ? ? ? ? BluetoothDevice device = intent .getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);
? ? ? ? ? ? if (device.getBondState() != BluetoothDevice.BOND_BONDED) {
? ? ? ? ? ? ? ? //未配对设备
? ? ? ? ? ? ? ? newDeviceArrayAdapter.add(device.getName() + "\n" + device.getAddress());
? ? ? ? ? ? }else {
? ? ? ? ? ? ? ? //已经配对过的设备
? ? ? ? ? ? ? ? TextView tvPaired = (TextView)findViewById(R.id.tv_paired);
? ? ? ? ? ? ? ? tvPaired.setVisibility(View.VISIBLE);
? ? ? ? ? ? ? ? lvPairedDevices.setVisibility(View.VISIBLE);
? ? ? ? ? ? ? ? pairedDeviceArrayAdapter.add(device.getName() + "\n" + device.getAddress());
? ? ? ? ? ? }
? ? ? ? ? ? Log.i(TAG,"name:" + device.getName() + " address"+ device.getAddress());
? ? ? ? } else if (BluetoothAdapter.ACTION_DISCOVERY_FINISHED.equals(action){
? ? ? ? ? ? // search finish
? ? ? ? ? ? Log.i(TAG, "search finish!");
? ? ? ? }
? ? }
};
(2),直接得到当前的蓝牙设备后,就可用通过遍历pairedDevices?,得到当前手机已经配对过的蓝牙设备。
Set
pairedDevices = myBluetoothAdapter.getBondedDevices();//获取当前蓝牙设备
if (pairedDevices.size() <= 0) return false;
for (BluetoothDevice device : pairedDevices) {
? ? Map
map = new HashMap
();
? ? map.put("DeviceName", device.getName());
? ? map.put("BDAddress", device.getAddress());
? ? list.add(map);
5.建立连接
private static final UUID SPP_UUID = UUID.fromString("00001101-0000-1000-8000-00805F9B34FB");
Method m = myDevice.getClass().getMethod("createRfcommSocket", new Class[] {int.class});//由BluetoothDevice衍生出BluetoothSocket, createRfcommSocket来选择连接的服务和协议
mySocket = (BluetoothSocket) m.invoke(myDevice, 1);
mySocket.connect();//使用BluetoothSocket来连接设备
6.把得到的蓝牙设备给通过点击ListView选择设备。
listView.setOnItemClickListener(new ListView.OnItemClickListener() {
? ? public void onItemClick(AdapterView
arg0, View arg1, int arg2, long arg3) {
? ? ? ? SelectedBDAddress = list.get(arg2).get("BDAddress");
? ? ? ? if (((ListView) arg0).getTag() != null) {
? ? ? ? ? ? ((View) ((ListView) arg0).getTag()).setBackgroundDrawable(null);
? ? ? ? }
? ? ? ? ((ListView) arg0).setTag(arg1);
? ? ? ? arg1.setBackgroundColor(Color.BLUE);
? ? ? ? myDevice = myBluetoothAdapter.getRemoteDevice(SelectedBDAddress);
? ? }
});
7.客户端发送数据
当两个设备成功连接之后,双方都会有一个BluetoothSocket对象,这时,就可以在设备之间传送数据了。
? ? ? ?1.使用getOutputStream()方法来获取输出流来处理传输。
? ? ? ?2.调用write()。
os = socket.getOutputStream();//获取输出流
if (os != null) {//判断输出流是否为空
? ? os.write(message.getBytes("UTF-8"));
}
os.flush();//将输出流的数据强制提交
os.close();//关闭输出流
}
将输出流中的数据提交后,要记得关闭输出流,否则,可能会造成只能发送一次数据。
8.服务端接收数据
1.使用getInputStream()方法来获取输入流来处理传输。
? ? ? ?2.调用read()。
InputStream im=null;
im=bluetoothSocket.getInputStream();
byte buf[] = new byte[1024];
if (is != null) {
? ? is.read(buf, 0, buf.length);//读取发来的数据
? ? String message = new String(buf);//把发来的数据转化为String类型
? ? BuletoothMainActivity.UpdateRevMsg(message);//更新信息在显示文本框
? ? is.close();//关闭输入流
使用服务端接收数据时,要先从客户端向服务端发起连接,只有接收到连接请求之后,才会返回一个BluetoothSocket对象。有BluetoothSocket对象才能获取到输入流。