Android系统中的进程优先级由高到低
高优先级前台进程可见进程中优先级服务进程后台进程低优先级空进程
Android组件
组件是可以调用的基本功能模块,Android应用程序就是由组件组成的
Android系统有四个重要的组件,分别是Activity、Service、BroadcaseReceiver和ContentProvider
Activity是Android程序的呈现层,显示可视化的用户界面,Android应用程序可以包含一个或多个Activity,一般在程序启动后会呈现一个Activity。
Service用于没有用户界面,但需要长时间在后台运行的应用 BroadcaseReceiver是用来接受并响应广播消息的组件
ContentProvider是Android系统提供的一种标准的共享数据的机制,应用程序可以通过ContentProvider访问其他应用程序的私有数据,私有数据可以是存储在文件系统中的文件,也可以是SQLite中的数据库
Activity表现为四种状态,分别是活动状态、暂停状态、停止状态和非活动状态
Activity 事件的回调函数: protected void onStart(); protected void onRestart(); protected void onResume(); protected void onPause(); protected void onStop();
protected void onDestroy(); Activity:
123onRestoreInstanceState45onSaveInstanceState7onPause89onResumeonStartonCreateonStop6onRestartonDestroy活动生命周期可视生命周期全生命周期
Android系统提供了两种调试工具LogCat和DevTools,用于定位、分析及修复程序中出现的错误
LogCat程序调试原理
1.引入android.util.Log包
2.使用Log.v(),Log.d(),Log.i(),Log.w() 和 Log.e()五个函数在程序中设置“日志点” 3.当程序运行到“日志点”时,应用程序的日志信息便被发送到LogCat中 4.判断“日志点”信息与预期的内容是否一致
E.g. final static String TAG = \"LOGCAT\"; Log.v(TAG,\"Verbose\");
DevTools是用于调试和测试的工具,包括了一系列用户各种用途的小工具
Unit 5. Android 用户界面
常见的系统控件包括TextView、EditText、Button、ImageButton、Checkbox、RadioButton、
Spinner、ListView和TabHost
TextView:显示字符串,EditText是一个具有编辑功能的TextView 相应的XML文件:
android:layout_height=\"wrap_content\" android:text=\"TextView01\" >
Test.java:
TextView txv=(TextView)findViewByID(R.id.TextView01); txv.setText(\"User:\");
ImageButton:
将img1拷贝到/res/drawable文件夹下(R.java中自动更新) imageButton.setImageResource(R.drawable.img1); 按钮响应点击事件:添加点击事件的监听器
imageButton.setOnClickListener(new View.OnClickListener() {
public void onClick(View view)点击事件的回调函数 {
txv.setText(\"ImageButton按钮\"); } })
每个View仅可以注册一个点击事件的监听器,如果使用setOnClickListener()函数注册第二个点击事件的监听器,之前注册的监听器将被自动注销.
多个按钮注册到同一个点击事件的监听器上,代码如下:
Button.OnClickListener buttonListener = new Button.OnClickListener(){ @Override public void onClick(View v) { switch(v.getId()){ case R.id.Button01: textView.setText(\"Button按钮\"); return; case R.id.ImageButton01: textView.setText(\"ImageButton按钮\"); return; } }};
button.setOnClickListener(buttonListener);
imageButton.setOnClickListener(buttonListener); CheckBox和RadioButton:
怎样定义同组中的RadioButton? XML中:
Test.java中:
RadioButton radioButton1 =(RadioButton)findViewById(R.id.RadioButton01); RadioButton.OnClickListener rblistener=new RadioButton.OnClickListener() {
public void OnClick(View v) {
//process; } };
radioButton1.setOnClickListener(rblistener);
Spinner:(similar to ComboBox) Test.java:
Spinner spinner=(Spinner)findViewById(R.id.Spinner01); List ArrayAdapter this,android.R.layout.simple_spinner_item, list ); //数组适配器能够将界面控件和底层数据绑定在一起 adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item); spinner.setAdapter(adapter); ListView:(垂直显示的列表控件) ListView listv=(ListView)findViewById(R.id.ListView01); List ArrayAdapter (this, android.R.layout.simple_list_item_1, list ); listv.setAdapter(adapter); AdapterView.OnItemClickListener listvListener=new AdapterView.OnItemClickListener(){ public void onItemClick(AdapterView> arg0, View arg1, int arg2, long arg3) { String msg =””; textView.setText(msg); }}; } TabHost:实现多个分页之间的快速切换(Similar to TabControl) 有几个tabpage就建立几个xml Test.java: public class TabDemo extends TabActivity { //普通的都是 extends Activity // 与以往继承Activity不同,TabActivity支持内嵌多个Activity或View public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); TabHost tabHost = getTabHost(); //获得Tab标签页的容器 LayoutInflater.from(this).inflate(R.layout.tab1, tabHost.getTabContentView(),true); //LayoutInflater将tab1.xml文件中的布局转换为Tab标签页可以使用的View对象 LayoutInflater.from(this).inflate(R.layout.tab2,tabHost.getTabContentView(),true); LayoutInflater.from(this).inflate(R.layout.tab3,tabHost.getTabContentView(),true); tabHost.addTab(tabHost.newTabSpec(\"TAB1\") .setIndicator(\"线性布局\").setContent(R.id.layout01)); //使用addTab()函数在tabHost上添加了第1个标识为\"TAB1\"的分页 tabHost.addTab(tabHost.newTabSpec(\"TAB2\") .setIndicator(\"绝对布局\").setContent(R.id.layout02)); tabHost.addTab(tabHost.newTabSpec(\"TAB3\") .setIndicator(\"相对布局\").setContent(R.id.layout03)); } 界面布局: 声明Android程序的界面布局有两种方法: 使用XML文件描述界面布局 在程序运行时动态添加或修改界面布局 用户既可以独立使用任何一种声明界面布局的方式,也可以同时使用两种方式 使用XML文件声明界面布局的特点: 将程序的表现层和控制层分离 在后期修改用户界面时,无需更改程序的源代码 可视化界面加快设计 线性布局LinearLayout: 如果垂直排列,则每行仅包含一个界面元素 如果水平排列,则每列仅包含一个界面元素 框架布局FrameLayout 表格布局TableLayout: 添加行为TableRow 相对布局(RelativeLayout): e.g. android:layout_below=\"@id/label\" android:layout_alignParentRight=\"true\" android:layout_toLeftOf=\"@id/cancel\" android:layout_alignTop=\"@id/cancel\"//声明与ID为cancel的元素在相同的水平位置 绝对布局(AbsoluteLayout) android:layout_x=\"40dip\" android:layout_y=\"40dip\" 菜单: Android系统支持三种菜单: 选项菜单(Option Menu) 子菜单(Submenu) 快捷菜单(Context Menu) 选项菜单 分为图标菜单(Icon Menu)& 扩展菜单(Expanded Menu)。 图标菜单能同时显示文字和图标的菜单,最多支持6个子项,但不支持单选框和复选框 扩展菜单是在图标菜单子项多余6个时才出现,是垂直的列表型仅有文字菜单 重载Activity的onCreateOptionMenu()函数,才能在Android应用程序中使用选项菜单 public boolean onCreateOptionsMenu(Menu menu){ menu.add(0,MENU_DOWNLOAD,0,\"下载设置\");//MENU_DOWNLOAD=1 //MenuItem android.view.Menu.add(int groupId, int itemId, int order, CharSequence title) menu.add(0,MENU_DOWNLOAD,0,\"下载设置\").setIcon(R.drawable.download); .setShortcut(’,’d’);//快捷键 return true; } 重载onPrepareOptionsMenu()函数,能够动态的添加、删除菜单子项,或修改菜单的标题、图标和可见性等内容 E.g. 下面的代码是在用户每次打开选项菜单时,在菜单子项中显示用户打开该子项的次数 public boolean onPrepareOptionsMenu(Menu menu){ MenuItem uploadItem = menu.findItem(MENU_UPLOAD); uploadItem.setTitle(\"上传设置:\" +String.valueOf(MenuUploadCounter)); return true; } onOptionsItemSelected ()函数能够处理菜单选择事件,且该函数在每次点击菜单子项时都会被调用 public boolean onOptionsItemSelected(MenuItem item){ switch(item.getItemId()){//获取到被选择菜单子项的ID case MENU_DOWNLOAD: MenuDownlaodCounter++; return true; case MENU_UPLOAD: MenuUploadCounter++; return true; } return false; } 子菜单 子菜单不支持嵌套,添加是使用addSubMenu()函数实现 SubMenu uploadMenu = (SubMenu) menu.addSubMenu(0,MENU_UPLOAD,1,\"上传设置\") .setIcon(R.drawable.upload); uploadMenu.setHeaderIcon(R.drawable.upload); uploadMenu.setHeaderTitle(\"上传参数设置\"); uploadMenu.add(0,SUB_MENU_UPLOAD_A,0,\"上传参数A\"); uploadMenu.add(0,SUB_MENU_UPLOAD_B,0,\"上传参数B\"); 快捷菜单 选项菜单中的onCreateOptionsMenu()函数仅在选项菜单第一次启动时被调用一次 快捷菜单的onCreateContextMenu()函数每次启动时都会被调用一次 菜单选择事件的处理需要重载onContextItemSelected()函数,该函数在用户选择快捷菜单中的菜单子项后被调用,与onOptionsItemSelected ()函数的使用方法基本相同 菜单在XML中的实现: 界面事件 按键事件将传递给onKey()函数进行处理 触摸事件将传递给onTouch()函数进行处理 是否继续传递事件给其他处理函数是由事件监听器处理函数的返回值决定的,取决于监听处理函数返回值。 按键事件: entryText.setOnKeyListener(new OnKeyListener(){ @Override public boolean onKey(View view, int keyCode, KeyEvent keyEvent) { int metaState = keyEvent.getMetaState(); int unicodeChar = keyEvent.getUnicodeChar(); String msg = \"\"; msg +=\"按键动作:\" + String.valueOf(keyEvent.getAction())+\"\\n\"; msg +=\"按键代码:\" + String.valueOf(keyCode)+\"\\n\"; msg +=\"按键字符:\" + (char)unicodeChar+\"\\n\"; msg +=\"UNICODE:\" + String.valueOf(unicodeChar)+\"\\n\"; msg +=\"重复次数:\" + String.valueOf(keyEvent.getRepeatCount())+\"\\n\"; msg +=\"功能键状态:\" + String.valueOf(metaState)+\"\\n\"; msg +=\"硬件编码:\" + String.valueOf(keyEvent.getScanCode())+\"\\n\"; msg +=\"按键标志:\" + String.valueOf(keyEvent.getFlags())+\"\\n\"; labelView.setText(msg); if (checkBox.isChecked()) return true; else return false; } 触摸事件: 重载onTouch ()函数 touchView.setOnTouchListener(new View.OnTouchListener(){ @Override public boolean onTouch(View v, MotionEvent event) { //过程代码„„ return true/false; }) TextView touchView = (TextView)findViewById(R.id.touch_area); touchView.setOnTouchListener(new View.OnTouchListener(){ @Override public boolean onTouch(View v, MotionEvent event) { int action = event.getAction(); switch (action) { case (MotionEvent.ACTION_DOWN): ...break; case (MotionEvent.ACTION_UP): ...break; case (MotionEvent.ACTION_MOVE): ...break; } return true; } }); Unit6 组建通信与广播消息 简述Intent的定义和用途。 Define: Intent可称为一个在不同组件之间传递的消息,这个消息在到达接收组件后, 接收组件会执行相关的动作 Intent的用途: 1. 启动Activity和Service 2. 在Android系统上发布广播消息 Intent可以实现不同Activity之间的切换和数据传递 启动Activity方式: 显式启动,必须在Intent中指明启动的Activity所在的类 Intent intent = new Intent(IntentDemo.this, ActivityToStart.class); startActivity(intent); AndroidManifest.xml中注册这两个Activity: 隐式启动, Android系统根据Intent的动作和数据来决定启动哪一个Activity,也就 是说在隐式启动时,Intent中只包含需要执行的动作和所包含的数据,而无需指明具体启动哪一个Activity,选择权有Android系统和最终用户来决定 Intent intent = new Intent(Intent.ACTION_VIEW, Uri.parse(\"http://www.google.com\")); startActivity(intent); 如果需要将子Activity的部分信息返回给父Activity(先启动的),则可以使用 Sub-Activity的方式去启动子Activity(后启动的) E.g. 父Activity: setContentView(R.layout.main); btn1.setOnClickListener(new OnClickListener()//注册子启动Intent方式到btn1 { Public void onClick(View v) { Intent intent = new Intent(ActivityComunication.this,SubActivity1.class); //第一个参数为当前应用程序上下文 startActivityForResult(intent,Sub_index1); } }) Protected void onActivityResult(int requestCode, int resultCode, Intent data) //当子Activity关闭时,启动它的父Activity的onActivityResult()函数将被调用; { super.onActivityResult(requestCode,resultCode,data); switch(requestCode){//检测是哪个Intent发回来的 case Sub_index1: if(resultCode==RESULT_OK) { Uri uriData=data.getData(); textView.setText(uriData.toString()); } break; case Sub_index2: break; } SubActivity1.java中: setContentView(R.layout.subactivity1); btnOK.setOnClickListener(new OnClickListener() { public void onClick(View view){ String uriString = editText.getText().toString(); Uri data = Uri.parse(uriString); Intent result = new Intent(null, data); setResult(RESULT_OK, result); //将Intent作为返回值,RESUIT_OK作为结果码,传递给父Activity finish(); //关闭当前的子Activity } SubActivity2.java中: btnReturn.setOnClickListener(new OnClickListener(){ public void onClick(View view){ setResult(RESULT_CANCELED, null); finish(); } }); 简述Intent过滤器的定义和功能。 Define: Intent过滤器是一种根据Intent中的动作(Action)、类别(Categorie)和数据(Data)等内容,对适合接收该Intent的组件进行匹配和筛选的机制 Function: Intent过滤器可以匹配数据类型、路径和协议,还包括可以用来确定多个匹配项顺序的优先级(Priority) 应用程序的Activity组件、Service组件和BroadcastReceiver都可以注册Intent过滤器,则这些组件在特定的数据格式上就可以产生相应的动作 3.简述Intent解析的匹配规则。 Intent到Intent过滤器的映射过程称为“Intent解析” Intent解析可以在所有的组件中,找到一个可以与请求的Intent达成最佳匹配的Intent过滤器 Intent解析的匹配规则: 1. Android系统把所有应用程序包中的Intent过滤器集合在一起,形成一个完整的Intent过滤器列表 2. 在Intent与Intent过滤器进行匹配时,Android系统会将列表中所有Intent过滤器的“动作”和“类别”与Intent进行匹配,任何不匹配的Intent过滤器都将被过滤掉。 3. 把Intent数据Uri的每个子部与Intent过滤器的标签中的属性进行匹配. 4. 如果Intent过滤器的匹配结果多于一个,则可以根据在 Unit8. 数据存储与访问 简单存储 SharedPreferences是一种轻量级的数据保存方式 通过SharedPreferences可以将NVP(Name/Value Pair,名称/值对)保存在Android的文件系统中,而且SharedPreferences完全屏蔽的对文件系统的操作过程 SharedPreferences支持三种访问模式:私有、全局读、全局写 读写都用getSharedPreferences()函数 public static final String PREFERENCE_NAME = \"SaveSetting\"; public static int MODE = Context.MODE_WORLD_READABLE + Context.MODE_WORLD_WRITEABLE;//读&写 SharedPreferences sharedPreferences = getSharedPreferences(PREFERENCE_NAME, MODE); //写 SharedPreferences.Editor editor = sharedPreferences.edit(); editor.putString(\"Name\editor.putInt(\"Age\editor.putFloat(\"Height\editor.commit(); //读 String name = sharedPreferences.getString(\"Name\ int age = sharedPreferences.getInt(\"Age\ float height = sharedPreferences.getFloat(\"Height\//第二个值是缺省值 SharedPreferences文件就保存在/data/data/ 文件存储 内部存储 1. openFileOutput() 2. openFileInput() 外部存储 Android的外部存储设备指的是SD卡(Secure Digital Memory Card),是一种广泛使用于数码设备上的记忆卡 SD卡使用的是FAT(File Allocation Table)的文件系统,不支持访问模式和权限控制 使用 将原始格式文件和XML文件分别存放在/res/raw和/res/xml目录下,供应用程序在运行时进行访问 E.g. 读取/res/raw/raw_file.txt文件,并将内容显示在界面上 inputStream = resources.openRawResource(R.raw.raw_file); byte[] reader = new byte[inputStream.available()]; while (inputStream.read(reader) != -1){ displayView.setText(new String(reader,\"utf-8\")); }; E.g. 读取XML格式文件 XmlPullParser parser = resources.getXml(R.xml.people); String msg = \"\"; try { while (parser.next() != XmlPullParser.END_DOCUMENT) { String people = parser.getName(); String name = null; String age = null; String height = null; if ((people != null) && people.equals(\"person\")) { int count = parser.getAttributeCount(); for (int i = 0; i < count; i++) { String attrName = parser.getAttributeName(i); String attrValue = parser.getAttributeValue(i); if ((attrName != null) && attrName.equals(\"name\")) { name = attrValue; } else if ((attrName != null) && attrName.equals(\"age\")) { age = attrValue; } else if ((attrName != null) && attrName.equals(\"height\")) { height = attrValue; } } if ((name != null) && (age != null) && (height != null)) { msg += \"姓名:\"+name+\",年龄:\"+age+\",身高:\"+height+\"\\n\"; 数据库存储---SQLiteDatabase 代码建库: 重载onCreate() & onUpgrade(), 不由程序开发人员调用,由SQLiteOpenHelper类决定何时调用。 SQLiteDatabase提供了SQLiteOpenHelper类提供对数据库的操作(就不用手写sql语句了) 在Android系统中,数据库查询结果的返回值并不是数据集合的完整拷贝,而是返回数据集的指针,这个指针就是Cursor类 private People[] ConvertToPeople(Cursor cursor){ int resultCounts = cursor.getCount(); if (resultCounts == 0 || !cursor.moveToFirst()){ return null; } People[] peoples = new People[resultCounts]; for (int i = 0 ; i peoples[i].ID = cursor.getInt(0); peoples[i].Name = cursor.getString(cursor.getColumnIndex(KEY_NAME)); peoples[i].Age = cursor.getInt(cursor.getColumnIndex(KEY_AGE)); peoples[i].Height = cursor.getFloat(cursor.getColumnIndex(KEY_HEIGHT)); cursor.moveToNext(); } return peoples; } 数据分享ContentProvider ContentProvider(数据提供者)是在应用程序间共享数据的一种接口机制 调用者不能够直接调用ContentProvider的接口函数,而需要使用ContentResolver对象,通过URI间接调用ContentProvider。 在使用者看来,数据提供者通过ContentProvider提供了一组标准的数据操作接口,却无法得知数据提供者的数据存储方法。 URI是通用资源标志符(Uniform Resource Identifier),用来定位任何远程或本地的可用资源 程序开发人员通过继承ContentProvider类可以创建一个新的数据提供者,过程可以分为三步: 继承ContentProvider,并重载六个函数(增改删查之类的) 声明CONTENT_URI,实现UriMatcher(判断URI是单条数据or多条数据) 注册ContentProvider(在AndroidManifest.xml文件中进行注册授权名) 因篇幅问题不能全部显示,请点此查看更多更全内容