我曾经的Android应用开发(二)

以前做Android开发的时候没怎么做笔记,也没写博客,有什么需要记的东西都是这个word放一点,那个txt放一点,现在都不知道到哪里找了,不过总归还是找到一两个word,整理了一下,便有了这篇文章,其中有自己的一些领悟,也有从互联网上摘抄的东西。

(一)关于Activity的启动问题:

1、Activity从创建到进入运行态所触发的事件onCreate()-->onStart()-->onResume()

2、从运行态到停止态所触发的事件 onPause()--->onStop()

3、从停止态到运行态所触发事件 onRestart()-->onStart()--->onResume()

4、从运行态到暂停态所触发事件 onPause()

5、从暂停态到运行态所触发事件 onResume()

(二)关于Service启动问题

使用intent.startService() 启动Service: Service与Activity没有关系,也没有通信,就算Activity退出了,Service可能还在。

intent.startService() ->onCreate()- >onStartCommand()->Service running
intent.stopService() | ->onDestroy() ->Service stop 
使用intent.bindService()启动Service:Service与Activity有通信

intent.bindService()->onCreate()->onBind()->Service running
onUnbind() -> onDestroy() ->Service stop


(三)关于Notification通知

Notification就是手机上方经常出现的通知,由于Notification可以与应用程序脱离。也就是说,即使应用程序被关闭,Notification仍然可以显示在状态栏中。就像短信应用没有启动,但是手机上方会出现通知。当应用程序再次启动后,又可以重新控制这些Notification。如清除或替换它们。因此,需要创建一个PendingIntent对象。该对象由Android系统负责维护,因此,在应用程序关闭后,该对象仍然不会被释放。这里说一下PendingIntent和Intent的区别:An Intent is something that is used right now; a PendingIntent is something that may create an Intent in the future. You will use a PendingIntent with Notifications, AlarmManager, etc.

(四)关于程序数据类型

Sqlite只支持null,integer,real,text和blob(二进制对象)数据类型,也兼容其他的varchar等等,但实际上在运算的时候会自动转换为五种类型,特点:保存任何类型的数据到任何字段中

(五)关于webwiew

在WebView的设计中,不是什么事都要WebView类干的,有些杂事是分给其他人的,这样WebView专心干好自己的解析、渲染工作就行了。WebViewClient就是帮助WebView处理各种通知、请求事件的,具体来说包括:

onLoadResource 
onPageStart 
onPageFinish 
onReceiveError 
onReceivedHttpAuthRequest 

WebChromeClient是辅助WebView处理Javascript的对话框,网站图标,网站title,加载进度等

onCloseWindow(关闭WebView)
 onCreateWindow() 
onJsAlert (WebView上alert是弹不出来东西的,需要定制你的WebChromeClient处理弹出) 
onJsPrompt 
onJsConfirm 
onProgressChanged 
onReceivedIcon 
onReceivedTitle

关于webview打开文件的写法:

webView.loadUrl("file:///android_asset/index.html"); -----打开本包内asset目录下的index.html文件 
webView.loadUrl("content://com.android.hello/sdcard/index.html");-----打开本地sd卡内的index.html文件

android能操作文件夹只有两个地方:
1.sdcard
2./data/<package_name>/
详见apidoc:
docs/guide/topics/data/data-storage.html#filesExternal

Environment.getRootDirectory()是得到系统/System目录

Environment.getExternalStorageState()是得到系统/Sdcard目录,需要判断是否有Sdcard

Environment.getDataDirectory()是得到/Data目录;


WebView加载网页时前面的那一段空白怎么填补?Toast不能定义时间,所以不行,会在加载没有完成的时候就灭了。可以在背景用一个View试试。每次加载开始时就让WebView消失而View显示。

关于网页加载进度提示的问题:

Toast提示网页加载进度可以在WebViewClient.onPageStart方法里面设置开始show,在WebChromeClient.onProgressChanged方法里面progress==100的时候结束cancel,其中设置WebChromeClient有如下方法webView.setWebChromeClient(WebChromeClient).

(六)关于程序意外退出后的保存问题

当你的程序中某一个ActivityA在运行时中,主动或被动地运行另一个新的ActivityB ,这个时候A会执行:

public
void onSaveInstanceState(Bundle outState) {   
    super.onSaveInstanceState(outState);   
    outState.putLong("id", 1234567890);   
}   

B完成以后又会来找A,这个时候就有两种情况,一种是A被回收,一种是没有被回收,被回收的A就要重新调用onCreate()方法,不同于直接启动的是这回onCreate()里是带上参数savedInstanceState,没被收回的就还是onResume就好了。savedInstanceState是一个Bundle对象,你基本上可以把他理解为系统帮你维护的一个Map对象。在onCreate()里你可能会用到它,如果正常启动onCreate就不会有它,所以用的时候要判断一下是否为空。

if(savedInstanceState != null){   
     long id = savedInstanceState.getLong("id");   
}   

if(savedInstanceState != null){     long id = savedInstanceState.getLong("id");}

就像官方的Notepad教程里的情况,你正在编辑某一个note,突然被中断,那么就把这个noteid记住,再起来的时候就可以根据这个id去把那个note取出来,程序就完整一些。这也是看你的应用需不需要保存什么,比如你的界面就是读取一个列表,那就不需要特殊记住什么,哦,没准你需要记住滚动条的位置...

(七)关于摄像头

摄像头的实现有CameraSurfaceViewSurfaceHolder,SurfaceHolder.Callback,PictureCallbackCamera.ParametersDisplay

首先SurfaceView相当于那个画面,也就是取景框。而设置SurfaceView需要一个SurfaceHolder,Camera通过setPreviewDisplay(SurfaceHolder)的方法来连接SurfaceHolder并通过它来控制SurfaceViewSurfaceHolder.CallbackSurfaceHolder用来显示SurfaceView数据的接口,它实现了三个方法:

surfaceCreated()SurfaceView被创建时调用。

surfaceChanged()SurfaceView发生改变时调用.

surfaceDestroyed()surfaceView销毁时进行调用.

SurfaceHolder通过addCallBack()方法将相应的接口绑定到它身上.

PictureCallbackCamera调用拍照方法takePicture(,,PictureCallback)的接口类,拍照的数据就在这个类里面的OnPictureTake()方法里面实现,对照片数据进行解析和存储。

Camera.Parameters是对Camera的一些拍照参数进行设置,如照片大小,照片格式等等。

Display是得到系统屏幕的一些参数.用来设置Camera的参数跟系统屏幕符合,如照片大小是否跟系统屏幕一样大.

默认情况下照相机的取景方向是向左旋转90°的。只设置orientation屏幕能转过来,但是拍出来的照片还是向左旋转90°的。

parameters.set("orientation","portrait");//"portrait"是竖向,仅仅是试图的方向

parameters.setRotation(90);//应该是旋转找出来的照片方向

相机旋转依赖于不同的设备和不同的版本,下面是一个国外论坛比较经典的总结(http://code.google.com/p/android/issues/detail?id=1193#c42):

Version1.6:tofixtheRotationIssue,anditisgoodformostofdevices

if (getResources().getConfiguration().orientation == Configuration.ORIENTATION_PORTRAIT)   {       
    p.set("orientation", "portrait");      p.set("rotation",90);    }   
if (getResources().getConfiguration().orientation == Configuration.ORIENTATION_LANDSCAPE)    {                    
  p.set("orientation", "landscape");         
  p.set("rotation", 90);   
 }

Version2.1:dependonkindofdevices,forexample,CanntfixtheissuewithXPeriaX10,butitisgoodforX8,andMini

Camera.Parameters parameters = camera.getParameters();
parameters.set("orientation", "portrait");
camera.setParameters(parameters);

Version2.2:notforalldevices

camera.setDisplayOrientation(90);


在做照相机程序的时候,一直不知道怎么在SurfaceView里面添加按钮,SurfaceView一般是全屏显示的,下面的FrameLayout是重点

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="vertical"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent"
    >
      <FrameLayout
            android:layout_width="fill_parent"
            android:layout_height="wrap_content"
            android:layout_weight="1" 
            >
  <SurfaceView
  android:id="@+id/surfaceView"
  android:layout_width="fill_parent"
  android:layout_height="fill_parent"
  >
  </SurfaceView>
    </FrameLayout> 
    <LinearLayout android:id="@+id/LinearLayout01"  
        android:layout_width="wrap_content" android:layout_height="wrap_content" 
android:orientation="horizontal">   
        <Button android:id="@+id/Button02" android:layout_width="wrap_content"  
            android:layout_height="wrap_content" android:layout_weight="1" android:text="返
回"></Button>  
    </LinearLayout>
</LinearLayout>

布局的问题:如果是两个空间来平分宽度,就用LinearLayout,然后两个控件都设置layout_weight=1,这样就可以很好的平分宽度了;如果三个平分的话就在中间那个控件单独弄一个LinearLayout或者其他的layout,这个layoutandroid:layout_weight="1"

,这样的话这个layout就有2/3的宽度,然后反正这个layout里面的控件设置属性android:layout_centerInParent="true"就能够在中间了


关于图像裁剪:

调用系统裁剪图片的主要代码是下面这些代码,这里不能设置得到哪些图片,应该是得到所有的图片,裁剪后可以自己设置路径和文件名

Intent intent = new Intent("com.android.camera.action.CROP"); 
intent.setDataAndType(photoUri, "image/*"); 
intent.putExtra("crop", "true"); //crop=true有这句才能出来最后的裁剪页面.

intent.putExtra("aspectX", 1);

intent.putExtra("aspectY", 1); intent.putExtra("outputX", 80); intent.putExtra("outputY", 80); intent.putExtra("return-data", true); intent.putExtra("output", Uri.fromFile(tempFile)); intent.putExtra("outputFormat", "JPEG"); startActivityForResult(intent, requestCode);


(八)关于GPS

只有启用了这个函数LocationManager.requestLocationUpdates(……);GPs才会起作用,这是一个请求更新函数,里面有一个监听器的参数,能够监听到位置的改变。

android的位置提供有两个,gpsnetwork,其中network包括wifi和基站等网络方式,gps每次获取的位置一般都是不同的,network获取的经纬度在一般很少改变,如果从wifi切换到移动网络,则获取的经纬度会发生变化,反之从移动网络切换到wifi,获取的经纬度也会发生变化,但是如果一直在移动网络,或者一直在wifi网络,则获取的经纬度在几次之内是很少会改变的。当然如果从一个wifi热点切换到另一个wifi热点,获取的经纬度肯定会变化。不变化的是在一个wifi热点内的周围移动获取的经纬度是基本不变的。在不同网络切换到时候获取的经纬度可能在一段时间内会变化,但最终会趋于稳定。例如:

我一开始用wifi获取的是23.0984789--113.3162901wifi),之后关闭wifi,获取的是23.0981123--113.3154123(基站),(中间还有一两个其他的值,也可以没有)最后趋于23.0981189--113.3154709(基站),开启wifi后,得到23.0984123--113.3162123wifi),(中间还有几个值,也可以没有),最后趋于23.0984789--113.3162901wifi),注意到最后趋于稳定的值都是一样的。

(九)关于游戏开发

1被动更新画面的。比如棋类,这种用view就好了。因为画面的更新是依赖于onTouch来更新,可以直接使用invalidate。因为这种情况下,这一次Touch和下一次的Touch需要的时间比较长些,不会产生影响。

2surfaceview中确实有onDraw这个方法,但是你surfaceview不会自己去调用!!!放在线程中不断调用的,一定要注意!!在继承view中,因为onDraw方法是系统自动调用的,不像在surfaceview这里这样去在run里面自己去不断调用,在view中我们可以抵用invalidate()/postInvalidate()这两种方法实现让系统调用onDraw方法,这里也是和surfaceview中的不同之一!

3这里canvas.save();canvas.restore();是两个相互匹配出现的,作用是用来保存画布的状态和取出保存的状态的。这里稍微解释一下,当我们对画布进行旋转,缩放,平移等操作的时候其实我们是想对特定的元素进行操作,比如图片,一个矩形等,但是当你用canvas的方法来进行这些操作的时候,其实是对整个画布进行了操作,那么之后在画布上的元素都会受到影响,所以我们在操作之前调用canvas.save()来保存画布当前的状态,当操作之后取出之前保存过的状态,这样就不会对其他的元素进行影响


(十)其他知识点

1)Android基于http上传文件到服务器端要分析文件的流格式,自己来组装流格式来发送到服务器端。在服务器端通过开源的一个组件commonsfileupload来实现文件流的解析。

2)真机和模拟器访问本机都是用10.0.2.2,因为127.0.0.1是模拟器本身的地址。但是如果是真机测试,则服务器的地址就是本机自己的ip地址

3) 要想监听电话的来电状态,信号强度等,可以通过 TelephonyManager 来实现,具体是得到一个电话管理器对象 TelephonyManager ,然后通过listen()方法设置相应的器PhoneStateListener来监听电话的各种状态.PhoneStateListener是里面有相应的回调函数,如OnSignaStrengthsChanged()方法是当电话的强度改变时就会调用。





你可能感兴趣的:(android)