必须总是activity中内嵌fragment对象


service运行在后台,运行时间不限,不提供界面


分为本地service和远程service。


不能在service主线程执行好事操作


所有的服务都在抽象类 android.app.Service 的子类中,而 android.app.Service 类则是


Context 的间接子类。



一、用户界面范例


1.自定义窗口


系统主题或自定义主题都必须在清单文件中设置。


所有通过 Activity.requestWindowFeature()方法修改窗口特性的请求都必须在调用


Activity.setContentView()之前完成。在此之后的所有改动都不会生效。


//设置自定义标题的布局资源


getWindow().setFeatureInt(Window.FEATURE_CUSTOM_TITLE,R.layout.custom_title);


2.动态开关系统的UI控件


夜间模式 API Level 11


任何视图中调用 setSystemUiVisibility()


即可。而想要恢复到默认模式,需要以同样的方式调用 SYSTEM_UI_FLAG_VISIBLE。通



XML 布局文件中的根元素是 LayoutInflater. inflate()返回的 View 元素


3.屏幕分辨率


低分辨率(ldpi): 120 dpi 尺寸是 mdpi 的 75%


中分辨率(mdpi): 160 dpi 原始的图片尺寸


高分辨率(hdpi): 240 dpi 尺寸是 mdpi 的 150%


超高分辨率(xhdpi): 320 dpi (API Level 8 新增) 尺寸是 mdpi 的 200%


超级高(xxhdpi): 480 dpi (API Level 16 新增) 尺寸是 mdpi 的 300%


4.锁定Activity方向


android:screenOrientation="portrait"或 android:screenOrientation="landscape"


如果为 Activity 设置了 android:screenOrientation="behind", Activity 就会跟 Activity 栈中前一个 Activity 的方向保持一致


android:configChanges="orientation|keyboardHidden" />


在一条赋值语句中可以注册多种变动,用“ |”符号将它们分开即可。


5.弹出菜单


也可以调用 Activity.openContextMenu()来触发任意视图的 ContextMenu,传入之前注


册的视图即可。


程序清单 2-29 自定义布局的 AlertDialog


public class CustomItemActivity extends Activity


implements DialogInterface.OnClickListener, View.OnClickListener {


private static final String[] ZONES = {"Pacific Time", "Mountain Time",


"Central Time", "Eastern Time", "Atlantic Time"};


private static final String[] OFFSETS =


{"GMT-08:00", "GMT-07:00", "GMT-06:00", "GMT-05:00", "GMT-04:00"};


Button mButton;


AlertDialog mActions;


@Override


protected void onCreate(Bundle savedInstanceState) {


super.onCreate(savedInstanceState);


setTitle("Activity");


mButton = new Button(this);


mButton.setText("Click for Time Zones");


mButton.setOnClickListener(this);


ArrayAdapter<String> adapter = new ArrayAdapter<String>(this,


R.layout.list_item) {


@Override


public View getView(int position, View convertView, ViewGroup parent) {


View row = convertView;


if(row == null) {


row = getLayoutInflater().inflate(R.layout.list_item,


parent, false);


}

TextView name = (TextView) row.findViewById(R.id.text_name);


TextView detai

l = (TextView) row.findViewById(R.id.text_detail); 

 

  name.setText(ZONES[position]); 

 

  detail.setText(OFFSETS[position]); 

 

  return row; 

 

  } 

 

  @Override 

 

  public int getCount() { 

 

  return ZONES.length; 

 

  }}; 

 

  AlertDialog.Builder builder = new AlertDialog.Builder(this); 

 

  builder.setTitle("Select Time Zone"); 

 

  builder.setAdapter(adapter, this); 

 

  //这里的取消动作只会让对话框消失,但在用户单击 Cancel 按钮时,也可以添加一个 

 

  //监听器来处理一些其他的操作 

 

  builder.setNegativeButton("Cancel", null); 

 

  mActions = builder.create(); 

 

  setContentView(mButton); 

 

  } 

 

  //这里处理列表的选择事件 

 

  @Override 

 

  public void onClick(DialogInterface dialog, int which) { 

 

  String selected = ZONES[which]; 

 

  mButton.setText(selected); 

 

  } 

 

  //这里处理 Button 的单击事件(弹出对话框) 

 

  @Override 

 

  public void onClick(View v) { 

 

  mActions.show(); 

 

  } 

 

  }


6.模拟home键


Intent intent = new Intent(Intent.ACTION_MAIN); 

 

  intent.addCategory(Intent.CATEGORY_HOME); 

 

  startActivity(intent);


7.TextView


SDK 中有一些很方便的预定义的用于格式化文本输入的 TextWatcher 实例


8.动画


Android SDK的AnimationUtils 类加载


滑入和渐显AnimationUtils.makeInAnimation()用布尔参数决定滑入的方向是左侧还是右侧向上


滑入和渐显 AnimationUtils.makeInChildBottomAnimation() 视图总是从屏幕的底部向上滑入


滑出和渐隐 AnimationUtils.makeOutAnimation() 用布尔参数决定滑入的方向是左侧还是右侧


渐隐 AnimationUtils.loadAnimation() 将 int 参数设为 android.R.anim.fade_out


渐显 AnimationUtils.loadAnimation() 将 int 参数设为 android.R.anim.fade_in


AlphaAnimation 以动画的定时改变视图的透明度。


RotateAnimation 以动画的形式改变视图的旋转角度。中心点是可配置的,默认是左上角。


ScaleAnimation 以动画的形式改变视图的缩放比例(大小)。中心点是默认是左上角。


TranslateAnimation 以动画的形式改变视图的位置。


动画视图 ViewPropertyAnimator


ObjectAnimator


在 XML 中用<shape>标签定义 Drawable 时,实际上是创建了一个 GradientDrawable


对象。对象的形状可以是矩形、椭圆、线条或圆圈,最常见的背景形状是矩形。具体来说,


在使用矩形时,可以用下面这些参数定义形状:


● 角半径 定义 4 个角的半径,或是分别定义各个角的半径。


● 渐变 线性、放射或 sweep 渐变。两个或三个颜色值。方向可以是 45°的任何倍数(0 就是从左到右, 90 就是从下到上,以此类推)。


● 固定颜色 用一种颜色填充形状。 如果同时定义了渐变的话,效果会受影响。


● 边线 对象形状的边界。 定义宽度和颜色。


● 大小和 padding


XML 中颜色的种类限制是 3 种,但是 GradientDrawable 的构造函数中的颜色参数是一个整型数组int[],传递多少颜色都可以。


Activity 间的过渡动画, 可以使用 overridePendingTransition()


Fragment 的过渡动画,可以使用 onCreateAnimation()或 onCreateAnimator()


通过调用 setCustomAnimations()覆写单个 FragmentTransaction 的


过渡动画。


setCustomAnimations()必须在 add()、 replace()和其他动作方法之前调用,否则动画将不


会运行。



9.圆角遮罩


首先在 Canvas 中根据所需的圆角半径创建一个圆角矩形,然后以 PorterDuff.Mode.SRC_IN 为画笔在同一个 Canvas 上绘制源图,得到的就是带圆角的源图。


10.Dialog


呈现给用户的界面需要在旋转过程中保持状态,始终处于最前端,更好的办法是


使用 Activity。这样就可以通过各种生命周期回调方法来保存和读取状态。


11.自定义Enter键


android:imeOptions


actionUnspecified:默认值,根据设备的情况显示动作。


actionGo:在 Enter 键上显示 Go。


ActionSearch:在 Enter 键上显示 Search。


actionSend:在 Enter 键上显示 Send。


antionNext:在 Enter 键上显示 Next。


actionDone:在 Enter 键上显示 Done。


自定义用户按下按键时所触发的动作。重


载动作的默认行为需要给相应的视图加上 TextView.OnEditorActionListener。


用 InputMethodManager.hideSoftInputFromWindow()方法可以让输入法管理器隐藏可见


的输入法。


12.listview


ExpandableListView 控件及其适配器可以处理分节列表中的二维数据结构。


13.getPageWidth()。


这个方法允许你在每个位置上设置图片页面大小相对于 ViewPager 页面大小的百分比。默


认值为 1,前面的示例也没有改变该默认值。但如果要一次显示几个页面,可以通过调整


这个方法的返回值来实现




二、显示web信息


1.通过url显示的应用


访问XX网站


通过web服务器显示实时更新的页面,可以动态更新


显示大资源图片,通过缩放来交互


2.显示本地资源


可用assets目录存储本地资源 file:///android_asset<resource path>


可显示string资源或变量中的原始html代码


3.通过WebviewClient拦截事件


WebViewClient.shouldOverrideUrlLoading()回调来拦截和监控用户的 Activity


shouldOverrideUrlLoading()会根据传入的 URL 决定是否要在 WebView 中加


载内容, 防止用户离开想要展示 的网站。


WebView.addJavascriptInterface()会为 JavaScript 绑定一个 Java 对象,这样就可以在


WebView 中调用 Java 的方法。会存在javascript注入问题


4.下载图片


完全在后台下载使用DownloadManager API service 支持断点续传


DownloadManager.Request 请求对象,它代表了下载的内容


Request.setAllowedNetworkTypes():指定下载所使用的网络类型


Request.setAllowedOverRoaming():设定当设备处于漫游模式时是否要下载。


Request.setDescription():设置下载在系统通知栏中显示的描述。


Request.setDestinationInExternalFilesDir():设置目标位置为外部存储器中的一个隐藏目录


Request.setDestinationInExternalPublicDir():设置目标位置为外部存储器中的一公共目录


Request.setDestinationUri():设置目标位置为位于外部存储器中一个文件 Uri


三。通信


1.接收短信


注册一个 BroadcastReceiver 来监听收到的消息,并在 onReceive()中处理它们。当收到一条短信时,操作系统会发送一个 action 值为 android.provider.Telephony.SMS_RECEIVED


的广播 Intent。应用程序则可以注册一个 BroadcastReceiver 过滤这个 Intent 并处理收到的


数据。接收短信需要在 manifest 中声明 android.permission.RECEIVE_SMS 权限。


2.蓝牙通信


蓝牙上的连接是通过发现可用的“服务”,并通过一个 128 位的 UUID 连接到相应的服务。


android.permission.BLUETOOTH 权限。另外,想要改变蓝牙的可发现性以及启用/禁用蓝牙适配器,还要在 manifest 中声明android.permission.BLUETOOTH_ADMIN 权限


3.查询网络连接状态


通过 ConnectivityManager 监控设备的网络连接状态。


public boolean isNetworkReachable() { 

 

  ConnectivityManager mManage = (ConnectivityManager)context.getSystemService(Context.CONNECTIVITY_SERVICE); 

 

  NetworkInfo current = mManager.getActiveNetworkInfo(); 

 

  if(current == null) { 

 

  return false; 

 

  } 

 

  return (current.getState() == NetworkInfo.State.CONNECTED); 

 

  }


判断链接类型


return (current.getType() == ConnectivityManager.TYPE_WIFI);


4.使用NFC传输数据


根据想要推送内容的大小,有两种机制可以用来在两个设备间 Beam 数据。


第一种. 使用前台 Push 进行 Beam。如果使用 NFC 在设备间发送简单的内容, 可以使用前台推送机制来创建一个 NfcMessage,它包含了一个或多个 NfcRecord 实例。


第二种,Android Application Record


5.使用 Beam 来发送大型图片文件


6.USB链接


<uses-feature android:name="android.hardware.usb.host" />


端点: USB 设备的最小构件。应用程序最终就是通过连接端点发送和接收数据的。主要分4 种类型:


y 控制传输:用于配置和状态命令。每个设备至少一个控制端点,即“端点 0”,不会关联任何接口。


y 中断传输:用于小量的、高优先级的控制命令。


y 批量传输:用于传输大数据。通常都是双向成对出现的(1 IN 和 1 OUT)。


同步传输:用于实时数据传输,如音频。撰写本书时最新的 Android SDK 还不支持这个功能。




● 配置:一个或多个接口的集合。 USB 强制规定一个设备在某一特定时间只能有一个配置是激活的。事实上,多数设备也就只有一个配置,并把它作为设备的操作模式



四、设备硬件交互


1.定位


需要注意设备的电量以及尊重用户的意愿


GPS 返回的信息更加精确(误差为几米),但需要的时间更长并且更耗电,


而网络位置通常精确到几千米,但速度更快而且省电


android.permission.ACCESS_COARSE_LOCATION 或


android.permission.ACCESS_FINE_LOCATION 权限


(1) 判断所需的位置信息源是否可用。如果不可用的话,决定是要求用户启用它还是


尝试其他的信息源。


(2) 用适当的最小距离和更新时间间隔注册设备位置的变化情况。


(3) 当不需要时,及时取消对设备位置变化情况的注册,以节约电量。


2.地图位置


<uses-library android:name="com.google.android.maps"></uses-library>

百度、高德、谷歌


3.拍摄照片和视频


将保存图片的文件位置指定为设备的外部存储器指定 android.permission.


WRITE_EXTERNAL_STORAGE 权限。


在摄像头不用时及时调用Camera.release()方法在摄像头不用时及时调用Camera.release()方法


录音


private void resetRecorder() { 

 

  //告诉录音机将使用设备的麦克作为音频输入源(AudioSource.MIC) 

 

  recorder.setAudioSource(MediaRecorder.AudioSource.MIC); 

 

  recorder.setOutputFormat(MediaRecorder.OutputFormat.THREE_GPP); 

 

  recorder.setAudioEncoder(MediaRecorder.AudioEncoder.DEFAULT); 

 

  recorder.setOutputFile(path.getAbsolutePath()); 

 

  try { 

 

  recorder.prepare(); 

 

  } catch (Exception e) { 

 

  e.printStackTrace(); 

 

  } 

 

  }

通过 android.speech 包中的类可以使用 Android 设备中内置的语音识别技术。


4.传感器


使用 SensorManager 接收来自于加速度计传感器持续的反馈数据


registerListener()的最后一个参数定义了更新频率。这里选择的是 SENSOR_DELAY_UI,它是接收更新的最快频率,每次更新都会直接修改 UI。


每当传感器有新值更新,都会用 SensorEven 值一起调用已注册监听器的 onSensorChanged()方法。这个 SensorEvent 值包含了 X/Y/Z 轴上的加速度值。


罗盘传感器


设备的磁场传感器和加速度计一起确定用户面向的方向


使用 SensorManager 的 getOrientation()得到用户在地球上的方向


5.从媒体内容得到截图的缩略图或其他元数据


MediaMetadataRetriever 读取媒体文件并返回有用的信息,可以读取和跟踪专辑或艺术家数据、或者内容数据本身,抓取该帧的截图



四。数据持久化


1.存储、修改和显示用户设置及应用设置


PreferenceActivity 和 XML Preference 文件


2.读写文件


内部存储


受保护的用于读写文件数据的目录空间。


外部存储


外部挂载的用于读写文件数据的空间。


API Level 4 以上需要 WRITE_EXTERNAL_STORAGE 权限。通常都是设备的 SD 卡。


Assets


APK 中只读的受保护空间。用于放置不能/不应该被编译的本地资源。


3.分享数据


ContentProvider作为应用程序数据对外的接口,可以向外部请求暴露任何类型的应用程序数据,包括应用程序各种资源(包括 assets 下的资源)



五。与系统交互


1.通知


通过所有的系统控件,如 Service、 BroadcastReceiver 或者 Activity,都可以将一个通


知发送到 NotificationManager。


Notification.Style展示更多的通知样式


2.创建粘性操作


IntentService 会将要执行的任务(用 Intent表示)放到队列中,然后逐个处理每个请求,全部处理完成后会终止自己。


3.启用其他应用程序


a。读取PDF文件


intent = new Intent(Intent.ACTION_VIEW);


intent.setDataAndType(file, "application/pdf");


b、与好友分享内容


Intent intent = new Intent(Intent.ACTION_SEND);


intent.setType("text/plain");


intent.putExtra(Intent.EXTRA_TEXT, update);


startActivity(Intent.createChooser(intent, "Share..."));


c。ShareActionProvider分享内容


根据用户使用习惯,频繁使用的选项会排到列表的最上方


<menu xmlns:android="http://schemas.android.com/apk/res/android">


<item android:id="@+id/menu_share"


android:showAsAction="ifRoom"


android:title="Share"


android:actionProviderClass="android.widget.ShareActionProvider"/>


</menu>


MenuItem item = menu.findItem(R.id.menu_share);


ShareActionProvider provider = (ShareActionProvider) item.getActionProvider();


4.启动系统应用程序


a。浏览器


pageIntent.setAction(Intent.ACTION_VIEW);


pageIntent.setData(Uri.parse(“ http://WEB_ADDRESS_TO_VIEW” ));


b。电话拨号器


dialIntent.setAction(Intent.ACTION_DIAL);


dialIntent.setData(Uri.Parse(“ tel:8885551234” );


c。地图


mapIntent.setAction(Intent.ACTION_VIEW);


mapIntent.setData(Uri.parse(“ geo:latitude,longitude” ));


d。电子邮件


mailIntent.setAction(Intent.ACTION_SEND);


mailIntent.setType(“ message/rfc822” );


mailIntent.putExtra(Intent.EXTRA_EMAIL, new String[] {"recipient@gmail.com"}); 收件人


mailIntent.putExtra(Intent.EXTRA_CC, new String[] {"carbon@gmail.com"}); 抄送


mailIntent.putExtra(Intent.EXTRA_BCC, new String[] {"blind@gmail.com"}); 密件抄送


mailIntent.putExtra(Intent.EXTRA_SUBJECT, "Email Subject");


mailIntent.putExtra(Intent.EXTRA_TEXT, "Body Text");


mailIntent.putExtra(Intent.EXTRA_STREAM, URI_TO_FILE); 附件


e、短消息


smsIntent.setAction(Intent.ACTION_VIEW);


smsIntent.setType(“ vnd.android-dir/mms-sms” );


smsIntent.putExtra(“ address” , “ 8885551234” );


smsIntent.putExtra(“ sms_body” , “ Body Text” );


f。联系人选择器


pickIntent.setAction(Intent.ACTION_PICK);


pickIntent.setData(URI_TO_CONTACT_TABLE);


g。Google Play


marketIntent.setAction(Intent.ACTION_VIEW);


marketIntent.setData(Uri.parse(“ market://details?id=PACKAGE_NAME_HERE” ));



六。Android NDK和Renderscript


七。应用程序设计指南


1.设计经过滤的应用程序


2.设计高性能的应用程序


优化代码结构、少创建对象、减少浮点运算、使用 System.arraycopy()复制、


使用扩充版的循环(比如 for (Strings: strings) {})


3.设计快速响应的应用程序


注意使用线程


4.设计无缝衔接的应用程序


不要丢失数据,不要提供原始数据,发送通知、用线程执行长时间操作、避免ANR、扩展系统主题、设计使用多种分辨率的用户界面、注意网络判断、不要指定键盘布局、节约用电。


5.设计安全的应用程序



部分Demo代码地址 https://github.com/beibeiMary/AndroidDevelopment-paradigmDemo.git/