小菜毛毛技术分享

与大家共同成长

  BlogJava :: 首页 :: 联系 :: 聚合  :: 管理
  164 Posts :: 141 Stories :: 94 Comments :: 0 Trackbacks

#

从零开始Android游戏编程
五子棋源码
Read RSS on OPhone
俄罗斯方块
空战游戏1945
加速传感器演示
演示如何使用Location和Google Map
个股宝典
连连看
策略游戏——回到战国 android源代码
滚屏动作游戏——太空保卫战 android源代码
冒险游戏——胜利大逃亡 android源代码
体育游戏——疯狂足球 android源代码 附件
水波效应android源码
Android 下3D赛车游戏
扫雷游戏,android源码,有注解
MP3切割器
Android国际象棋源码
旅行记录软件源码
DroidReader 源码
Android下的VOIP客户端源码
Android下的FTP服务器源码
Android下俄罗斯方块源码
posted @ 2010-12-03 12:39 小菜毛毛 阅读(518) | 评论 (0)编辑 收藏

     摘要: 转自:http://blog.csdn.net/Android_Tutor/archive/2010/04/20/5508615.aspx 今天我们的教程是根据前面一节扩展进行的,如果你没有看,请点击 Android高手进阶教程(三) 查看第三课,这样跟容易方便你的理解! 在xml 文件里定义控件的属性,我们已经习惯了android:attrs="" ,那么我们能不能定...  阅读全文
posted @ 2010-11-23 15:22 小菜毛毛 阅读(419) | 评论 (0)编辑 收藏

     摘要: 转自:http://blog.csdn.net/Android_Tutor/archive/2010/04/21/5513869.aspx 大家好我们这一节讲的是LayoutInflater的使用,在实际开发种LayoutInflater这个类还是非常有用的,它的作用类似于 findViewById(), 不同点是LayoutInflater是用来找layout下xml布局文件,并且实例化...  阅读全文
posted @ 2010-11-23 15:20 小菜毛毛 阅读(355) | 评论 (0)编辑 收藏

OverView:
程序通过后台每天检查是否有最新版本,如果需要更新当前版本,将弹出对话框让用户选择是否在当前通过Market来更新软件
Knowledge Points:
  • SharedPreferences: 一个轻量级的存储方法,类似于经常使用的.ini文件,它也是通过检索关键字来取得相应的数值。之所以是成为轻量级,是因为它所能应用的数值类型有限,对于存储较大数值,效率相对较低。官方参考
  • System.currentTimeMillis:将当前时间以毫秒作为单位来表示,用于比较两个时间的先后顺序。(其数值表示从1970-01-01 00:00:00直到当前时间的总毫秒数)官方参考
  • 通过网络来读取信息:在checkUpdate()方法中包含了通过制定的URL来读取网络资源。具体操作步骤,请参考源代码
  • Runnable: 在其内部的Run()方法中实现所要执行的任何代码,当这个runnable interface被调用后可以视作为新的线程。
Source Code:
  1. public class hello extends Activity  {
  2.         /** Called when the activity is first created. */
  3.         private Handler mHandler;
  4.          
  5.     @Override
  6.     public void onCreate(Bundle savedInstanceState) {
  7.         super.onCreate(savedInstanceState);
  8.         setContentView(R.layout.main);
  9.         
  10.         mHandler = new Handler();

  11.         /* Get Last Update Time from Preferences */
  12.         SharedPreferences prefs = getPreferences(0);
  13.         long lastUpdateTime =  prefs.getLong("lastUpdateTime", System.currentTimeMillis());

  14.         int curVersion = 0;
  15.                 try {
  16.                         curVersion = getPackageManager().getPackageInfo("linhai.com.hello", 0).versionCode;
  17.                 } catch (NameNotFoundException e) {
  18.                         // TODO Auto-generated catch block
  19.                         e.printStackTrace();
  20.                 }
  21.         Log.i("DEMO",String.valueOf(curVersion));
  22.         /* Should Activity Check for Updates Now? */
  23.         if ((lastUpdateTime + (24 * 60 * 60 * 1000)) < System.currentTimeMillis()) {

  24.             /* Save current timestamp for next Check*/
  25.            lastUpdateTime = System.currentTimeMillis();
  26.             SharedPreferences.Editor editor = getPreferences(0).edit();
  27.             editor.putLong("lastUpdateTime", lastUpdateTime);
  28.             editor.commit();      

  29.             /* Start Update */
  30.          //   checkUpdate.start();
  31.         }
  32.     }

  33.     /* This Thread checks for Updates in the Background */
  34.     private Thread checkUpdate = new Thread()
  35.     {
  36.         public void run() {
  37.             try {
  38.                 URL updateURL = new URL("http://my.company.com/update");
  39.                 URLConnection conn = updateURL.openConnection();
  40.                 InputStream is = conn.getInputStream();
  41.                 BufferedInputStream bis = new BufferedInputStream(is);
  42.                 ByteArrayBuffer baf = new ByteArrayBuffer(50);

  43.                 int current = 0;
  44.                 while((current = bis.read()) != -1){
  45.                      baf.append((byte)current);
  46.                 }

  47.                 /* Convert the Bytes read to a String. */
  48.                 final String s = new String(baf.toByteArray());        

  49.                 /* Get current Version Number */
  50.                 int curVersion = getPackageManager().getPackageInfo("your.app.id", 0).versionCode;
  51.                 int newVersion = Integer.valueOf(s);

  52.                 /* Is a higher version than the current already out? */
  53.                 if (newVersion > curVersion) {
  54.                     /* Post a Handler for the UI to pick up and open the Dialog */
  55.                     mHandler.post(showUpdate);
  56.                 }
  57.             } catch (Exception e) {
  58.             }
  59.         }
  60.     };

  61.     /* This Runnable creates a Dialog and asks the user to open the Market */
  62.     private Runnable showUpdate = new Runnable(){
  63.            public void run(){
  64.             new AlertDialog.Builder(hello.this)
  65.             .setIcon(R.drawable.ok)
  66.             .setTitle("Update Available")
  67.             .setMessage("An update for is available!\n\nOpen Android Market and see the details?")
  68.             .setPositiveButton("Yes", new DialogInterface.OnClickListener() {
  69.                     public void onClick(DialogInterface dialog, int whichButton) {
  70.                             /* User clicked OK so do some stuff */
  71.                             Intent intent = new Intent(Intent.ACTION_VIEW, Uri.parse("market://search?q=pname:your.app.id"));
  72.                             startActivity(intent);
  73.                     }
  74.             })
  75.             .setNegativeButton("No", new DialogInterface.OnClickListener() {
  76.                     public void onClick(DialogInterface dialog, int whichButton) {
  77.                             /* User clicked Cancel */
  78.                     }
  79.             })
  80.             .show();
  81.            }
  82.     };
  83.   
  84. }
复制代码


分为三个部分:
  • 置于onCreate()方法中的程序用于判断当前时间是否需要检查更新(如果距离上次更新时间大于1天,将启动检查更新)
  • 当以上条件满足时,启动checkUpdate来检查当前程序是否为最新版本。
  • 如果确定版本已过期,那么将登录market,并直接指向当前程序页面。
*******************************************************************************************
向上言:
     本人在论坛曾经发过一关于此问题的求助帖,虽然大至的思路和上文差不多,关键点是在于程序如何更新,现在看到它这里指出的更新方法居然是登录market。不过以后发布的程序都是在market中,问题就不存在。
  1.                             Intent intent = new Intent(Intent.ACTION_VIEW, Uri.parse("market://search?q=pname:your.app.id"));
  2.                             startActivity(intent);
复制代码
大家都是在eclipse上开发吧,在每次更新代码,运行模拟器时,大家是否有注意到console的提示信息:
  1. [2009-06-06 19:53:50 - Hello] Android Launch!
  2. [2009-06-06 19:53:50 - Hello] adb is running normally.
  3. [2009-06-06 19:53:50 - Hello] Performing linhai.com.hello.hello activity launch
  4. [2009-06-06 19:53:50 - Hello] Automatic Target Mode: using existing emulator 'emulator-5554' running compatible AVD 'avd'
  5. [2009-06-06 19:53:50 - Hello] WARNING: Application does not specify an API level requirement!
  6. [2009-06-06 19:53:50 - Hello] Device API version is 3 (Android 1.5)
  7. [2009-06-06 19:53:50 - Hello] Uploading Hello.apk onto device 'emulator-5554'
  8. [2009-06-06 19:53:50 - Hello] Installing Hello.apk...
  9. [2009-06-06 19:54:05 - Hello] Application already exists. Attempting to re-install instead...
  10. [2009-06-06 19:54:31 - Hello] Success!
复制代码
分析:
1。android正常运行
2。通过配置文件AndroidManifest.xml中运行我们的程序
3。Uploading Hello.apk onto device 'emulator-5554'这句是关键,更新我们的程序
4。Installing Hello.apk...
5。Application already exists. Attempting to re-install instead...//程序已经存在,尝试重新安装

所以如果我们的程序要自动更新,本人初步猜想是和上面的步骤是一样的。
详看logcat中的log
  1. 06-06 11:54:02.567: DEBUG/PackageParser(582): Scanning package: /data/app/vmdl12464.tmp
  2. 06-06 11:54:08.048: INFO/PackageManager(582): Removing non-system package:linhai.com.hello
  3. 06-06 11:54:08.187: DEBUG/PackageManager(582): Removing package linhai.com.hello
  4. 06-06 11:54:08.286: DEBUG/PackageManager(582):   Activities: linhai.com.hello.hello
  5. 06-06 11:54:11.136: DEBUG/PackageManager(582): Scanning package linhai.com.hello
  6. 06-06 11:54:11.301: INFO/PackageManager(582): /data/app/vmdl12464.tmp changed; unpacking
  7. 06-06 11:54:11.626: DEBUG/installd(555): DexInv: --- BEGIN '/data/app/vmdl12464.tmp' ---
  8. 06-06 11:54:12.987: DEBUG/dalvikvm(7756): DexOpt: load 224ms, verify 265ms, opt 1ms
  9. 06-06 11:54:13.047: DEBUG/installd(555): DexInv: --- END '/data/app/vmdl12464.tmp' (success) ---
  10. 06-06 11:54:13.057: DEBUG/PackageManager(582):   Activities: linhai.com.hello.hello
  11. 06-06 11:54:15.608: INFO/installd(555): move /data/dalvik-cache/data@app@vmdl12464.tmp@classes.dex -> /data/dalvik-cache/data@app@linhai.com.hello.apk@classes.dex
  12. 06-06 11:54:15.737: DEBUG/PackageManager(582): New package installed in /data/app/linhai.com.hello.apk
复制代码
关于此类的自动更新的第三方管理软件已经有了叫aTrackDog,其原理就是使用上面的方式。
关于得到版本号,使用:
  1. int curVersion = getPackageManager().getPackageInfo("your.app.id", 0).versionCode;
复制代码
程序版本号的是放在AndroidManifest.xml文件中:
  1. <manifest xmlns:android="http://schemas.android.com/apk/res/android"
  2.         package="linhai.com.hello" android:versionCode="2" android:versionName="2.0.1">
复制代码
主点是关于:getPackageManager()在这个下面有很多方法,你可以通过它得,得到当前终端安装的程序等。关于安装包的函数是:getPackageManager().installPackage(packageURI)

动手试验:
在dos状态下运行:
1.JPG
查看logcat下的信息,大致和刚才相同,分析流程:
  1. 06-06 12:18:58.827: INFO/jdwp(8368): received file descriptor 20 from ADB
  2. 06-06 12:19:02.546: DEBUG/PackageParser(582): Scanning package: /data/app/vmdl12465.tmp
  3. 06-06 12:19:07.738: INFO/PackageManager(582): /data/app/vmdl12465.tmp changed; unpacking
  4. 06-06 12:19:07.978: DEBUG/installd(555): DexInv: --- BEGIN '/data/app/vmdl12465.tmp' ---
  5. 06-06 12:19:09.617: DEBUG/dalvikvm(8378): DexOpt: load 254ms, verify 564ms, opt 3ms
  6. 06-06 12:19:09.697: DEBUG/installd(555): DexInv: --- END '/data/app/vmdl12465.tmp' (success) ---
  7. 06-06 12:19:11.907: INFO/installd(555): move /data/dalvik-cache/data@app@vmdl12465.tmp@classes.dex -> /data/dalvik-cache/data@app@com.example.android.snake.apk@classes.dex
  8. 06-06 12:19:11.956: DEBUG/PackageManager(582): New package installed in /data/app/com.example.android.snake.apk
  9. 06-06 12:19:14.746: DEBUG/dalvikvm(8368): VM cleaning up
  10. 06-06 12:19:14.857: DEBUG/dalvikvm(8368): LinearAlloc 0x0 used 628420 of 4194304 (14%)
  11. 06-06 12:19:15.897: DEBUG/dalvikvm(582): GC freed 17704 objects / 903984 bytes in 615ms
  12. 06-06 12:19:15.936: DEBUG/HomeLoaders(625): application intent received: android.intent.action.PACKAGE_ADDED, replacing=false
  13. 06-06 12:19:15.936: DEBUG/HomeLoaders(625):   --> package:com.example.android.snake
  14. 06-06 12:19:15.936: DEBUG/HomeLoaders(625):   --> add package
复制代码
1。接收数据,保存到临时文件中/data/app/vmdl12465.tmp
2。解压此文件,注意路径/data/dalvik-cache/data@app@vmdl12465.tmp@classes.dex
它是在data下的dalvik-cache下
3.安装文件[这个步骤还包括查找程序是否已经安装等]
4.使用GC清理内存

查看DDMS中的结构
2.JPG
看到此文件结构,应该可以想起linux下的文件系统和它的权限管理,也就可以理解,为什么我们的程序无法在data下创建文件之类的问题了。
转载:http://www.androidres.com/?p=349
posted @ 2010-11-23 11:07 小菜毛毛 阅读(366) | 评论 (0)编辑 收藏

ndroid中,你的应用程序程序与View类组件有着一种固定的联系,例如按钮(Button)文本框(TextView), 可编辑文本框(EditText), 列表框(ListView), 复选框(CheckBox), 单选框(RadioButton), 滚动条(Gallery), 微调器(Spinner), 等等,还有一些比较先进的有着特殊用途的View组件,例如 AutoCompleteTextView, ImageSwitcherTextSwitcher。除此之外,种类繁多的像 线性布局(LinearLayout), 框架布局(FrameLayout), 这样的布局组件(Layout)也被认为是View组件,他们是从View类派生过来的。

你的应用程序就是这些控制组件和布局组件以某种方式结合显示在屏幕上,一般来说这些组件对你来说基本够用,但是你也应该知道你是可以通过类继承创建 属于自己的组件,一般可以继承像View、Layouts(布局组件)这样的组件,甚至可以是一些比较高级的控制类组件。下面我们说一下为什么要继承:

  • 你可以为实现某种功能创建一个完全自定义风格的组件,例如用二维的图形创建控制组件实现声音的控制,就像电子控制一样。
  • 你可以把几种组件结合形成一个新的组件,你的组件可能同时包含ComboBox(一个能输入的文本列表)和dual-pane selector control(左右两个List窗口,你可以分配窗口每一项的从属关系)等等。
  • 你可以创建自己的布局组件(Layout)。SDK中的布局组件已经提供了一系列的选项让你打造属于自己的应用程序,但是高级的开发人员会发现根据现有的Layout组件开发新的Layout组件是很有必要的,甚至是完全从底层开发新的组件。
  • 你可以覆盖一个现有组件的显示或功能。例如,改变EditText(可编辑文本)组件在屏幕上的显示方式(可以参考Notepad的例子,里面教你如何创建一个下划线的显示页面)。
  • 你可以捕获像按键按下这样的事件,以一些通用的方法来处理这些事件(一个游戏的例子)。

为了实现某种目标你可能很有必要扩展一个已经存在的View组件,下面我们结合一些例子教你如何去做。

内容:

基本方法(The Basic Approach )
完全自定义组件(Fully Customized Components )
定制组件的例子(Customized Component Example )
组件的混合(或者控制类的混合) (Compound Components (or Compound Controls) )
修改现有组件(Tweaking an Existing Component )
小结(Go Forth and Componentize )

基本方法(The Basic Approach )

下面的一些步骤都比较概括,教你如何创建自己的组件:

  1. 让你的类(Class)继承一个现有的View 类或View的子类。
  2. 重载父类的一些方法:需要重载的父类方法一般以‘on’开头,如onDraw(), onMeasure()onKeyDown()等等。
    • 这个在Activity 或则 ListActivity 派生中同样适用,你需要重载一些生命周期函数和一些其他功能性的HOOK函数。
  3. 使用你的继承类:一旦你的继承类创建完成,你可以在基类能够使用的地方使用你的继承类,但完成功能就是你自己编写的了。

继承类能够定义在activities里面,这样你能够方便的调用,但是这并不是必要的(或许在你的应用程序中你希望创建一个所有人都可以使用的组件)。

完全自定义组件(Fully Customized Components)

完全自定义组件的方法可以创建一些用于显示的图形组件(graphical components),也许是一个像电压表的图形计量器,或者想卡拉OK里面显示歌词的小球随着音乐滚动。无论那种方式,你也不能单纯的利用组件的结合完成,无论你怎么结合这些现有的组件。

幸运的是,你可以以你自己的要求轻松地创建完全属于自己的组件,你会发现不够用的只是你的想象力、屏幕的尺寸和处理器的性能(记住你的应用程序最后只会在那些性能低于桌面电脑的平台上面运行)。

下面简单介绍如何打造完全自定义的组件:

  1. 最为通用的VIEW类的父类毫无疑问是View类,因此,最开始你要创建一个基于此类的一个子类。
  2. 你可以写一个构造函数从XML文件中提取属性和参数,当然你也可以自己定义这些属性和参数(也许是图形计量器的颜色和尺寸,或者是指针的宽度和幅度等等)
  3. 你可能有必要写自己的事件监听器,属性的访问和修改函数和一些组件本身的功能上的代码。
  4. 如果你希望组件能够显示什么东西,你很有可能会重载 onMeasure() 函数,因而你就不得不重载 onDraw() 函数。当两个函数都用默认的,那么 onDraw() 函数将不会做任何事情,并且默认的 onMeasure() 函数自动的设置了一个100x100 —的尺寸,这个尺寸可能并不是你想要的。
  5. 其他有必要重载的on... 系列函数都需要重新写一次。

onDraw()onMeasure()

onDraw()函数将会传给你一个 Canvas 对象,通过它你可以在二维图形上做任何事情,包括其他的一些标准和通用的组件、文本的格式,任何你可以想到的东西都可以通过它实现。

注意: 这里不包括三维图形如果你想使用三维的图形,你应该把你的父类由View改为SurfaceView类,并且用一个单独的线程。可以参考GLSurfaceViewActivity 的例子。

onMeasure() 函数有点棘手,因为这个函数是体现组件和容器交互的关键部分,onMeasure()应该重载,让它能够有效而准确的表现它所包含部分的测量值。这就有点复杂了,因为我们不但要考虑父类的限制(通过onMeasure()传过来的),同时我们应该知道一旦测量宽度和高度出来后,就要立即调用setMeasuredDimension() 方法。

概括的来讲,执行onMeasure()函数分为一下几个阶段:

  1. 重载的onMeasure()方法会被调用,高度和宽度参数同时也会涉及到(widthMeasureSpecheighMeasureSpec两个参数都是整数类型),同时你应该考虑你产品的尺寸限制。这里详细的内容可以参考View.onMeasure(int, int) (这个连接内容详细的解释了整个measurement操作)。
  2. 你的组件要通过onMeasure()计算得到必要的measurement长度和宽度从而来显示你的组件,它应该与规格保持一致,尽管它可以实现一些规格以外的功能(在这个例子里,父类能够选择做什么,包括剪切、滑动、提交异常或者用不同的参数又一次调用onMeasure()函数)。
  3. 一旦高度和宽度计算出来之后,必须调用setMeasuredDimension(int width, int height),否则就会导致异常。

一个自定义组件的例子(A Customized Component Example)

API Demos 中的CustomView提供了以一个自定义组件的例子,这个自定义组件在 LabelView 类中定义。

LabelView例子涉及到了自定义组件的方方面面:

  • 首先让自定义组件从View类中派生出来。
  • 编写带参数的构造函数(参数可以来源于XML文件)。这里面的一些处理都已经在View父类中完成,但是任然有些Labelview使用的自定义组件特有的新的参数需要处理。
  • 一些标准的Public函数,例如setText(), setTextSize(), setTextColor()
  • 重载onMeasure()方法来确定组件的尺寸(注意:在LabelView中是通过一个私有函数measureWidth()来实现的)
  • 重载onDraw()函数把Lable显示在提供的canvas上。

在例子中,你可以通过custom_view_1.xml看到自定义组件LabelView的用法。在XML文件中特别要注意的是android:app:两个参数的混合运用,app:参数表示应用程序中被认为是LabelView组件的个体,这些也会作为资源在R类中定义。

组件混合技术Compound Components (or Compound Controls)

如果你不想创建一个完全自定义的组件,而是由几个现有组件的组合产生的新的组件,那么混合组件技术就更加适合。简单的来 说,这样把几个现有的组件融合到一个逻辑组合里面可以封装成一个新的组件。例如,一个Combo Box组件可以看作是是一个EditText和一个带有弹出列表的Button组件的混合体。如果你点击按钮为列表选择一项,

在Android中,其实还有其他的两个View类可以做到类似的效果: SpinnerAutoCompleteTextView,,但是Combo Box作为一个例子更容易让人理解。

下面简单的介绍如何创建组合组件:

  1. 一般从Layout类开始,创建一个Layout类的派生类。也许在Combo box我们会选择水平方向的LinearLayout作为父类。记住,其他的Layout类是可以嵌套到里面的,因此混合组件可以是任何组件的混合。注 意,正如Activity一样,你既可以使用外部XML文件来声明你的组件,也可以嵌套在代码中。
  2. 在新的混合组件的构造函数中,首先,调用所有的父类的构造函数,传入对应的参数。然后可以设置你的混合组件的其他的一些方面,在哪创建 EditText组件,又在哪创建PopupList组件。注意:你同时也可以在XML文件中引入一些自己的属性和参数,这些属性和参数也可以被你的混合 组件所使用。
  3. 你也可以创建时间监听器去监听新组件中View类触发的事件,例如,对List选项单击事件的监听,你必须在此时间发生后更新你EditText的值。
  4. 你可能创建自己的一些属性,带有访问和修改方法。例如,允许设置EditText初始值并且提供访问它的方法。
  5. 在Layout的派生类中,你没有必要去重载onDraw()onMeasure()方法,因为Layout会有比较好的默认处理。但是,如果你觉得有必要你也可以重载它。
  6. 你也可能重载一些on系列函数,例如通过onKeyDown()的重载,你可以通过按某个键去选择列表中的对应的值。

总之,把Layout类作为基类有下面几个优点:

  • 正如activity一样,你也可以通过XML文件去声明你的新组件,或者你也可以在代码中嵌套。
  • onDraw()函数和onMeasure()函数是没有必要重载的,两个函数已经做得很好了。
  • 你可以很快的创建你的混合组件,并且可以像单一组件那样使用。

混合组件的例子(Examples of Compound Controls)

In the API Demos project 在API Demos工程中,有两个List类的例子——Example 4和Example 6,里面的SpeechView组件是从LinearLayout类派生过来,实现显示演讲显示功能,对应的原代码是List4.javaList6.java

调整现有组件(Tweaking an Existing Component)

在某些情况下,你可能有更简单的方法去创建你的组件。如果你应经有了一个非常类似的组件,你所要做的只是简单的从这个组件派生出你的组件,重在其中 一些有必要修改的方法。通过完全自定义组件的方法你也可以同样的实现,但通过冲View派生产生新的组件,你可以简单获取一些已经存在的处理机制,这些很 可能是你所想要的,而没有必要从头开始。

例如,在SDK中有一个NotePad的例子(NotePad application )。该例子演示了很多Android平台实用的细节,例如你会学到从EditView派生出能够自动换行的记事本。这还不是一个完美的例子,因为相比早期的版本来说,这些API已经感变了很多,但它确实说明了一些问题。

如果你还未查看该程序,现在你就可以在Eclipse中导入记事本例程(或仅通过提供的链接查看相应的源代码)。特别是查看NoteEditor.java 中的MyEditText的定义。

下面有几点要注意的地方:

  1. 声明(The Definition)

    这个类是通过下面一行代码来定义的:

    public static class MyEditText extends EditText

    • 它是定义在NoteEditor activity类里面的,但是它是共有的(public),因此如果有必要,它可以通过NoteEditor.MyEditTextNoteEditor外面来调用。
    • 它是static类(静态类),意味着不会出现所谓的通过父类访问数据的“虚态方法”, 这样就使该类成为一个可以不严重依赖NoteEditor的单独类。对于不需要从外部类访问的内联类的创建,这是一个很清晰地思路,保证所产生的类很小,并且允许它可以被其他的类方便的调用。
    • 它是EditText类的扩展,它是我们选择的用来自定义的父类。当我们完成以后,新的类就可以作为一个普通的EditText来使用。
  2. 类的初始化

    一般来说,父类是首先调用的。进一步来说,这不是一个默认的构造函数,而是一个带参数的构造函数。因为EditText是使用从XML布局文件提取出来的参数进行创建,因此我们的构造函数也要取出参数并且将这些参数传递给父类。

  3. 方法重载

    在本例中,仅对onDraw()一个方法进行重载。但你可以很容易地为你的定制组件重载其他需要的方法。

    对于记事本例子来说,通过重载onDraw()方法我们可以在EidtView的画布(canvas)上绘制蓝色的线条(canvas类是通过重写的onDraw()方法传递)。该函数快要结束时要调用super.onDraw()函数。父类的方法是应该调用,但是在这个例子里面,我们是在我们划好了蓝线之后调用的。

  4. 使用定制组件

    现在,我们已经有自己定制的组件了,但是应该怎样使用它呢?在记事本例子中,定制的组件直接在预定义的布局文件中使用,让我们看一看res/layout目录中的note_editor.xml文件。

    <view xmlns:android="http://schemas.android.com/apk/res/android" 
    class="com.android.notepad.NoteEditor$MyEditText"
    id="@+id/note"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent"
    android:background="@android:drawable/empty"
    android:padding="10dip"
    android:scrollbars="vertical"
    android:fadingEdge="vertical" />
    • 该自定义组件在XML中是作为一个一般的View类来创建的,并且是通过全路径包来描述的。注意这里内联类是通过NoteEditor$MyEditText来表示的,这是Java编程中引用内联类的标准方法。
    • 在定义中的其他属性和参数将传递给定制组件的构造函数,然后才传到EditText构造函数中,因此这些参数也是你使用EditText组件的参数。注意,这里你也可以增加你自己的参数,我们将在下面讨论这个问题。

这就是你全部需要做的,诚然这是一个简单的例子。但问题的关键是:你的需求有多复杂,那么你的自定义组件就有多么复杂。

一个更为复杂的组件可能需要重载更多的on系列函数,并且还要很多特有的函数来充分实现自定义组件的功能。唯一的限制就是你的想象力和你需要组件去执行什么工作。

现在开始你的组件化之旅吧

如你所见,Android提供了一种精巧而又强大的组件模型,让你尽可能的完成你的工作。从简单的组件调整到组件混合,甚至完全自定义组件,灵活的运用这些技术,你应该可以得到一个完全符合你外观要求的的Android程序 

posted @ 2010-11-23 10:19 小菜毛毛 阅读(355) | 评论 (0)编辑 收藏

http://apphu.com/androidmarket

APP虎大讲堂:
android market就是程序应用商店。在2008年8月29日,谷歌推出了Android Market,为使用Android操作系统的手机用户提供第三方应用。

这个平台相似于Apple的App Store,可以连接最新的Google在线 服务器。由于其本土化的设计,Android Market可以让用户下载和安装支持Android系统的第三方软件。

Google作为Android Market的东道主,却一再强调Android Market的扮演的角色仅仅是“软件销售和传播的中心”而不是“软件过滤器”。

为什么Google选择 android market 而不是Store?

Google选择“’Market’”这个词而不是“Store”,是因为其觉得开发者需要的是一个开放的、毫无阻碍的环境来创造内容。Google希望 Android Market最终会像YouTube那样,只需要注册一个发行人资格和软件的类别就可以发布软件。
Google并没有表示会对android market进行监管,只是表示Android Market里的软件将拥有反馈系统以及类似YouTube上的等级系统。Google 将通过追踪工具获得软件的反馈,如果某个软件有危险性,将会有标识提醒用户注意。但是其中的隐私问题却在前不久的SMobile 的分析报告>中显露无疑,而且普通用户很难注意到有些软件会侵犯他们的隐私,况且让谷歌android手机用户去辨别生涩的专业名词,实在太强人所难了。

Android Market学习了App Store开创的软件销售模式,对iPhone以及App Store是一个冲击;更重要的一方面是 Google选择的Market模式与苹果的App Store之间的差异会逐渐显现出来。

国内三大类android market知多少

自从android在中国大大的火了一把之后,android market也如雨后春笋般的不断涌现出来。总的来说android market有如下几类:
第一类: 谷歌创建的android market
谷歌android market,只此一家,别无其他官方market。

第二类: 国内有头有脸的手机厂商和移动运营商创建的android market

  • MOTO的智件园:
    摩托罗拉也是通过去年转型生产一系列android手机,才着实大赚了一把,流转了不利局面,倒是Nokia迟缓的反应速度让其市场份额半年几乎损失过 半,虽然只在英国占有主导地位,可以在美国的市场份额远不及iphone和android手机,MOTO的Milestone更是让其重新站上历史的舞 台。不甘于被谷歌android market 控制的摩托罗拉自然在寻出路,建造自己的android market
  • 中移动的Mobile Market
  • 中移动的MM简单来说是在android1.0/android1.5的基础上改良版的android系统,虽然当时可以跑动大部分android 软件,但是这个market仍处于不愠不火的状态。不过不久前,中国移动在原来版本的基础上进行了许多创新和改进,推出的OPhone2,0,还完全兼容 Android2.1,甚至三星“奥斯卡I7680”也搭载了OMS系统。目前MM已经初具规模,中国移动Mobile Market拥有16400款应用。

  • 联通的UniStore
  • 联通应用商店(UniStore)已经完成了漫长的“内测阶段”,将于7月中旬正式发布,该应用商店在支付模式上将采用“中间账户”的模式,用户注 册联通应用商店时会自动注册“中间账户”,便可绑定话费支付或者支付宝、财付通等第三方支付工具。据悉,联通应用商店将采用开放平台的模式,也就是说不仅 支持中国联通手机用户使用,也支持中国移动和中国电信的手机用户使用,目前仅有775款。

  • 中国电信的天翼软件工厂
  • 中国电信的天翼空间更是时刻处在升级状态,虽然使出浑身解数,也仍然难见起色,天翼空间拥有1054款

  • 酷派的Android Coolmart为了支撑新机器的上市,宇龙酷派也正在进行着Android Coolmart的招兵买马中。

第三类: 独立第三方创建的android market

虽然可用的谷歌android市场越来越多,但是同质化越来越严重的Market只能让用户无所适从,也无法产生类似App Store一样的用户黏性。怎么样教育用户用自家的market是最大的问题,让我们期待中国的android市场是如何演绎他们自己的故事。当然APP 虎的软件在各类市场都可以通过搜索APPhu下载。

posted @ 2010-11-22 17:41 小菜毛毛 阅读(324) | 评论 (0)编辑 收藏

http://www.iteeyan.com/2010/07/play-android-app-on-emulator/

前几天,Jackeroo给大家介绍了一个Android模拟器,可以让大家在PC机上玩Android 2.2。不过,该模拟器中少了一个精华的东西,那就是“Android Market(电子市场)”。目前,iPhone手机玩的是操控感、时尚,而Android手机玩的则是软件,少了“Android Market”的Android模拟器,无异于自废了一半的功力……

其实,要想在Android 2.2模拟器中使用“Android Market(电子市场)”,认真说来还是有点麻烦。网上虽然也有地方介绍过,但很多细节部分语焉不详。Jackeroo就以自己的实战操作,帮助大家温习一下。

Step 01 新建Android 2.2虚拟机

首先,安装Android SDK,新建一台Android 2.2虚拟机。不知道该去哪里下载Android SDK或者不清楚该如何使用虚拟机的朋友,请先阅读“Google手机免费玩·在PC上装Android 2.2”博文。

PlayAndroidAppOnEmulator 01 393x500 PC上试玩Android Market

Step 02 命令行方式启动新建虚拟机

把SDK包下的System.img文件(F:\android-sdk-windows\platforms\android-8\images)拷贝到的%UserProfile%\.android\avd\Android-2.2下。

然后打开命令行窗口,切换到SDK包的Tools目录下,加参数“-partition-size 96”启动虚拟机,才能让/system有足够的空间安装“Android Market(电子市场)”。

cd /d f:\android-sdk-windows\tools

emulator.exe -avd Android-2.2 -partition-size 96

PlayAndroidAppOnEmulator 02 500x326 PC上试玩Android Market

Step 03 让Android启动Checkin服务

要正常使用“Android Market(电子市场)”,必须启动Checkin服务。等Android 2.2虚拟机启动完毕,看到正常的界面。

PlayAndroidAppOnEmulator 03 500x354 PC上试玩Android Market

这时候,我们可以把配置文件build.prop取回来编辑(如果你有真实的Android连在电脑上,一定要先取下来再进行以下操作)。

cd /d f:\android-sdk-windows\tools

adb pull /system/build.prop .

PlayAndroidAppOnEmulator 04 500x326 PC上试玩Android Market

注意:第一次执行adb指令,会加载adb相关服务,然后提示“device offline(设备不在线)”。此时,需要再次执行上面的adb指令就可以了。

这样一来,build.prop就放在了f:\android-sdk-windows\tools目录下,用文本编辑软件比如EmEditor、UltraEdit之类的打开它。将“ro.config.nocheckin=yes”前面加“#”号注释掉。

#ro.config.nocheckin=yes

然后再传到Android虚拟机上,重新启动虚拟机,Checkin服务就启动了(在上传之前,需要执行“adb remount”指令使/system目录可写)。

adb remount
adb push build.prop /system/build.prop

PlayAndroidAppOnEmulator 05 500x326 PC上试玩Android Market

Step 04 安装“Android  Market”到虚拟机

首先,下载一个为各种手机开发的定制版Android 2.2,比如Jackeroo曾经用过的Android 2.2 for HTC。将它解压缩,将system/app/GoogleServicesFramework.apk 和system/app/Vending.apk放到f:\android-sdk-windows\tools下。

Android 2.2 for Legend :远程下载

然后执行以下指令安装这两个apk安装包,并且删除Android虚拟机上的SdkSetup.apk(注意大小写):

adb push GoogleServicesFramework.apk /system/app
adb push Vending.apk /system/app
adb shell rm /system/app/SdkSetup.apk

PlayAndroidAppOnEmulator 06 500x326 PC上试玩Android Market

Step 05 清理现场

关闭虚拟机, 把产生的 image: userdata-qemu.img, userdata.img, cache.img都删除,重新启动虚拟机它就会自动初始化。

Step 06 “Android Market”现身

打开SDK Setup.exe,按照常规方式启动刚才新创建的Android 2.2虚拟机,就可以看到“Android Market”。

PlayAndroidAppOnEmulator 07 500x354 PC上试玩Android Market

点击“Market”,就需要进行Google登录了,用你自己的Google账号登录吧。

PlayAndroidAppOnEmulator 08 500x354 PC上试玩Android Market

登录以后,理论上说就可以使用“Android Market(电子市场)”尝试各种软件了,但由于网络无法连接,暂时还搜索不到。

有连接上的朋友,请告诉我解决方法。 

posted @ 2010-11-22 16:56 小菜毛毛 阅读(592) | 评论 (0)编辑 收藏

http://dev.10086.cn/cmdn/bbs/thread-17136-1-1.html

最近看论坛上有人问如何挂断电话,实际上1.1版本后.Google已经把该API隐藏掉
今天看资料,发现可以通过AIDL(Android远程方法)及反射,调用hide API,废话不多说了.附上过程

一:在你的项目中新建包com.android.internal.telephony,因为要使用AIDL,该包与ITelephony.aidl一致
    在该包下新建文件ITelephony.aidl

首先

package com.android.internal.telephony;
/* * Copyright (C) 2007 The Android Open Source Project
* * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
* * [url=http://www.apache.org/licenses/LICENSE-2.0]http://www.apache.org/licenses/LICENSE-2.0[/url]
* * Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/**
* Interface used to interact with the phone. Mostly this is used by the
* TelephonyManager class. A few places are still using this directly.
* Please clean them up if possible and use TelephonyManager insteadl.
* * {@hide}
*/
interface ITelephony {
/** * End call or go to the Home screen *
* @return whether it hung up
*/
boolean endCall();
/** * Answer the currently-ringing call.
* * If there's already a current active call, that call will be
* automatically put on hold. If both lines are currently in use, the
* current active call will be ended. *
* TODO: provide a flag to let the caller specify what policy to use
* if both lines are in use. (The current behavior is hardwired to
* "answer incoming, end ongoing", which is how the CALL button
* is specced to behave.) *
* TODO: this should be a oneway call (especially since it's called
* directly from the key queue thread). */
void answerRingingCall();
}   
 
之后会在gen下面自动生成ITelephony.java
二.通过反射生成ITelephony实例
TelephonyManager telMgr = (TelephonyManager)getSystemService(
TELEPHONY_SERVICE);
//初始化iTelephony
Class <TelephonyManager> c = TelephonyManager.class;
Method getITelephonyMethod = null;
try {
       getITelephonyMethod = c.getDeclaredMethod("getITelephony", (Class[])null);
       getITelephonyMethod.setAccessible(true);
} catch (SecurityException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (NoSuchMethodException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
try {
        iTelephony = (ITelephony) getITelephonyMethod.invoke(telMgr, (Object[])null);
} catch (IllegalArgumentException e) {
// TODO Auto-generated catch block
      e.printStackTrace();
} catch (IllegalAccessException e) {
// TODO Auto-generated catch block
      e.printStackTrace();
} catch (InvocationTargetException e) {
// TODO Auto-generated catch block
      e.printStackTrace();
}
这样可以调用iTelephony的endCall()方法
三.在AndroidManifest.xml中增加权限
  <uses-permission android:name="android.permission.CALL_PHONE"/>
posted @ 2010-11-22 16:11 小菜毛毛 阅读(1011) | 评论 (0)编辑 收藏

     摘要: http://blog.csdn.net/maxleng/archive/2010/04/15/5490770.aspx IPC框架分析 Binder,Service,Service manager   我首先从宏观的角度观察Binder,Service,Service Manager,并阐述各自的概念。从Linux的概念空间中,Android的设计Acti...  阅读全文
posted @ 2010-11-21 21:13 小菜毛毛 阅读(945) | 评论 (0)编辑 收藏

     摘要: 建立AIDL服务的步骤(3) (4)编写一个MyService类,代码如下: package net.blogjava.mobile.complex.type.aidl;     import java.util.HashMap;   import java.util.Map; &nb...  阅读全文
posted @ 2010-11-19 17:09 小菜毛毛 阅读(261) | 评论 (0)编辑 收藏

仅列出标题
共17页: 上一页 1 2 3 4 5 6 7 8 9 下一页 Last