




已阅读5页,还剩63页未读, 继续免费阅读
版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领
文档简介
目录 11. 入门实例剖析122.在测试时,如何实现一个提示83.可以使用AlertDialog.Builder 才产生一个提示框.94.menu 的用法.101. 简单的代码102. menu实现的两种方法105.Activity 的切换(含Bundle传值)141. 代码142. 详解:156.AndroidUILayout191. AbsoluteLayout197. Tab以及 HostTab操作208. List (图片/按钮/标题/文本)26LIST例一27LIST例二36LIST例三409. 调用浏览器 载入某网址4310.监控应用程序包的安装&删除43方法一:43方法二:4611. 使用Toast输出一个字符串5212. 把一个字符串写进文件5213. 把文件内容读出到一个字符串5414. 调用Android installer 安装和卸载程序5515. 结束某个进程5516. 设置默认来电铃声5617. 开机自启动5718. 线程与子线程58handlerMessage实例5819. Service601. 什么是Service602. 如何使用Service603. Service的生命周期66附) 常用界面截图:67提示167提示268菜单681. 入门实例剖析1开卷语俗话说,“熟读唐诗三百首,不会作诗也会吟”。最近收集了很多Android的示例代码,从这些代码的阅读和实验中学习到很多知识,从而产生写这个系列的打算,目标就是一步步跟着实例进行动手实作,真正从“做”中体会和学习Android开发。 本文目标是Android自带的一个范例程序:记事本, 预备知识搭建开发环境,尝试编写”Hello World”,了解Android的基本概念,熟悉Android的API(官方文档中都有,不赘述)。程序截图先来简单了解下程序运行的效果 1 2 3 4程序入口点类似于win32程序里的WinMain函数,Android自然也有它的程序入口点。它通过在AndroidManifest.xml文件中配置来指明,可以看到名为NotesList的activity节点下有这样一个intent-filter,其action为ent.action.MAIN,Category指定为 ent.category.LAUNCHER,这就指明了这个activity是作为入口activity,系统查找到它后,就会创建这个activity实例来运行,若未发现就不启动(你可以把MAIN改名字试试)。NotesList详解就从入口点所在的activity(见图1)开始,可以看到这个activity最重要的功能就是显示日志列表。这个程序的日志都存放在Sqlite数据库中,因此需要读取出所有的日志记录并显示。先来看两个重要的私有数据,第一个PROJECTION字段指明了“日志列表“所关注的数据库中的字段(即只需要ID和Title就可以了)。privatestaticfinal String PROJECTION =new String Notes._ID, / 0 Notes.TITLE, / 1 ;第二个字段COLUMN_INDEX_TITLE指明title字段在数据表中的索引。privatestaticfinalint COLUMN_INDEX_TITLE =1;然后就进入第一个调用的函数onCreate。 Intent intent = getIntent(); if (intent.getData() =null) intent.setData(Notes.CONTENT_URI); 因为NotesList这个activity是系统调用的,此时的intent是不带数据和操作类型的,系统只是在其中指明了目标组件是Notelist,所以这里把”content:/ vider.NotePad/notes”保存到intent里面,这个URI地址指明了数据库中的数据表名(参见以后的NotePadProvider类),也就是保存日志的数据表notes。 Cursor cursor = managedQuery(getIntent().getData(), PROJECTION, null, null, Notes.DEFAULT_SORT_ORDER); 然后调用managedQuery函数查询出所有的日志信息,这里第一个参数就是上面设置的” content:/ vider.NotePad/notes”这个URI,即notes数据表。PROJECTION 字段指明了结果中所需要的字段,Notes.DEFAULT_SORT_ORDER 指明了结果的排序规则。实际上managedQuery并没有直接去查询数据库,而是通过Content Provider来完成实际的数据库操作,这样就实现了逻辑层和数据库层的分离。SimpleCursorAdapter adapter =new SimpleCursorAdapter(this, R.layout.noteslist_item, cursor, new String Notes.TITLE , newint android.R.id.text1 ); setListAdapter(adapter); 查询出日志列表后,构造一个CursorAdapter,并将其作为List View的数据源,从而在界面上显示出日志列表。可以看到,第二个参数是R.layout.noteslist_item,打开对应的noteslist_item.xml文件, 就是用来显示一条日志记录的TextView,最后两个字段指明了实际的字段映射关系,通过这个TextView来显示一条日志记录的title字段。处理“选择日志”事件既然有了“日志列表”,就自然要考虑如何处理某一条日志的单击事件,这通过重载onListItemClick方法来完成, Override protectedvoid onListItemClick(ListView l, View v, int position, long id) Uri uri = ContentUris.withAppendedId(getIntent().getData(), id); String action = getIntent().getAction(); if (Intent.ACTION_PICK.equals(action) | Intent.ACTION_GET_CONTENT.equals(action) / The caller is waiting for us to return a note selected by / the user. The have clicked on one, so return it now. setResult(RESULT_OK, new Intent().setData(uri); else / Launch activity to view/edit the currently selected item startActivity(new Intent(Intent.ACTION_EDIT, uri); 首先通过”content:/ vider.NotePad/notes”和日志的id 号拼接得到选中日志的真正URI,然后创建一个新的Intent,其操作类型为Intent.ACTION_EDIT,数据域指出待编辑的日志URI(这里只分析else块)。Intent深度剖析那么,上面这句startActivity(new Intent(Intent.ACTION_EDIT, uri)执行后会发生什么事情呢?这时候Android系统就跳出来接管了,它会根据intent中的信息找到对应的activity,在这里找到的是NoteEditor这个activity,然后创建这个activity的实例并运行。那么,Android又是如何找到NoteEditor这个对应的activity的呢?这就是intent发挥作用的时刻了。new Intent(Intent.ACTION_EDIT, uri)这里的Intent.ACTION_EDIT=” ent.action.EDIT”,另外通过设置断点,我们看下这里的uri值: 可以看到选中的日志条目的URI是:content:/vider.NotePad/notes/1然后我们再来看下Androidmanfest.xml,其中有这个provider 发现没有?它也有vider.NotePad,这个是content:/vider.NotePad/notes/1的一部分,同时 上面第一个intent-filter中有一个action 名为ent.action.EDIT,而前面我们创建的Intent也正好是Intent.ACTION_EDIT=” ent.action.EDIT”,想必大家已经明白是怎么回事了吧。下面就进入activity选择机制了:系统从intent中获取道uri,得到了content:/vider.NotePad/notes/1,去掉开始的content:标识,得到vider.NotePad/notes/1,然后获取前面的vider.NotePad,然后就到Androidmanfest.xml中找到authorities为vider.NotePad的provider,这个就是后面要讲的contentprovider,然后就加载这个content provider。在这里是NotePadProvider,然后调用NotePadProvider的gettype函数,并把上述URI传给这个函数,函数返回URI所对应的类型(这里返回Notes.CONTENT_ITEM_TYPE,代表一条日志记录,而CONTENT_ITEM_TYPE = vnd.android.cursor.item/vnd.google.note )。 Override public String getType(Uri uri) switch (sUriMatcher.match(uri) case NOTES: return Notes.CONTENT_TYPE; case NOTE_ID: return Notes.CONTENT_ITEM_TYPE; default: thrownew IllegalArgumentException(Unknown URI + uri); 上面的sUriMatcher.match是用来检测uri是否能够被处理,而sUriMatcher.match(uri)返回值其实是由 sUriMatcher =new UriMatcher(UriMatcher.NO_MATCH); sUriMatcher.addURI(NotePad.AUTHORITY, notes, NOTES); sUriMatcher.addURI(NotePad.AUTHORITY, notes/#, NOTE_ID);决定的。然后系统使用获得的 vnd.android.cursor.item/vnd.google.note 和”ent.action.EDIT”到androidmanfest.xml中去找匹配的activity.正好NoteEditor这个activity的intent-filter满足上述条件,这样就找到了NoteEditor。于是系统加载这个类并实例化,运行,然后就到了NoteEditor的OnCreate函数中(见后续文章)。小技巧1,在命令行中使用”adb shell”命令进入系统中,然后”cd app”进入应用程序所在目录,”rm XXX”就可以删除你指定的apk,从而去掉其在系统顶层界面占据的图标,若两次”cd data”则可以进入应用程序使用的数据目录,你的数据可以保存在这里,例如Notepad就是把其数据库放在它的databases目录下,名为note_pad.db.2,第一次启动模拟器会比较慢,但以后就别关闭模拟器了,修改代码,调试都不需要再次启动的,直接修改后run或debug就是。2.在测试时,如何实现一个提示可以使用1. Toast.makeText(this,这是一个提示,Toast.LENGTH_SHORT).show();2. /从资源文件string.xml 里面取提示信息3. Toast.makeText(this, getString(R.string.welcome), Toast.LENGTH_SHORT).show();这个提示会几秒钟后消失3.可以使用AlertDialog.Builder 才产生一个提示框. 例如像messagebox那样的1. newAlertDialog.Builder(this)2. .setTitle(Android提示)3. .setMessage(这是一个提示,请确定)4. .show();带一个确定的对话框1. newAlertDialog.Builder(this)2. .setMessage(这是第二个提示)3. .setPositiveButton(确定,4. newDialogInterface.OnClickListener()5. publicvoidonClick(DialogInterfacedialoginterface,inti)6. /按钮事件7. 8. )9. .show();AlertDialog.Builder 还有很多复杂的用法,有确定和取消的对话框1. newAlertDialog.Builder(this)2. .setTitle(提示)3. .setMessage(确定退出?)4. .setIcon(R.drawable.quit)5. .setPositiveButton(确定,newDialogInterface.OnClickListener()6. publicvoidonClick(DialogInterfacedialog,intwhichButton)7. setResult(RESULT_OK);/确定按钮事件8. finish();9. 10. )11. .setNegativeButton(取消,newDialogInterface.OnClickListener()12. publicvoidonClick(DialogInterfacedialog,intwhichButton)13. /取消按钮事件14. 15. )16. .show();4. menu 的用法. 1. 简单的代码1. publicstaticfinalintITEM_1_ID=Menu.FIRST;2. publicstaticfinalintITEM_2_ID=Menu.FIRST+1;3. publicstaticfinalintITEM_3_ID=Menu.FIRST+2;4. 5. publicbooleanonCreateOptionsMenu(Menumenu)6. super.onCreateOptionsMenu(menu);7. /不带图标的menu8. menu.add(0,ITEM_1_ID,0,item-1);9. /带图标的menu10. menu.add(0,ITEM_2_ID,1,item-2).setIcon(R.drawable.editbills2);11. menu.add(0,ITEM_3_ID,2,item-3).setIcon(R.drawable.billsum1);12. returntrue;13. 14.15. publicbooleanonOptionsItemSelected(MenuItemitem)16. switch(item.getItemId()17. case1:18. Toast.makeText(this,menu1,Toast.LENGTH_SHORT).show();19. returntrue;20. case2:21. 22. returntrue;23. case3:24. 25. returntrue;26. 27. returnfalse;28. 2. menu实现的两种方法大部分的应用程序都包括两种人机互动方式,一种是直接通过GUI的 Views,其可以满足大部分的交互操作。另外一种是应用Menu,当按下Menu按钮后,会弹出与当前活动状态下的应用程序相匹配的菜单。这两种方式相比较都有各自的优势,而且可以很好的相辅相成,即便用户可以由主界面完成大部分操作,但是适当的拓展Menu功能可以更加完善应用程序,至少用户可以通过排列整齐的 按钮清晰的了解当前模式下可以使用的功能。有两种方法可以为Android APPs添加菜单功能,下边将对设置过程给出详细的介绍:第一种方法,通过Layout来添加静态菜单元素。一般情况下,开发者在res/Layout路径下来定义应用程序的GUI。应用Eclipse创建一个新项目后,可以看到res/layout中存在一个 预置的main.xml文件,其作为程序默认启动界面。同样,可以通过这种方式 创建一个静态的Menu,创建方法参阅下边的源代码:?View Code XML 3), so be carefull- 在Activity类中调用刚刚创建的Menu,首先将当前的Activity与指定的Menu XML相关联:Overridepublic boolean onCreateOptionsMenu(Menu menu) super.onCreateOptionsMenu(menu); getMenuInflater().inflate(R.layout.menu_mainactivity, menu); return true;实现onOptionsItemSelected方法: (其目的是捕捉到菜单触发事件后,对具体触发的选项作出响应,实际调用的函数包含在各自的case中)01.Override02.public boolean onOptionsItemSelected(MenuItem item) 03. switch (item.getItemId() 04. case R.id.previous:05. previous(); /go to previous song in the playlist06. return true;07. case R.id.play_pause:08. isPlaying() ? pause() : play(); /toggle play/pause09. return true;10. case R.id.next:11. next(); /go to next song in the playlist12. return true;13. 14. return false; /should never happen15.最后可以通过onPrepareOptionMenu方法初始化Menu Items的属性:01.Override02.public boolean onPrepareOptionsMenu(Menu menu) 03. /set play_pause menu item look04. if(isPlaying() 05. menu06. .findItem(R.id.play_pause)07. .setTitle(R.string.pause)08. .setIcon(android.R.drawable.ic_media_pause);09. else 10. menu11. .findItem(R.id.play_pause)12. .setTitle(R.string.play)13. .setIcon(android.R.drawable.ic_media_play);14. 15. return true;16.大部分程序都通过这种方式添加Menu菜单功能,而且通过以上的步骤来看,其实现方法非常简单。第二种方法,在Activity类中动态创建Menu。首先需要定义Menu Item识别序号:1.public static final MENU_PREVIOUS = 0; /no more R.ids2.public static final MENU_PLAY_PAUSE = 1;3.public static final MENU_NEXT = 2;实现onCreateOptionMenu()方法:(第一种方法中已经通过xml定义了现成的Menu结构,所以不需要应用这个方法)01.Override02.public boolean onCreateOptionsMenu(Menu menu) 03. menu04. .add(0, MENU_PREVIOUS, 0, R.string.previous)05. .setIcon(android.R.drawable.ic_media_previous);06. menu07. .add(0, MENU_PLAY_PAUSE, 0, R.string.play)08. .setIcon (android.R.drawable.ic_media_play);09. menu10. .add(0, MENU_NEXT, 0, R.string.next)11. .setIcon(android.R.drawable.ic_media_next);12. return true;13.引用与第一种方法相同的方式来捕捉菜单的行为:01.Override02.public boolean onOptionsItemSelected(MenuItem item) 03. switch (item.getItemId() 04. case MENU_PREVIOUS:05. previous(); /go to previous song in the playlist06. return true;07. case MENU_PLAY_PAUSE:08. isPlaying() ? pause() : play(); /toggle play/pause09. return true;10. case MENU_NEXT:11. next(); /go to next song in the playlist12. return true;13. 14. return false; /should never happen15.对以上两种方法的补充:根据需要设置不同Menu Item的属性:1.menu.findItem(R.id.next).setEnabled(false);设置Menu Item从属关系(添加子父级别):直接写在方法中:1.menu2. .addSubMenu(R.id.repeat)3. .add(R.id.one)4. .add(R.id.all)5. .add(R.id.none);直接定义在XML Layout中:?View Code XML 这两种不同的方法实现的目的是一样的,而且不存在本质上的却别,具体根据实际情况(根据项目的结构需要或者团队开发标准)选择合适的方法来创建Menu。5.Activity 的切换(含Bundle传值)1. 代码1、 2个Activity 的切换,没有数据传递1. /从A到B2. Intentintent=newIntent();3. intent.setClass(A.this,B.class);4. startActivity(intent);5. A.this.finish();2、 2个Activity 之间传递数据(简单)/A数据传给B /A中代码:”passData” 是自定义的识别标志,可以随便命名 还可以添加多个Intent intent = new Intent(); intent.setClass(A.this, B.class); Bundle mBundle = new Bundle(); mBundle.putString(passData, rayblog);/压入数据 intent.putExtras(mBundle); startActivity(intent);A.this.finish();/B中接受数据的代码:/读出数据, 则data的值为 rayblog Bundle bundle = getIntent().getExtras(); String data = bundle.getString( passData );3、 2个Activity 之间传递数据(复杂方法我没看懂) 相关的几个函数startActivityForResult public final void setResult(int resultCode, String data) 回调函数 protected void onActivityResult(int requestCode, int resultCode, Intent data)例如A到B, 从B得到A的数据1. /A到B2. static final int RG_REQUEST = 0;3. Intentintent=newIntent();4. intent.setClass(A.this,B.class);5. startActivityForResult(intent,RG_REQUEST);6. 7. /在B中处理8. Bundle bundle = new Bundle();bundle.putString(DataKey, edittext.getText().toString();/给bundle 写入数据Intent mIntent = new Intent();mIntent.putExtras(bundle);setResult(RESULT_OK, mIntent);finish();9.10. /最后在A的回调函数里面接收数据11. if (requestCode = RG_REQUEST) if (resultCode = RESULT_CANCELED) setTitle(Canceled.); else if(resultCode = RESULT_OK) setTitle(String)data.getCharSequenceExtra(DataKey);2. 详解:一个Android应用程序很少会只有一个Activity对象,如何在多个Activity之间进行跳转,而且能够互相传值是一个很基本的要求。在前面创建的MyApp中,我们通过点击按钮可以更新当前界面上的文本内容。现在我们想换种方式,在点击按钮后,显示一个新的屏幕,在这个屏幕上输入一段话,然后再返回到原先的界面显示刚才输入的那句话。首先我们新建这个新屏幕的布局文件input.xml,并添加一个文本输入框和一个按钮(注意,xml元素的命名不要和其他布局文件中的定义重名,因为所有的资源都在R中进行索引,比如id,如果重名了在使用R.id.*的时候就会有问题了)。这个布局文件对应的是一个Activity,因此我们再新建一个Input类(继承自Activity)用于显示这个布局并响应事件。然后,还有一个重要的工作,那就是在清单文件AndroidManifest.xml中告诉程序,我定义了一个新的Activity,你可以去调用它。我们希望在以前的那个主界面上点击按钮以后可以跳转到文本输入界面,所以我们需要对按钮的onClick事件进行定义:在这段代码里出现了一些新东西。首先是Intent,它是Android一个很重要的类.Intent直译是“意图”,什么是意图呢?比如你想从这个Activity跳转到另外一个Activity,这就是一个意图。它不但可以连接多个Activity,还可以在它们之间传递数据。在这里,我们就是用Intent从MyApp对象跳转到了Input对象。再看紧跟着的startActivityForResult()方法,顾名思义,它可以从一个定义好的Intent对象启动一个新的Activity,并且,这个Activity会返回执行的结果,这些内容下面马上就会提到。好,这里我们已经可以调出新Activity了,我们看一下执行的结果:你马上可以想到,现在需要对新的Activity(Input)进行处理了。我们在点击“确定”按钮的时候,需要获得上面EditText对象中的文本,然后返回到前一个Activity(MyApp)中去。看我们的按钮事件处理:这里的关键是SharedPreferences对象,这是在多个Activity(同一包中)共享数据的方式,本质上它就是一个可以在包的范围内进行数据共享的文件。我们通过一个标签“Text”获得了和文本相关的那个SharedPreferences对象(“Text”仅仅是自己定义的一个标签),然后给它赋予一个“text”对象值为当前文本框中输入的文本。设置完成以后,设置当前Activity的执行结果为RESULT_OK,再关闭当前的Activity,剩下的事情就可以回到MyApp这个主界面中去执行了。其实剩下的事情也很简单,在MyApp这个Activity中,我们需要重写一个函数,onActivityResult()。因为我们启动Input这个Activity的时候使用的是startActivityForResult()方法,这个方法会使Input执行完以后返回给MyApp一个结果,MyApp接收到返回结果的时候会触发onActivityResult事件,对于结果的处理就在onActivityResult()中进行。同样,我们通过“Text”这个标签获得SharedPreferences对象,再把字符串从“text”对象中取出来并显示到当前屏幕上。另外说明一下,requ
温馨提示
- 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
- 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
- 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
- 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
- 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
- 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
- 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
最新文档
- 玛塔5岁课件教学课件
- 中永兴不锈钢公司线材酸洗项目环评报告
- 堤防工程防汛抢险方案(3篇)
- 地坪工程招商加盟方案(3篇)
- 猫咪聚会课件教学
- 审美视域下高中语文专题读写的研究
- 房屋工程实施方案(3篇)
- 狂犬病防治宣传课件
- 安全教育影片培训总结课件
- 安全教育培训随笔课件
- 食品安全 课件 高中主题班会
- YS/T 830-2012正丁基锂
- GB/T 31341-2014节能评估技术导则
- GB/T 29114-2012燃气轮机液体燃料
- GB/T 24218.3-2010纺织品非织造布试验方法第3部分:断裂强力和断裂伸长率的测定(条样法)
- GB/T 12470-2018埋弧焊用热强钢实心焊丝、药芯焊丝和焊丝-焊剂组合分类要求
- GB/T 10799-2008硬质泡沫塑料开孔和闭孔体积百分率的测定
- GA/T 1193-2014人身损害误工期、护理期、营养期评定规范
- FCI测试试题附答案
- 博微配电网工程设计软件
- 教育科研:教师职业成长的阶梯课件
评论
0/150
提交评论