Android知识点总结

Android知识总结:(内容有很多还在补全中)

Activity:

用来跟用户来进行交互的界面,使用过程中要注意的就是他的生命周期,

onCreate的时候只是加载布局文件,进行控件的初始化,这个时候用户还看不到界面,只有在onStart以后,用户才能看的到界面,但是还不能跟界面进行交互。也就是这一步界面的初始化都已经完成,当onResume执行以后,界面可以接收用户的交互,点击,触摸等手势操作。

OnPause, onStop的调用是在当界面从新边的不可见的时候调用,(点home键,点返回键,只要是界面边的不可见,那么就肯定会调用它)

而在销毁一个Activity的时候会依次调用 onPause,onStop,onDestry。

使用好Activity的什么周期,结合Fragment的生命周期可以实现比较好的用户体验的功能。

当Activity界面上弹出一个Dialog的时候,不会对Activity造成影响。

 

Service:

Service顾名思义,就是一个服务,他是Android中一个运行在后台的组件,

Service其实也是运行在主线程中,我们可以通过Thread.currentThread().getName()

获取到当前线程的名称,可以发现是在主线程中,但是Service一般用来做一些后台的,耗时的操作,这个是通过在他里边开线程进行实现的。

Android 还提供了IntentService,这个Service中会自己开线程,也就是操作都是在子线程中。

 

关于Service使用的场景很多,但是常见的是:音乐播放器,做轮询,做心跳,做下载管理器等等。

使用方式有俩种:

直接startService,这个是通过Intent来进行直接启动。

Intent intent = new Intent(this,Service.class);
startService(intent);

 

还有就是绑定service,通过

@Override
public boolean bindService(Intent service, ServiceConnection conn,
        int flags) {
    return mBase.bindService(service, conn, flags);
}

 

这俩种方式的区别就是startService启动了service以后,交互的实现比较复杂,

比如音乐播放器的后台播放,想实现暂停的功能,他的播放是在Service中,那么暂停的时候是没有办法控制的,但是用bindService的话,就可以通过ServiceConnection

对象来获取service对象,就可以调用service中的方法,然后进行控制。

 

BroadCast:

①广播接收器是一个专注于接收广播通知信息,并做出对应处理的组件。很多广播是源自于系统代码的──比如,通知时区改变、电池电量低、拍摄了一张照片或者用户改变了语言选项。应用程序也可以进行广播──比如说,通知其它应用程序一些数据下载完成并处于可用状态。
②应用程序可以拥有任意数量的广播接收器以对所有它感兴趣的通知信息予以响应。所有的接收器均继承自BroadcastReceiver基类。
③广播接收器没有用户界面。然而,它们可以启动一个activity来响应它们收到的信息,或者用NotificationManager来通知用户。通知可以用很多种方式来吸引用户的注意力──闪动背灯、震动、播放声音等等。一般来说是在状态栏上放一个持久的图标,用户可以打开它并获取消息。

 

Android中的广播事件有两种,一种就是系统广播事件,比如:ACTION_BOOT_COMPLETED(系统启动完成后触发),ACTION_TIME_CHANGED(系统时间改变时触发),ACTION_BATTERY_LOW(电量低时触发)等等。另外一种是我们自定义的广播事件。

 

广播事件的流程
①注册广播事件:注册方式有两种,一种是静态注册,就是在AndroidManifest.xml文件中定义,注册的广播接收器必须要继承BroadcastReceiver;另一种是动态注册,是在程序中使用Context.registerReceiver注册,注册的广播接收器相当于一个匿名类。两种方式都需要IntentFIlter
②发送广播事件:通过Context.sendBroadcast来发送,由Intent来传递注册时用到的Action。
③接收广播事件:当发送的广播被接收器监听到后,会调用它的onReceive()方法,并将包含消息的Intent对象传给它。onReceive中代码的执行时间不要超过5s,否则Android会弹出超时dialog。

下面我通过代码演示自定义广播事件和系统广播事件的使用。完整代码下载地址:android_broadcastreceiver.rar

Step1:在MainActivity的onStart方法中注册广播事件。静态注册方式是在AndroidManifest.xml文件中。

Step2: 点击相应按钮后会触发相应的方式来发送广播消息。

[java]  view plain  copy
  1. /** 
  2.  * MainActivity 
  3.  * @author zuolongsnail 
  4.  * 
  5.  */  
  6. public class MainActivity extends Activity {  
  7.     private Button sendStaticBtn;  
  8.     private Button sendDynamicBtn;  
  9.     private Button sendSystemBtn;  
  10.     private static final String STATICACTION = "com.byread.static";  
  11.     private static final String DYNAMICACTION = "com.byread.dynamic";  
  12.     // USB设备连接  
  13.     private static final String SYSTEMACTION = Intent.ACTION_POWER_CONNECTED;  
  14.     @Override  
  15.     public void onCreate(Bundle savedInstanceState) {  
  16.         super.onCreate(savedInstanceState);  
  17.         setContentView(R.layout.main);  
  18.         sendStaticBtn = (Button) findViewById(R.id.send_static);  
  19.         sendDynamicBtn = (Button) findViewById(R.id.send_dynamic);  
  20.         sendSystemBtn = (Button) findViewById(R.id.send_system);  
  21.         sendStaticBtn.setOnClickListener(new MyOnClickListener());  
  22.         sendDynamicBtn.setOnClickListener(new MyOnClickListener());  
  23.         sendSystemBtn.setOnClickListener(new MyOnClickListener());  
  24.     }  
  25.     class MyOnClickListener implements OnClickListener{  
  26.         @Override  
  27.         public void onClick(View v) {  
  28.             // 发送自定义静态注册广播消息  
  29.             if(v.getId() == R.id.send_static){  
  30.                 Log.e("MainActivity""发送自定义静态注册广播消息");  
  31.                 Intent intent = new Intent();  
  32.                 intent.setAction(STATICACTION);  
  33.                 intent.putExtra("msg""接收静态注册广播成功!");  
  34.                 sendBroadcast(intent);  
  35.             }  
  36.             // 发送自定义动态注册广播消息  
  37.             else if(v.getId() == R.id.send_dynamic){  
  38.                 Log.e("MainActivity""发送自定义动态注册广播消息");  
  39.                 Intent intent = new Intent();  
  40.                 intent.setAction(DYNAMICACTION);  
  41.                 intent.putExtra("msg""接收动态注册广播成功!");  
  42.                 sendBroadcast(intent);  
  43.             }  
  44.             // 发送系统动态注册广播消息。当手机连接充电设备时会由系统自己发送广播消息。  
  45.             else if(v.getId() == R.id.send_system){  
  46.                 Log.e("MainActivity""发送系统动态注册广播消息");  
  47.                 Intent intent = new Intent();  
  48.                 intent.setAction(SYSTEMACTION);  
  49.                 intent.putExtra("msg""正在充电。。。。");  
  50.             }  
  51.         }  
  52.     }  
  53.     @Override  
  54.     protected void onStart() {  
  55.         super.onStart();  
  56.         Log.e("MainActivity""注册广播事件");  
  57.         // 注册自定义动态广播消息  
  58.         IntentFilter filter_dynamic = new IntentFilter();  
  59.         filter_dynamic.addAction(DYNAMICACTION);  
  60.         registerReceiver(dynamicReceiver, filter_dynamic);  
  61.         // 注册系统动态广播消息  
  62.         IntentFilter filter_system = new IntentFilter();  
  63.         filter_system.addAction(SYSTEMACTION);  
  64.         registerReceiver(systemReceiver, filter_system);  
  65.     }  
  66.     private BroadcastReceiver dynamicReceiver = new BroadcastReceiver() {  
  67.           
  68.         @Override  
  69.         public void onReceive(Context context, Intent intent) {  
  70.             Log.e("MainActivity""接收自定义动态注册广播消息");  
  71.             if(intent.getAction().equals(DYNAMICACTION)){  
  72.                 String msg = intent.getStringExtra("msg");  
  73.                 Toast.makeText(context, msg, Toast.LENGTH_SHORT).show();  
  74.             }  
  75.         }  
  76.     };  
  77.     private BroadcastReceiver systemReceiver = new BroadcastReceiver() {  
  78.           
  79.         @Override  
  80.         public void onReceive(Context context, Intent intent) {  
  81.             Log.e("MainActivity""接收系统动态注册广播消息");  
  82.             if(intent.getAction().equals(SYSTEMACTION)){  
  83.                 String msg = intent.getStringExtra("msg");  
  84.                 Toast.makeText(context, msg, Toast.LENGTH_SHORT).show();  
  85.             }  
  86.         }  
  87.     };  
  88. }  

Step3:接收广播消息。以下为两个静态注册的广播接收器。

[java]  view plain  copy
  1. /** 
  2.  * 自定义静态注册广播消息接收器 
  3.  * @author zuolongsnail 
  4.  * 
  5.  */  
  6. public class StaticReceiver extends BroadcastReceiver {  
  7.   
  8.     @Override  
  9.     public void onReceive(Context context, Intent intent) {  
  10.         String msg = intent.getStringExtra("msg");  
  11.         Toast.makeText(context, msg, Toast.LENGTH_SHORT).show();  
  12.     }  
  13. }  

[java]  view plain  copy
  1. /** 
  2.  * 系统静态注册广播消息接收器 
  3.  *  
  4.  * @author zuolongsnail 
  5.  *  
  6.  */  
  7. public class SystemReceiver extends BroadcastReceiver {  
  8.   
  9.     @Override  
  10.     public void onReceive(Context context, Intent intent) {  
  11.         if (intent.getAction().equals(Intent.ACTION_BATTERY_LOW)) {  
  12.             Log.e("SystemReceiver""电量低提示");  
  13.             Toast.makeText(context, "您的手机电量偏低,请及时充电", Toast.LENGTH_SHORT).show();  
  14.         }  
  15.     }  
  16. }  

下面是AndroidManifest.xml文件:

[xhtml]  view plain  copy
  1. <?xml version="1.0" encoding="utf-8"?>  
  2. <manifest xmlns:android="http://schemas.android.com/apk/res/android"  
  3.     package="com.byread" android:versionCode="1" android:versionName="1.0">  
  4.     <application android:icon="@drawable/icon" android:label="@string/app_name">  
  5.         <activity android:name=".MainActivity" android:label="@string/app_name">  
  6.             <intent-filter>  
  7.                 <action android:name="android.intent.action.MAIN" />  
  8.                 <category android:name="android.intent.category.LAUNCHER" />  
  9.             </intent-filter>  
  10.         </activity>  
  11.         <!-- 注册自定义静态广播接收器 -->  
  12.         <receiver android:name=".StaticReceiver">  
  13.             <intent-filter>  
  14.                 <action android:name="com.byread.static" />  
  15.             </intent-filter>  
  16.         </receiver>  
  17.         <!-- 注册系统静态广播接收器 -->  
  18.         <receiver android:name=".SystemReceiver">  
  19.             <intent-filter>  
  20.                 <action android:name="android.intent.action.BATTERY_LOW" />  
  21.             </intent-filter>  
  22.         </receiver>  
  23.     </application>  
  24. </manifest>  



ContentProvider:

ContentProvider(内容提供者)是Android中的四大组件之一。主要用于对外共享数据,也就是通过ContentProvider把应用中的数据共享给其他应用访问,其他应用可以通过ContentProvider对指定应用中的数据进行操作。ContentProvider分为系统的和自定义的,系统的也就是例如联系人,图片等数据。

 

以下这段是Google Doc中对ContentProvider的大致概述。
内容提供者将一些特定的应用程序数据供给其它应用程序使用。数据可以存储于文件系统、SQLite数据库或其它方式。内容提供者继承于ContentProvider 基类,为其它应用程序取用和存储它管理的数据实现了一套标准方法。然而,应用程序并不直接调用这些方法,而是使用一个 ContentResolver 对象,调用它的方法作为替代。ContentResolver可以与任意内容提供者进行会话,与其合作来对所有相关交互通讯进行管理。


Gallery的使用

 在Android中,画廊控件Gallery用来显示图片列表,可以用手指直接拖动图片左右移动。Gallery只能水平显示一行,且Gallery列表中的图片会根据不同的拖动情况向左或向右移动,直到显示到最后一个图片为止。

 

使用模式:

适配器模式:

      Gallery对象,适配器对象。

监听:onItemClickListener

ListView:

GridView:

ScrollView:

ProgressBar:

ToolBar:

ImageView:

TextView

Button: 

ViewPager:

WebView:

LinearLayout:

RelativeLayout:

TabLayout:

FrameLayout:

AbsoluteLayout:

Android Fragment的使用以及生命周期。

1、onAttach():当Fragment与依赖的activity产生关联时回调的函数
2、onCreate():创建Fragment时回调的函数
3、onCreateView():当Fragment创建绘制view视图时回调的函数,返回值为view
4、onActivityCreated():表示与Fragment依赖的activity创建完成时回调的函数
5、onStart():Fragment能够被用户看到时回调的函数
6、onResume():Fragment获取到用户焦点时回调的函数,可以与用户交互
7、onPause():Fragment失去用户焦点时回调的函数
8、onStop():Fragment完全被遮挡,不能被用户看到时回调的函数
9、onDestroyView():当Fragment中的视图被销毁时回调的函数,视图移除
10、onDestroy():当Fragment被销毁时回调的函数
11、onDestach():当Fragment与依赖的activity失去关联时回调的函数

Fragment与Fragment之间的交互

方式一:Fragment管理器对象中根据fragment的id获取对象后调用对象的函数
RightFragment   right=getFragmentMenagr().findFragmentById();
方式二:直接得到第二个fragment的控件
TextView   tv=getFragmentMenage().findFragmentById().getView().findViewById();
tv.settext();
方式三:
TextView  tv=getActivity().findViewById(R.id.tv);

Fragment 与Activity的交互

(1)Activity向引入的Fragment传值
存值时:setArguments(Bundle bundle);
取值时:Bundle  bundle=getArguments();
activity中:
Fragment    f=new  Fragment();
Bundle bundle=new Bundle();
bundle.putString(key,value);
bundle.putInt();
f.setArguments(bundle);
Fragment中:
Bundle    bundle=getArguments();
bundle.getString(key);
(2) Fragment向关联的Activity传值(接口回调)
Fragment中:
    public  interface   CallBack{
        public void send(XXX);    
}
需要在传递数据之前:实例化CallBack接口的子类     .send(XXX);

Android Handler的使用场景以及源码实现流程:

Handler机制的原理:http://blog.csdn.net/itachi85/article/details/8035333

内存泄漏:http://www.cnblogs.com/xujian2014/p/5025650.html

一、handler的使用步骤
1、在工作线程中创建消息对象
(1)第一种方式
Message message=new Message();
(2)第二种方式(常用):在消息池中获取消息对象 判断消息池是否存在可用的message,如果存在则取出使用,否则创建并放回
Message message1=Message.obtain();
2、将需要传递的数据封装到message中
(1)第一种方式:
 
 
//what变量主要用来标示消息多个工作线程向ui线程发送消息,或是一个工作线程多次向ui线程发送消息时,用what进行区分
message.what=1;
//如果需要向ui线程发送整型数据,可以使用arg1arg2
message. arg1 = 100 ;
message. arg2 = 200 ;
//如果需要向ui线程发送类类型的数据,可以使用obj
message. obj = " 测试工作线程 " ;
(2)第二种方式:将需要传递的数据先封装到Bundle中再进行传递
Bundle bundle=new Bundle();
bundle.putInt("in",500);
bundle.putString("str","nihao");
message.setData(bundle);//bundle存储到message
handler.sendMessage(message);
3、在工作线程中通过handler对象将message对象进行传递,并在主线程中接受进行处理
创建Handler对象,往哪个线程发送消息,就在该线程实例化Handler对象
private Handler handler=new Handler(){
@Override
public void handleMessage(Message msg) {
switch (msg.what){
case 1:
int num1=msg.arg1;
int num2=msg.arg2;
String str= (String) msg.obj;
//tv.setText(num1+","+num2+","+str);

Bundle bundle=msg.getData();//获取传递的bundle对象
int i=bundle.getInt("in",0);
String str1=bundle.getString("str");
tv.setText("i="+i+",str1="+str1);
break;
}
}
}
;

二、Handler源码解析
1、Handler的通信机制:
    Handler机制中工作线程和主线程之间通信主要是靠收发消息进行通信,工作线程中执行完成耗时操作,需要将结果数据封装到Message消息对象中,由Handler进行发送,Handler在哪个线程中创建就与该线程中的MessageQueue相关联,工作线程使用Handler发送消息时就发送到Handler相关联的消息队列中,发送的message统一由handler相关联的MessageQueue消息队列进行管理;主线程中Handler处理消息时,底层会有Looper对象循环在Handler相关联的MessageQueue消息队列中取出消息交给Handler调用handlerMessage()方法处理消息;

2、Handler对象在创建(new)时就与当前线程的Looper  MessageQueue相关联,这样通过该handler对象发送和处理消息都是操作关联的MessageQueue中的消息
简单来说:Handler在哪个线程new就是处理哪个线程MessageQueue消息队列中的消息

Android的Activity的启动模式分析以及代码中动态设置启动模

    什么是启动模式?表示activity启动后在回退栈中如何进行管理;
设置启动模式:<activity  android:launchMode="standard、singleTop、singleTask、singleInstance">
1、standard 标准启动模式    默认启动模式
    standard 启动模式下 会按照activity的启动的顺序依次创建activity的实例并且压入到回退栈中;
2、SingleTop 单顶模式(栈顶唯一模式)
    SingleTop 启动模式下 启动一个activity的实例时 如果发现回退栈的顶端是该activity的实例,将复用该实例,不再创建实例压入栈中;
    如果需要避免某个antivity被重复多次启动时,可以设置为SingleTop   例如:系统短信界面
3、singleTask 栈内唯一模式
    singleTask 启动模式下 启动一个activity实例时 检查回退栈中是否存在该activity的实例,如果实例存在 回退栈中会清除该activity实例最早出现位置以上的所有的activity的实例,以保证该activity在回退栈中的唯一性;
    如果存在比较耗费系统资源的activity时建议使用singleTask ,例如:浏览器界面
4、singleInstance  单独的回退栈中的单一的实例
    singleInstance  启动模式下 启动一个activity的实例时,会将当前的activity存储到一个单独的回退栈中作为单一的实例;

Android 事件处理,事件拦截:

数据库的使用:

Android Dialog使用,以及源码实现流程

1、setItems(数组的资源id或者字符串类型的数组,每项item的点击事件);普通列表
2、setAdapter(ListAdapter接口SimpleAdapter,每项item的点击事件);适配器列表
3、setSingleChoseItems(数组的资源id或者字符串类型的数组,默认选中的item的下标 都未选中为-1,每项item的点击事件);单选按钮列表
4、setMuliteChoseItems(数据源,boolean类型的数组 要求与数据源长度一致 表示item的选中状态,每项item的监听事件);多选按钮列表
5、setCustomTitle(View)设置自定义Dialog的标题视图
6、setView(View) 设置自定义dialog的内容视图

Android Toast 使用以及源码实现流程(Android Toast自定义)

Android 网络访问:

Android socket编程

Android 多线程:

Android 图片上传,文件上传,文件下载,断点续传:

Android 图片压缩

Android 动画:

帧动画:

补间动画:

属性动画:

属性动画:ValueAnimation

OpenGl使用实现3d效果

Android传感器:

Android的传感器开发

1.1开发传感器应用

开发传感器的步骤如下:

调用Context的getSystemService(Context.SENSOR_SERVICE)方法获取SensorManager对象。

调用SensorManager的getDefaultSensor(int type)方法来获取指定类型的传感器。

一般在Activity的onResume()方法中调用SensorManager的registerListener()为指定传感器注册监听器即可。程序可以通过实现监听器即可获取传感器传回来的数据。

SersorManager提供的注册传感器的方法为registerListener(SensorListenerlistener, Sensor sensor, int rate)该方法中三个参数说明如下:

listener:监听传感器事件的监听器

sensor:传感器对象

rate:指定获取传感器数据的频率

rate可以获取传感器数据的频率,支持如下几个频率值:

SENSOR_DELAY_FASTEST:最快,延迟最小。

SENSOR_DELAY_GAME:适合游戏的频率。

SENSOR_DELAY_NORMAL:正常频率

SENSOR_DELAY_UI:适合普通用户界面的频率。

例:加速度传感器:


<span style="font-size:14px;">AccelerometerTest.java

public class AccelerometerTest extends Activity
    implements SensorEventListener
{
    // 定义系统的Sensor管理器
    SensorManager sensorManager;
    EditText etTxt1;
 
    @Override
    public void onCreate(Bundle savedInstanceState)
    {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);
        // 获取程序界面上的文本框组件
        etTxt1 = (EditText) findViewById(R.id.txt1);
        // 获取系统的传感器管理服务
        sensorManager = (SensorManager) getSystemService(
            Context.SENSOR_SERVICE);
    }
 
    @Override
    protected void onResume()
    {
        super.onResume();
        // 为系统的加速度传感器注册监听器
        sensorManager.registerListener(this,
            sensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER),
            SensorManager.SENSOR_DELAY_GAME);
    }
 
    @Override
    protected void onStop()
    {
        // 取消注册
        sensorManager.unregisterListener(this);
        super.onStop();
    }
 
    // 以下是实现SensorEventListener接口必须实现的方法
    // 当传感器的值发生改变时回调该方法
    @Override
    public void onSensorChanged(SensorEvent event)
    {
        float[] values = event.values;
        StringBuilder sb = new StringBuilder();
        sb.append(X方向上的加速度:);
        sb.append(values[0]);
        sb.append(
Y方向上的加速度:);
        sb.append(values[1]);
        sb.append(
Z方向上的加速度:);
        sb.append(values[2]);
        etTxt1.setText(sb.toString());
    }
 
    // 当传感器精度改变时回调该方法。
    @Override
    public void onAccuracyChanged(Sensor sensor, int accuracy)
    {
    }
}
</span>



 

需要指出的是,传感器的坐标系统与屏幕坐标系统不同,传感器坐标系统的X轴沿屏幕向右;Y轴则沿屏幕向上,Z轴在垂直屏幕向上。

当拿着手机横向左右移动时,可能产生X轴上的加速度;拿着手机前后移动时,可能产生Y轴上的加速度;当拿着手机竖向上下移动时,可能产生Z轴上的加速度。

 

1.2下载和安装SensorSimulator

SensorSimulator是传感器的模拟工具,安装这个模拟工具之后,开发者就可以在Android模拟器上开发、调试传感器应用。

SensorSimulator,由PC端程序和手机端程序组成,当两端的程序运行并建立连接之后,用户可以通过PC端的程序来改变手机的传感数据。

下载和安装SensorSimulator步骤如下:

登录到http://code.google.com/p/openintents/wiki/SensorSimulator站点或FTP上,下载SensorSimulator的最新版本。

下载SensorSimulator工具后,下载完成后得到一个sensorsimulator-2.0-rc1.zip压缩包。解压该文件,得到如下文件结构。

安装SensorSimulator的手机端程序。通过命令窗口进入到上面文件的bin目录下,输入如下命令来安装SensorSimulatorSettings-2.0-rc1.apk文件。adb install SensorSimulatorSettings-2.0-rc1.apk

运行SensorSimulator的PC端程序,通过命令窗口进入到上面文件的bin目录下,并在窗口内执行如下命令:java –jar sensorsimulator-2.0-rc1.jar。运行该程序出现如下界面。

运行SensorSimulator的手机端程序。

在SensorSimulator的手机端程序中填写SensorSimulator的PC端程序的监听IP地址、监听端口。

切换到SensorSimulator的Testting Tab页,单击该Tab里的Connect按钮,SensorSimulator手机端和PC端连接。

 

1.3利用SensorSimulator开发传感器应用

通过使用SensorSimulator,接下来就可以在Android模拟器中开发、调试传感器应用了。不过使用SensorSimulator开发传感器应用与开发真实的传感器应用略有区别。

Android应用必须通过引用外部JAR包的形式来引用SensorSimulator的lib目录下的sensorsimulator-2.0-rc1.jar包。

在应用项目上右键单击选择“Build Path”à “Add External Archives…”,找到sensorsimulator-2.0-rc1.jar所在位置,将其添加到项目中。

应用程序编程使用SensorManagerSimulator代替了原有的SensorManager。

应用程序获取SensorManagerSimulator之后,需要调用connectSimulator()方法连接模拟器。

应用程序编程时所用的Sensor、SensorEvent、 SensorEventListener等不再是Android提供的类,而是由SensorSimulator提供的类。

应用程序需要访问网络的权限。

例:利用传感模拟工具开发加速度传感器:

 


<span style="font-size:14px;">AccelSimulatorTest.java

import org.openintents.sensorsimulator.hardware.SensorManagerSimulator;
import org.openintents.sensorsimulator.hardware.Sensor;
import org.openintents.sensorsimulator.hardware.SensorEvent;
import org.openintents.sensorsimulator.hardware.SensorEventListener;
 
import android.app.Activity;
import android.hardware.SensorManager;
import android.os.Bundle;
import android.widget.EditText;
 
public class AccelSimulatorTest extends Activity
    implements SensorEventListener
{
    // 定义模拟器的Sensor管理器
    private SensorManagerSimulator mSensorManager;
    // 定义界面上的文本框组件
    EditText etTxt1;
 
    @Override
    public void onCreate(Bundle savedInstanceState)
    {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);
        // 获取程序界面的文本框组件
        etTxt1 = (EditText) findViewById(R.id.txt1);
        // 获取传感器模拟器的传感器管理服务
        mSensorManager = SensorManagerSimulator.getSystemService(
            this, SENSOR_SERVICE);
        // 连接传感器模拟器
        mSensorManager.connectSimulator();
    }
 
    @Override
    protected void onResume()
    {
        super.onResume();
        // 为系统的加速度传感器注册监听器
        mSensorManager.registerListener(this,
            mSensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER),
            SensorManager.SENSOR_DELAY_GAME);
    }
 
    @Override
    protected void onStop()
    {
        // 取消注册
        mSensorManager.unregisterListener(this);
        super.onStop();
    }
 
    // 以下是实现SensorEventListener接口必须实现的方法
    // 当传感器的值发生改变时回调该方法
    @Override
    public void onSensorChanged(SensorEvent event)
    {
        float[] values = event.values;
        StringBuilder sb = new StringBuilder();
        sb.append(X方向上的加速度:);
        sb.append(values[0]);
        sb.append(
Y方向上的加速度:);
        sb.append(values[1]);
        sb.append(
Z方向上的加速度:);
        sb.append(values[2]);
        etTxt1.setText(sb.toString());
    }
 
    @Override
    // 当传感器精度改变时回调该方法。
    public void onAccuracyChanged(Sensor sensor, int accuracy)
    {
    }
}
</span>



 

?

1

2

<!-- 通过模拟器调试需要访问网络 -->

    <uses-permission android:name="android.permission.INTERNET/"></uses-permission>

 

Android的常用传感器

2.1加速度传感器Accelerometer

加速度传感器主要感应手机的运动,在注册了传感器监听器后加速度传感器主要捕获3个参数values[0]、values[1]、values[2]。

values[0]:空间坐标系中x轴方向上的加速度减去重力加速度减去中立加速度在x轴上的分量。

values[1]:空间坐标系中x轴方向上的加速度减去重力加速度减去中立加速度在y轴上的分量。

values[2]:空间坐标系中x轴方向上的加速度减去重力加速度减去中立加速度在z轴上的分量。

上述3个数据的单位均为米每二次方秒。

距离说明:

当手机平放到桌面静止时,加速度为重力加速度g,通过0减去-g(重力加速度g方向为z轴反方向,故为负值)得到values[2]为g。

如果把手机水平方向右推,此时手机x方向上的加速度为正,即values[0]为正。

当把手机以a米每二次方秒的加速度竖值向上举时,values[2]的返回值为(a+g)米每二次方秒,通过a减去-g得到。

 

2.2方向传感器Orientation

方向传感器主要感应手机方位的变化,其每次读取的都是静态的状态值,在注册了传感器监听器后方向传感器主要捕获3个参数values[0]、values[1]、values[2],关于三个角度的说明如下:

第一个角度:表示手机顶部朝向与正北方向的夹角。当手机绕着Z轴旋转时,该角度值发生改变。

第二个角度:表示手机顶部或尾部翘起的角度,当手机绕着X轴倾斜时,该角度值发生变化。

第三个角度:表示手机左侧或右侧翘起的角度。当手机绕着Y轴倾斜时,该角度值发生变化。

 

2.3磁场传感器Magnetic Field

磁场传感器主要用于感应周围的磁感应强度。即使周围没有任何直接的磁场,手机设备也始终会处于地球磁场中。随着手机状态设备摆放状态的改变,周围磁场在手机的X、Y、Z方向上的会发生改变。

磁场传感器传感器会返回三个数据,三个数据分别代表周围磁场分解到X、Y、Z三个方向上的磁场分量。磁场数据的单位是微特斯拉(uT)。

 

2.4光传感器Light

光传感器用于感应周围的光强,注册监听器后只捕获一个参数:values[0]。该参数代表周围的光照强度,单位为勒克斯(lux)。

 

2.5温度传感器Temperature

温度传感器用于获取手机设备所处环境的温度。温度传感器会返回一个数据,该数据代表手机设备周围的温度,单位是摄氏度。

 

2.6压力传感器 Pressure

压力传感器用于获取手机设备所处环境的压力的大小。压力传感器会返回一个数据,代表手机设备周围的压力大小。

 

例:传感器应用:

 


<span style="font-size:14px;">SensorSimulatorTest.java

public class SensorSimulatorTest extends Activity
    implements SensorEventListener
{
    // // 定义真机的Sensor管理器
    // private SensorManager mSensorManager;
    // 定义模拟器的Sensor管理器
    private SensorManagerSimulator mSensorManager;
 
    EditText etOrientation;
    EditText etMagnetic;
    EditText etTemerature;
    EditText etLight;
    EditText etPressure;
 
    @Override
    public void onCreate(Bundle savedInstanceState)
    {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);
        // 获取界面上的EditText组件
        etOrientation = (EditText) findViewById(R.id.etOrientation);
        etMagnetic = (EditText) findViewById(R.id.etMagnetic);
        etTemerature = (EditText) findViewById(R.id.etTemerature);
        etLight = (EditText) findViewById(R.id.etLight);
        etPressure = (EditText) findViewById(R.id.etPressure);
        // 获取真机的传感器管理服务
        // mSensorManager = (SensorManager)getSystemService(SENSOR_SERVICE);
        // 获取传感器模拟器的传感器管理服务
        mSensorManager = SensorManagerSimulator.getSystemService(this,
            SENSOR_SERVICE);
        // 连接传感器模拟器
        mSensorManager.connectSimulator();
    }
 
    @Override
    protected void onResume()
    {
        super.onResume();
        // 为系统的方向传感器注册监听器
        mSensorManager.registerListener(this,
            mSensorManager.getDefaultSensor(Sensor.TYPE_ORIENTATION),
            SensorManager.SENSOR_DELAY_GAME);
        // 为系统的磁场传感器注册监听器
        mSensorManager.registerListener(this,
            mSensorManager.getDefaultSensor(Sensor.TYPE_MAGNETIC_FIELD),
            SensorManager.SENSOR_DELAY_GAME);
        // 为系统的温度传感器注册监听器
        mSensorManager.registerListener(this,
            mSensorManager.getDefaultSensor(Sensor.TYPE_TEMPERATURE),
            SensorManager.SENSOR_DELAY_GAME);
        // 为系统的光传感器注册监听器
        mSensorManager.registerListener(this,
            mSensorManager.getDefaultSensor(Sensor.TYPE_LIGHT),
            SensorManager.SENSOR_DELAY_GAME);
        // 为系统的压力传感器注册监听器
        mSensorManager.registerListener(this,
            mSensorManager.getDefaultSensor(Sensor.TYPE_PRESSURE),
            SensorManager.SENSOR_DELAY_GAME);
    }
 
    @Override
    protected void onStop()
    {
        // 程序退出时取消注册传感器监听器
        mSensorManager.unregisterListener(this);
        super.onStop();
    }
 
    @Override
    protected void onPause()
    {
        // 程序暂停时取消注册传感器监听器
        mSensorManager.unregisterListener(this);
        super.onPause();
    }
 
    // 以下是实现SensorEventListener接口必须实现的方法
    @Override
    // 当传感器精度改变时回调该方法。
    public void onAccuracyChanged(Sensor sensor, int accuracy)
    {
    }
 
    @Override
    public void onSensorChanged(SensorEvent event)
    {
        float[] values = event.values;
        // // 真机上获取触发event的传感器类型
        // int sensorType = event.sensor.getType();
        // 模拟器上获取触发event的传感器类型
        int sensorType = event.type;
        StringBuilder sb = null;
        // 判断是哪个传感器发生改变
        switch (sensorType)
        {
            // 方向传感器
            case Sensor.TYPE_ORIENTATION:
                sb = new StringBuilder();
                sb.append(绕Z轴转过的角度:);
                sb.append(values[0]);
                sb.append(
绕X轴转过的角度:);
                sb.append(values[1]);
                sb.append(
绕Y轴转过的角度:);
                sb.append(values[2]);
                etOrientation.setText(sb.toString());
                break;
            // 磁场传感器
            case Sensor.TYPE_MAGNETIC_FIELD:
                sb = new StringBuilder();
                sb.append(X方向上的角度:);
                sb.append(values[0]);
                sb.append(
Y方向上的角度:);
                sb.append(values[1]);
                sb.append(
Z方向上的角度:);
                sb.append(values[2]);
                etMagnetic.setText(sb.toString());
                break;
            // 温度传感器
            case Sensor.TYPE_TEMPERATURE:
                sb = new StringBuilder();
                sb.append(当前温度为:);
                sb.append(values[0]);
                etTemerature.setText(sb.toString());
                break;
            // 光传感器
            case Sensor.TYPE_LIGHT:
                sb = new StringBuilder();
                sb.append(当前光的强度为:);
                sb.append(values[0]);
                etLight.setText(sb.toString());
                break;
            // 压力传感器
            case Sensor.TYPE_PRESSURE:
                sb = new StringBuilder();
                sb.append(当前压力为:);
                sb.append(values[0]);
                etPressure.setText(sb.toString());
                break;
        }
    }
}
</span>



 

传感器应用案例

对传感器的支持是Android系统的特性之一,通过使用传感器可以开发出各种有趣的应用,我们通过方向传感器来开发指南针。

开发指南针的思路比较简单:程序先准备一张指南针图片,该图片上方向指针指向北方。接下来开发一个检测方向的传感器,程序检测到手机顶部绕Z轴转过多少度,让指南针图片反向转过多少度即可。

该应用中只要在界面中添加一张图片,并让图片总是反向转过方向传感器反回的第一个角度即可。

 

例:指南针

<span style="font-size:14px;">Compass.java

public class Compass extends Activity
    implements SensorEventListener
{
    // 定义显示指南针的图片
    ImageView znzImage;
    // 记录指南针图片转过的角度
    float currentDegree = 0f;
    // 定义模拟器的Sensor管理器
//  private SensorManagerSimulator mSensorManager;
 
     // 定义真机的Sensor管理器
    SensorManager mSensorManager;
    @Override
    public void onCreate(Bundle savedInstanceState)
    {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);
        // 获取界面中显示指南针的图片
        znzImage = (ImageView) findViewById(R.id.znzImage);
 
         // 获取真机的传感器管理服务
         mSensorManager = (SensorManager)getSystemService(SENSOR_SERVICE);
//      // 获取传感器模拟器的传感器管理服务
//      mSensorManager = SensorManagerSimulator.getSystemService(this,
//          SENSOR_SERVICE);
//      // 连接传感器模拟器
//      mSensorManager.connectSimulator();
    }
 
    @Override
    protected void onResume()
    {
        super.onResume();
        // 为系统的方向传感器注册监听器
        mSensorManager.registerListener(this,
            mSensorManager.getDefaultSensor(Sensor.TYPE_ORIENTATION),
            SensorManager.SENSOR_DELAY_GAME);
    }
 
    @Override
    protected void onPause()
    {
        // 取消注册
        mSensorManager.unregisterListener(this);
        super.onPause();
    }
 
    @Override
    protected void onStop()
    {
        // 取消注册
        mSensorManager.unregisterListener(this);
        super.onStop();
    }
 
    @Override
    public void onSensorChanged(SensorEvent event)
    {
        // 真机上获取触发event的传感器类型
        int sensorType = event.sensor.getType();
//      // 模拟器上获取触发event的传感器类型
//      int sensorType = event.type;
        switch (sensorType)
        {
            case Sensor.TYPE_ORIENTATION:
                // 获取绕Z轴转过的角度。
                float degree = event.values[0];
                // 创建旋转动画(反向转过degree度)
                RotateAnimation ra = new RotateAnimation(currentDegree,
                    -degree, Animation.RELATIVE_TO_SELF, 0.5f,
                    Animation.RELATIVE_TO_SELF, 0.5f);
                // 设置动画的持续时间
                ra.setDuration(200);
                // 运行动画
                znzImage.startAnimation(ra);
                currentDegree = -degree;
                break;
        }
    }
 
    @Override
    public void onAccuracyChanged(Sensor sensor, int accuracy)
    {
    }
}
 
 
</span>


<span style="font-size:14px;">例:水平仪:
Gradienter.java

public class Gradienter extends Activity implements SensorEventListener
{
    // 定义水平仪的仪表盘
    MyView show;
    // 定义水平仪能处理的最大倾斜角,超过该角度,气泡将直接在位于边界。
    int MAX_ANGLE = 30;
    // // 定义真机的Sensor管理器
    // SensorManager mSensorManager;
    // 定义模拟器的Sensor管理器
    SensorManagerSimulator mSensorManager;
 
    @Override
    public void onCreate(Bundle savedInstanceState)
    {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);
        // 获取水平仪的主组件
        show = (MyView) findViewById(R.id.show);
        // 获取真机的传感器管理服务
        // mSensorManager = (SensorManager)getSystemService(SENSOR_SERVICE);
        // 获取传感器模拟器的传感器管理服务
        mSensorManager = SensorManagerSimulator.getSystemService(this,
            SENSOR_SERVICE);
        // 连接传感器模拟器
        mSensorManager.connectSimulator();
    }
 
    @Override
    public void onResume()
    {
        super.onResume();
        // 为系统的方向传感器注册监听器
        mSensorManager.registerListener(this,
            mSensorManager.getDefaultSensor(Sensor.TYPE_ORIENTATION),
            SensorManager.SENSOR_DELAY_GAME);
    }
 
    @Override
    protected void onPause()
    {
        // 取消注册
        mSensorManager.unregisterListener(this);
        super.onPause();
    }
 
    @Override
    protected void onStop()
    {
        // 取消注册
        mSensorManager.unregisterListener(this);
        super.onStop();
    }
 
    @Override
    public void onAccuracyChanged(Sensor sensor, int accuracy)
    {
    }
 
    @Override
    public void onSensorChanged(SensorEvent event)
    {
        float[] values = event.values;
        // // 真机上获取触发event的传感器类型
        // int sensorType = event.sensor.getType();
        // 模拟器上获取触发event的传感器类型
        int sensorType = event.type;
        switch (sensorType)
        {
            case Sensor.TYPE_ORIENTATION:
                // 获取与Y轴的夹角
                float yAngle = values[1];
                // 获取与Z轴的夹角
                float zAngle = values[2];
                // 气泡位于中间时(水平仪完全水平),气泡的X、Y座标
                int x = (show.back.getWidth() - show.bubble.getWidth()) / 2;
                int y = (show.back.getHeight() - show.bubble.getHeight()) / 2;
                // 如果与Z轴的倾斜角还在最大角度之内
                if (Math.abs(zAngle) <= MAX_ANGLE)
                {
                    // 根据与Z轴的倾斜角度计算X座标的变化值(倾斜角度越大,X座标变化越大)
                    int deltaX = (int) ((show.back.getWidth() - show.bubble
                        .getWidth()) / 2 * zAngle / MAX_ANGLE);
                    x += deltaX;
                }
                // 如果与Z轴的倾斜角已经大于MAX_ANGLE,气泡应到最左边
                else if (zAngle > MAX_ANGLE)
                {
                    x = 0;
                }
                // 如果与Z轴的倾斜角已经小于负的MAX_ANGLE,气泡应到最右边
                else
                {
                    x = show.back.getWidth() - show.bubble.getWidth();
                }
                // 如果与Y轴的倾斜角还在最大角度之内
                if (Math.abs(yAngle) <= MAX_ANGLE)
                {
                    // 根据与Y轴的倾斜角度计算Y座标的变化值(倾斜角度越大,Y座标变化越大)
                    int deltaY = (int) ((show.back.getHeight() - show.bubble
                        .getHeight()) / 2 * yAngle / MAX_ANGLE);
                    y += deltaY;
                }
                // 如果与Y轴的倾斜角已经大于MAX_ANGLE,气泡应到最下边
                else if (yAngle > MAX_ANGLE)
                {
                    y = show.back.getHeight() - show.bubble.getHeight();
                }
                // 如果与Y轴的倾斜角已经小于负的MAX_ANGLE,气泡应到最右边
                else
                {
                    y = 0;
                }
                // 如果计算出来的X、Y座标还位于水平仪的仪表盘内,更新水平仪的气泡座标
                if (isContain(x, y))
                {
                    show.bubbleX = x;
                    show.bubbleY = y;
                }
                // 通知系统重回MyView组件
                show.postInvalidate();
                break;
        }
    }
 
    // 计算x、y点的气泡是否处于水平仪的仪表盘内
    private boolean isContain(int x, int y)
    {
        // 计算气泡的圆心座标X、Y
        int bubbleCx = x + show.bubble.getWidth() / 2;
        int bubbleCy = y + show.bubble.getWidth() / 2;
        // 计算水平仪仪表盘的圆心座标X、Y
        int backCx = show.back.getWidth() / 2;
        int backCy = show.back.getWidth() / 2;
        // 计算气泡的圆心与水平仪仪表盘的圆心之间的距离。
        double distance = Math.sqrt((bubbleCx - backCx) * (bubbleCx - backCx)
            + (bubbleCy - backCy) * (bubbleCy - backCy));
        // 若两个圆心的距离小于它们的半径差,即可认为处于该点的气泡依然位于仪表盘内
        if (distance < (show.back.getWidth() - show.bubble.getWidth()) / 2)
        {
            return true;
        }
        else
        {
            return false;
        }
    }
}
 
MyView.java

public class MyView extends View
{
    // 定义水平仪仪表盘图片
    Bitmap back;
    // 定义水平仪中的气泡图标
    Bitmap bubble;
    // 定义水平仪中气泡 的X、Y座标
    int bubbleX, bubbleY;
 
    public MyView(Context context, AttributeSet attrs)
    {
        super(context, attrs);
        // 加载水平仪图片和气泡图片
        back = BitmapFactory.decodeResource(getResources()
            , R.drawable.back);
        bubble = BitmapFactory
            .decodeResource(getResources(), R.drawable.bubble);
    }
 
    @Override
    protected void onDraw(Canvas canvas)
    {
        super.onDraw(canvas);
        // 绘制水平仪表盘图片
        canvas.drawBitmap(back, 0, 0, null);
        // 根据气泡座标绘制气泡
        canvas.drawBitmap(bubble, bubbleX, bubbleY, null);
    }
}</span>


Android 通知栏功能

通知栏主要是为了及时的通知用户消息,配合推送来进行使用是最常见的情况,也可以对下载,音乐播放器等的进行使用,比如酷我音乐通知栏可以切换播放歌曲,暂停等功能。

         使用方式:

Android 推送

Android 的推送是为了实现当产品有新的重大更新,或是有新的优惠或是活动,等的时候及时 的通知。让用户提高对于我们产品的粘性。提高活跃度。

现在使用最多的几个推送:

         百度

         极光推送

         友盟

         等

使用方式也是按接入文档来进行。

Android 地图开发:

关于地图开发:

         百度地图开发:

         高德地图开发:

开发流程基本相同,最新的版本的使用更加简单,按流程接入就好,难点在于实现自定义的遮罩,已经浮层,路径绘制,对导航进行自定义出来等。

很多人说高德地图比百度地图更加精确,这个可以自己测试,如果要精确定位检测是否打开GPS.

 

20:、Android 第三广告平台:

Android 即时通讯:

即时通讯就是实现及时应答的功能,通过Tcp,udp,或socket进行连接,进行实时应答的功能。

腾讯的微信,QQ,陌陌,等等就是实现这样的效果。

关于这个功能的实现有很多方式:

(1)     XMPP协议实现

(2)     Mqtt协议实现

(3)     Socket实现

 

Android 视频开发:

Android 短信开发:

Android 音频开发

Android蓝牙开发

Android 无线网络开发:

Android 联系人开发:

Android各种第三方框架的使用:

Android listView的优化,内存优化,Android代码的重构

Android 各种错位问题的处理

Android 下载管理器的书写

android 有自带的下载管理器,但是在自己的应用中使用可能有点不是特别舒服,所有很多应用都是自己写,下边就介绍下android自带
下载管理器与 自己写下载管理器的流程介绍。
(1)、系统下载管理器

(2)、自定义下载管理器

Android 手机适配

关于手机适配一直是android中很重要的一个点,因为android手机分辨率,尺寸太多,具体的就不多说了,下边这篇文章里边很细,值得一看。

Android 6.0权限的管理

android 6.0的的很多新特效,其中权限管理就是一块,很多功能再使用的时候都会提示用户进行授权,
虽然有点烦,但是打打提高了安全性,而且网上已经有很多权限申请的框架。

Android 材料设计语言,已经v7中新添加的控件等

单例模式:

说到单例模式,为什么要使用单例模式呢?

为了保证在一个进程中只保持某个类的唯一的一个类的引用,也就是为了使这个类的对象的安全性。

所以就有了单例模式。

文章地址:http://blog.csdn.net/u012808234/article/details/43964945

 

工厂模式

文章地址:http://blog.csdn.net/u012808234/article/details/52605933

 

适配器模式

适配器模式也是Android中用的特别多的一个模式,最典型的可能就是BaseAdapter  跟listView等的关系了。
那么什么是适配器模式呢?
适配器模式就是使俩个使用场景不符的俩个对象通过适配器而变的可以及交互。就跟我们的电压一样,标准电压220v,手机充电电压5v,适配器就是中间的那个变压器。把标准电压适配成手机可以使用的电压。

观察者模式

观察者模式也被叫做是  发布/订阅 模式,这个模式使用很广,他的原理就是:

定义了一种一对多的依赖关系,让多个观察者对象同时监听某一个主题对象。

   这个主题对象在状态上发生变化时,会通知所有观察者对象,让它们能够自动更新自己。


比如我们要时刻监听短信变化,网络变化,数据库变化等等。

参考博客:http://www.w2bc.com/Article/76136


Build(建造者)模式

模板模式                                               

模板方法模式说的通俗点就是代码的复用,也就是通过子类继承父类,然后实现父类的方法(父类中的方法可以是空实现,也可以是一个抽象方法),然后在之类实现的方法中可以定义许多自定义的实现,父类可以通过这个方法来调用子类中的这个方法的实现。

 

文章地址:http://blog.csdn.net/u012808234/article/details/51152440

 

Java的基础算法:

关于算法,在程序开发中十分的重要,而算法其实就是对于某一种情况而实现的一种编程思想。

比如说二分查找,就是为了实现查找而提出的一种解决查找问题的算法,

一个问题有很多重算法,在代码编写中一定要使用效率最高的算法来进行实现。

算法的优劣是通过时间复杂度以及空间复杂度来进行判断的。

下边简单介绍几个java的基本算法:

插入排序:

<span style="font-size:14px;">public class InsertSort implements SortUtil.Sort{

    /* (non-Javadoc)
    * @see org.rut.util.algorithm.SortUtil.Sort#sort(int[])
    */
    public void sort(int[] data) {
        int temp;
        for(int i=1;i<data.length;i++){
            for(int j=i;(j>0)&&(data[j]<data[j-1]);j--){
                SortUtil.swap(data,j,j-1);
            }
        }        
    }

}

冒泡排序:
public class BubbleSort implements SortUtil.Sort{

    /* (non-Javadoc)
    * @see org.rut.util.algorithm.SortUtil.Sort#sort(int[])
    */
    public void sort(int[] data) {
        int temp;
        for(int i=0;i<data.length;i++){
            for(int j=data.length-1;j>i;j--){
                if(data[j]<data[j-1]){
                    SortUtil.swap(data,j,j-1);
                }
            }
        }
    }

}



选择排序:
public class SelectionSort implements SortUtil.Sort {

    /*
    * (non-Javadoc)
    * 
    * @see org.rut.util.algorithm.SortUtil.Sort#sort(int[])
    */
    public void sort(int[] data) {
        int temp;
        for (int i = 0; i< data.length; i++) {
            int lowIndex= i;
            for (int j= data.length - 1; j > i; j--) {
                if (data[j]< data[lowIndex]) {
                    lowIndex= j;
                }
            }
            SortUtil.swap(data,i,lowIndex);
        }
    }

}

Shell排序:
public class ShellSort implements SortUtil.Sort{

    /* (non-Javadoc)
    * @see org.rut.util.algorithm.SortUtil.Sort#sort(int[])
    */
    public void sort(int[] data) {
        for(int i=data.length/2;i>2;i/=2){
            for(int j=0;j<i;j++){
                insertSort(data,j,i);
            }
        }
        insertSort(data,0,1);
    }

    /**
    * @param data
    * @param j
    * @param i
    */
    private void insertSort(int[]data, int start, int inc) {
        int temp;
        for(int i=start+inc;i<data.length;i+=inc){
            for(int j=i;(j>=inc)&&(data[j]<data[j-inc]);j-=inc){
                SortUtil.swap(data,j,j-inc);
            }
        }
    }

}

快速排序:
public class QuickSort implements SortUtil.Sort{

    /* (non-Javadoc)
    * @see org.rut.util.algorithm.SortUtil.Sort#sort(int[])
    */
    public void sort(int[] data) {
        quickSort(data,0,data.length-1);        
    }
    private void quickSort(int[]data,int i,int j){
        int pivotIndex=(i+j)/2;
        //swap
        SortUtil.swap(data,pivotIndex,j);
        
        int k=partition(data,i-1,j,data[j]);
        SortUtil.swap(data,k,j);
        if((k-i)>1)quickSort(data,i,k-1);
        if((j-k)>1)quickSort(data,k+1,j);
        
    }
    /**
    * @param data
    * @param i
    * @param j
    * @return
    */
    private int partition(int[]data, int l, int r,int pivot) {
        do{
           while(data[++l]<pivot);
           while((r!=0)&&data[--r]>pivot);
          SortUtil.swap(data,l,r);
        }
        while(l<r);
        SortUtil.swap(data,l,r);        
        return l;
    }

}

改进后的快速排序:
public class ImprovedQuickSort implements SortUtil.Sort {

    private static int MAX_STACK_SIZE=4096;
    private static int THRESHOLD=10;
    /* (non-Javadoc)
    * @see org.rut.util.algorithm.SortUtil.Sort#sort(int[])
    */
    public void sort(int[] data) {
        int[] stack=new int[MAX_STACK_SIZE];
        
        int top=-1;
        int pivot;
        int pivotIndex,l,r;
        
        stack[++top]=0;
        stack[++top]=data.length-1;
        
        while(top>0){
            int j=stack[top--];
            int i=stack[top--];
            
            pivotIndex=(i+j)/2;
            pivot=data[pivotIndex];
            
            SortUtil.swap(data,pivotIndex,j);
            
            //partition
            l=i-1;
            r=j;
            do{
                while(data[++l]<pivot);
                while((r!=0)&&(data[--r]>pivot));
                SortUtil.swap(data,l,r);
            }
            while(l<r);
            SortUtil.swap(data,l,r);
            SortUtil.swap(data,l,j);
            
            if((l-i)>THRESHOLD){
                stack[++top]=i;
                stack[++top]=l-1;
            }
            if((j-l)>THRESHOLD){
                stack[++top]=l+1;
                stack[++top]=j;
            }
            
        }
        //new InsertSort().sort(data);
        insertSort(data);
    }
    /**
    * @param data
    */
    private void insertSort(int[] data) {
        int temp;
        for(int i=1;i<data.length;i++){
            for(int j=i;(j>0)&&(data[j]<data[j-1]);j--){
                SortUtil.swap(data,j,j-1);
            }
        }       
    }

}

归并排序:
public class MergeSort implements SortUtil.Sort{

    /* (non-Javadoc)
    * @see org.rut.util.algorithm.SortUtil.Sort#sort(int[])
    */
    public void sort(int[] data) {
        int[]temp=new int[data.length];
        mergeSort(data,temp,0,data.length-1);
    }
    
    private void mergeSort(int[] data,int[]temp,int l,int r){
        int mid=(l+r)/2;
        if(l==r) return ;
        mergeSort(data,temp,l,mid);
        mergeSort(data,temp,mid+1,r);
        for(int i=l;i<=r;i++){
            temp<i>=data<i>;
        }
        int i1=l;
        int i2=mid+1;
        for(int cur=l;cur<=r;cur++){
            if(i1==mid+1)
                data[cur]=temp[i2++];
            else if(i2>r)
                data[cur]=temp[i1++];
            else if(temp[i1]<temp[i2])
                data[cur]=temp[i1++];
            else
                data[cur]=temp[i2++];            
        }
    }

}

改进后的归并排序:
public class ImprovedMergeSort implements SortUtil.Sort {

    private static final int THRESHOLD= 10;

    /*
    * (non-Javadoc)
    * 
    * @see org.rut.util.algorithm.SortUtil.Sort#sort(int[])
    */
    public void sort(int[] data) {
        int[]temp=new int[data.length];
        mergeSort(data,temp,0,data.length-1);
    }

    private void mergeSort(int[] data, int[]temp, int l, int r) {
        int i, j, k;
        int mid = (l + r) / 2;
        if (l == r)
            return;
        if ((mid - l) >=THRESHOLD)
            mergeSort(data,temp, l, mid);
        else
            insertSort(data,l, mid - l + 1);
        if ((r - mid) >THRESHOLD)
            mergeSort(data,temp, mid + 1, r);
        else
            insertSort(data,mid + 1, r - mid);

        for (i = l; i <= mid;i++) {
            temp<i>= data<i>;
        }
        for (j = 1; j <= r -mid; j++) {
            temp[r- j + 1] = data[j + mid];
        }
        int a = temp[l];
        int b = temp[r];
        for (i = l, j = r, k = l;k <= r; k++) {
            if (a< b) {
                data[k]= temp[i++];
                a= temp<i>;
            } else {
                data[k]= temp[j--];
                b= temp[j];
            }
        }
    }

   
    private void insertSort(int[]data, int start, int len) {
        for(int i=start+1;i<start+len;i++){
            for(int j=i;(j>start)&& data[j]<data[j-1];j--){
                SortUtil.swap(data,j,j-1);
            }
        }
    }

}




堆排序:
public class HeapSort implements SortUtil.Sort{

    /* (non-Javadoc)
    * @see org.rut.util.algorithm.SortUtil.Sort#sort(int[])
    */
    public void sort(int[] data) {
        MaxHeap h=new MaxHeap();
        h.init(data);
        for(int i=0;i<data.length;i++)
            h.remove();
        System.arraycopy(h.queue,1,data,0,data.length);
    }

     private static class MaxHeap{         
        
        void init(int[] data){
            this.queue=new int[data.length+1];
            for(int i=0;i<data.length;i++){
                queue[++size]=data<i>;
                fixUp(size);
            }
        }
         
        private int size=0;

        private int[] queue;
                
        public int get() {
            return queue[1];
        }

        public void remove(){
            SortUtil.swap(queue,1,size--);
            fixDown(1);
        }
        //fixdown
        private void fixDown(int k){
            int j;
            while ((j= k << 1) <= size) {
                if (j< size && queue[j]<queue[j+1])
                    j++; 
                if (queue[k]>queue[j]) //不用交换
                    break;
                SortUtil.swap(queue,j,k);
                k= j;
            }
        }
        private void fixUp(int k){
            while (k> 1) {
                int j= k >> 1;
                if (queue[j]>queue[k])
                    break;
                SortUtil.swap(queue,j,k);
                k= j;
            }
        }

    }

}</span>


Android与html/js的交互

关于Android与html进行交互主要是为了在用html页面代替Android原生代码所写的界面而产生的不可避免的交互,看下图:
这个界面就是html5所写的,但是可以其中的下载是通过android原生代码来进行编写的,点击html5中的下载,然后调用Android中的下载管理器(系统下载管理器或是自己写的下载管理器),下载完成还要通知他下载完成,或是下载的进度等等。

文章地址:http://blog.csdn.net/u012808234/article/details/44595497

 

SpannableString 来改变textView中http协议,手机号,已经你想要改变的字的颜色,以及添加onClick事件

比如这样一个字符串要在Android中进行实现:
Seri : 我是seri你好吗我很好
实现的方式有很多重,我们可以用好几个TextView来进行实现,也可以用Html来实现,当然也可以用SpannableString 来实现。

文章地址:http://blog.csdn.net/u012808234/article/details/42675165

 

Android jni +ndk 开发

Android的jni开发通俗的讲就是javanative interface ,java本地接口调用,就是我们做本地方法的实现。

为什么要做本地方法的实现呢?

首先我们要知道,Android开发使用是java语言,而jni开发的时候后本地实现一般都是c或c++代码来写的。那么他们有什么区别呢。

C语言和JAVA其实是很相识的,最直接的区别就在与,一个是全面向过程,一个是面向对象。而且JAVA是可以跨平台的。而C语言不能,但能够直接操作硬件,并且生成机器码的效率高。C语言多了一个,指针也是C语言的精髓。
可以直接操作硬件,那么就意味着在有些操作上速度是比java的执行速度快很多的,比如多媒体中对音视频的处理,图像的各种变换等。

Android 中jni开发用的比较多的就是音视频,以及图像方面。

比如美拍,各种视频播放器,快手,微信中的语音等等吧。

下边是jni开发的介绍以及音视频处理中jni的调用。

http://blog.csdn.net/u012808234/article/details/50381641

http://blog.csdn.net/u012808234/article/details/51700826

http://blog.csdn.net/u012808234/article/details/51701487

http://blog.csdn.net/u012808234/article/details/51605143

http://blog.csdn.net/u012808234/article/details/51672229

关于opencv使用:

http://blog.csdn.net/u012808234/article/details/50562896

http://blog.csdn.net/u012808234/article/details/50594421

http://blog.csdn.net/u012808234/article/details/50388525

Android aidl开发,实现进程间通信

关于Android Aidl开发,Aidl就是Android interface definition language (接口定义语言)

主要是为了实现进程间通信,或者是远程通信。

关于这个功能再Android的系统里边就有很多的实现。

有开发过蓝牙或者WIFI应用的朋友肯定都知道,要去操作它必须先获得一个管理类,比如WIFI的管理类是WifiManager,通过getSystemService(Context.WIFI_SERVICE)就可以得到wifi的管理权限,这个提供了很多的方法可以让用户去操作它,比如打开wifi可以调用setWifiEnabled(true)方法。那这个Manager到底做了什么工作呢?是怎样实现打开wifi的呢?其实这个Manager只是一个管理类,真正干活的另有其人,是一个叫WifiService的系统服务。在Android系统中有很多的Managerwifi的管理类叫WifiManager,蓝牙的管理类叫BluetoothManager,但是,只要有xxxManager.java,就会有Ixxx.aidl,并且有xxxService.java。这个aidl类就是实现ManagerService通信的桥梁。

对于Android手机来说,当开机以后整个手机的系统其实就是一个大大的应用,我们平常写的应用都运行在这个应用上边,系统中不管是蓝牙,通讯录,等等都是他里边的应用,我们要使用它里边的功能就等于是在实现手机上应用之间的通信。

文章地址:http://blog.csdn.net/u012808234/article/details/51312491

 

Android xml解析方式及比较

Android中,常见的XML解析器分别为SAX解析器、DOM解析器和PULL解析器,下面,详细介绍。

SAX解析器:

SAX(Simple API for XML)解析器是一种基于事件的解析器,它的核心是事件处理模式,主要是围绕着事件源以及事件处理器来工作的。当事件源产生事件后,调用事件处理器相应的处理方法,一个事件就可以得到处理。在事件源调用事件处理器中特定方法的时候,还要传递给事件处理器相应事件的状态信息,这样事件处理器才能够根据提供的事件信息来决定自己的行为。

SAX解析器的优点是解析速度快,占用内存少。非常适合在Android移动设备中使用。

DOM解析器:

DOM是基于树形结构的的节点或信息片段的集合,允许开发人员使用DOM API遍历XML树、检索所需数据。分析该结构通常需要加载整个文档和构造树形结构,然后才可以检索和更新节点信息。

由于DOM在内存中以树形结构存放,因此检索和更新效率会更高。但是对于特别大的文档,解析和加载整个文档将会很耗资源。

PULL解析器:

PULL解析器的运行方式和SAX类似,都是基于事件的模式。不同的是,在PULL解析过程中,我们需要自己获取产生的事件然后做相应的操作,而不像SAX那样由处理器触发一种事件的方法,执行我们的代码。PULL解析器小巧轻便,解析速度快,简单易用,非常适合在Android移动设备中使用,Android系统内部在解析各种XML时也是用PULL解析器。

可以发现每个解析方式都是有他的优点以及确定,具体使用还需要视情况而定,也可以使用第三方的解析框架。

 

Android代码混淆

Java 是一种跨平台的、解释型语言,Java源代码编译成中间字节码存储于 class 文件中。由于跨平台的需要,Java字节码中包括了很多源代码信息,如变量名、方法名,并且通过这些名称来访问变量和方法,这些符号带有许多语义信息,很容易被反编译成 Java源代码。为了防止这种现象,我们可以使用 Java混淆器对 Java字节码进行混淆。

混淆就是对发布出去的程序进行重新组织和处理,使得处理后的代码与处理前代码完成相同的功能,而混淆后的代码很难被反编译,即使反编译成功也很难得出程序的真正语义。被混淆过的程序代码,仍然遵照原来的档案格式和指令集,执行结果也与混淆前一样,只是混淆器将代码中的所有变量、函数、类的名称变为简短的英文字母代号,在缺乏相应的函数名和程序注释的况下,即使被反编译,也将难以阅读。同时混淆是不可逆的,在混淆的过程中一些不影响正常运行的信息将永久丢失,这些信息的丢失使程序变得更加难以理解。

混淆器的作用不仅仅是保护代码,它也有精简编译后程序大小的作用。由于以上介绍的缩短变量和函数名以及丢失部分信息的原因,编译后 jar文件体积大约能减少25%,这对当前费用较贵的无线网络传输是有一定意义的。

Android 热更新,插件化apk,热修复的原理及使用,第三方热修复的框架

 

关于这个知识点,上边的功能其实基于的原理都是相同的。

热更新:是为了实现应用可以实时更新,而不需要不停的发布新的线上版本。当应用有小的修改的时候,通过这个技术来实现功能的替换或是修改调整。

插件化Apk:关于插件,已经在各大平台上出现过很多,eclipse插件、chrome插件、3dmax插件,所有这些插件大概都为了在一个主程序中实现比较通用的功能,把业务相关或者让可以让用户自定义扩展的功能不附加在主程序中,主程序可在运行时安装和卸载。

android如何实现插件也已经被广泛传播,实现的原理都是实现一套插件接口,把插件实现编成apk或者dex,然后在运行时使用DexClassLoader动态加载进来。

插件化Apk就是为了减小Apk的大小,而把一个应用的不同功能模块打包成一个Apk文件。然后通过被安装的Apk来加载这几个Apk文件,插件化在运行流畅度上有比较大的问题,个人看法。使用过支付的人应该知道,支付宝就是使用插件化来加载的,可以发现小的版本支付宝基本上都不需要重新下载,只需要更新那几个插件包就可以实现替换。

 

那么关于这个热修复,以及插件化实现的原理,就是通过ClassLoader来加载你所修改或是更新好的插件,然后在应该中调用。

具体看下边资料:

插件原理即实现:http://www.alloyteam.com/2014/04/android-cha-jian-yuan-li-pou-xi/

热修复:http://www.tuicool.com/articles/367RBvY

Android NFC功能开发

NFC手机相比普通手机来说,有以下3个附加功能: 
1.可以当成POS机来用,也就是读取模式  
2.可以当成一张卡来刷,也就是NFC技术最核心的移动支付功能 
3.可以像蓝牙、Wi-Fi一样做点对点通信 

Near  Field Communication(NFC)为一短距离无线通信技术,通常有效通讯距离为4厘米以内。NFC工作频率为13.65 兆赫兹,通信速率为106 kbit/秒到 848kbit/秒。

NFC通信总是由一个发起者 (initiator)和一个接受者(target)组成。通常initiator 主动发送电磁场(RF)可以为被动式接受者(passive target)提供电源。其工作的基本原理和收音机类似。正是由于被动式接受者可以通过发起者提供电源,因此target 可以有非常简单的形式,比如标签,卡,sticker 的形式。

NFC也支持点到点的通信(peer to peer)此时参与通信的双方都有电源支持。

和其它无线通信方式如Bluetooth相比,NFC 支持的通信带宽和距离要小的多,但是它成本低,如价格标签可能只有几分钱,也不需要配对,搜寻设备等,通信双方可以在靠近的瞬间完成交互。

Android NFC应用中,Android手机通常是作为通信中的发起者,也就是作为NFC的读写器。Android手机也可以模拟作为NFC通信的接受者且从Android 2.3.3起也支持P2P通信。

Android使用第三方字体,字体文件   (.TTF)

关于第三方字体,他是用来使应用看起来;更加符合用户的观看习惯或是突出产品的特性等等。比如要漫画里边字体可能是娃娃字体,或是火星文字体

看下图:

使用第三方字体也很简单,把字体文件下载以后,放到assets文件夹下,然后通过

Typeface typeface = Typeface.createFromAsset(“参数一AssetsManager”,“路径”);

然后给TextView设置,或是给Paint设置都可以。

第三方登录,支付等等

第三方登录通常是使用现在使用范围最广的用户群的账号来进行登录,通过第三方认证登录以后在自己应用里边生成对应的账号,来实现账号绑定,以及减少因注册减少的用户量。

现在使用最多的有一下几个:

         QQ

         新浪

         人人

         支付宝

         微信

         等等吧。

要做第三方的登录只要根据官方的文档来进行接入就可以了。

 

关于第三方支付这一块,是为了提升支付的成功率:

第三方的支付现在分很多种:

         支付宝

         微信

         QQ钱包

         银联

         充值卡

         手机短信支付

         等等。

相应的接入方式官方都有,有问题可以查查百度,很多人都做过了。

Android 反射

 反射主要是指程序可以访问、检测和修改它本身状态或行为的一种能力。在计算机科学领域,反射是一类应用,它们能够自描述和自控制。这类应用通过某种机制来实现对自己行为的描述和检测,并能根据自身行为的状态和结果,调整或修改应用所描述行为的状态和相关的语义。

   在Java中的反射机制,被称为Reflection(大家看到这个单词,第一个想法应该就是去开发文档中搜一下了)。它允许运行中的Java程序对自身进行检查,并能直接操作程序的内部属性或方法。Reflection机制允许程序在正在执行的过程中,利用Reflection APIs取得任何已知名称的类的内部信息,包括:package、 type parameters、 superclass、 implemented interfaces、 inner classes、 outer classes、 fields、 constructors、 methods、 modifiers等,并可以在执行的过程中,动态生成Instances、变更fields内容或唤起methods。

  好,了解这些,那我们就知道了,我们可以利用反射机制在Java程序中,动态的去调用一些protected甚至是private的方法或类,这样可以很大程度上满足我们的一些比较特殊需求。你当然会问,反射机制在Android平台下有何用处呢?

  我们在进行Android程序的开发时,为了方便调试程序,并快速定位程序的错误点,会从网上下载到对应版本的Android SDK的源码(这里给大家提供一个2.3.3版本的下载链接)。你会发现很多类或方法中经常加上了“@hide”注释标记,它的作用是使这个方法或类在生成SDK时不可见,那么我们的程序可能无法编译通过,而且在最终发布的时候,就可能存在一些问题。

那么,对于这个问题,第一种方法就是自己去掉Android源码中的"@hide"标记,然后重新编译生成一个SDK。另一种方法就是使用Java反射机制了,可以利用这种反射机制访问存在访问权限的方法或修改其域。

 

 

 

 

正则表达式的学习

正则表达式是用来进行数据的过滤的,用比较严谨的文字表达就是:使用单个字符串来描述、匹配一系列符合某个句法规则的字符串;

       使用正则可以减少很多不必要的判断,而且可以提高开发效率。

       比如我们经常做的身份证验证,邮箱验证,手机号验证等等。

         文章地址:http://blog.csdn.net/u012808234/article/details/48105525

 

 

 

Android Smail 语法的学习(保证能看的懂,如果专门做反编译,那么就要熟练使用了)

android的apk进行反编译以后就是smail文件,学习smail 语法是为了在使用在出现问题的时候而又没有源码的情况下进行快熟的问题定位。
Smali基本语法 
 .field private isFlag:z  定义变量 
.method  方法 
.parameter  方法参数
 .prologue  方法开始
 .line 12  此方法位于第12行 
invoke-super  调用父函数  
const/high16  v0, 0x7fo3  
把0x7fo3赋值给v0 invoke-direct  
调用函数 return-void  函数返回void 
.end method  函数结束
 new-instance  创建实例 
iput-object  对象赋值 
iget-object  调用对象 
invoke-static  调用静态函数 
invoke-xxxx  这个就是调用什么样的方法
条件跳转分支:  
"if-eq vA, vB, :cond_**"   如果vA等于vB则跳转到:cond_** 
"if-ne vA, vB, :cond_**"   如果vA不等于vB则跳转到:cond_** 
"if-lt vA, vB, :cond_**"    如果vA小于vB则跳转到:cond_**  
"if-ge vA, vB, :cond_**"   如果vA大于等于vB则跳转到:cond_** 
"if-gt vA, vB, :cond_**"   如果vA大于vB则跳转到:cond_**  
"if-le vA, vB, :cond_**"    如果vA小于等于vB则跳转到:cond_** 
"if-eqz vA, :cond_**"   如果vA等于0则跳转到:cond_** 
"if-nez vA, :cond_**"   如果vA不等于0则跳转到:cond_**
 "if-ltz vA, :cond_**"    如果vA小于0则跳转到:cond_**  
"if-gez vA, :cond_**"   如果vA大于等于0则跳转到:cond_** 
"if-gtz vA, :cond_**"   如果vA大于0则跳转到:cond_**  
"if-lez vA, :cond_**"    如果vA小于等于0则跳转到:cond_**

 参考博客地址:http://blog.csdn.net/u012808234/article/details/52799136


Android 的wifi开发:

   android中对于wifi的开发是通过WifiManager的管理类来进行的,通过wifi可以做网络管理,也可以通过Wifi来进行数据传输。

在做wifi管理的时候,没有办法获取已经连接的wifi的密码。
wifi进行数据传输没有办法进行双向传输,现在应该是只能客户端向服务器段进行数据传输,

参考资料:

http://download.csdn.net/detail/u012808234/9660109

http://blog.csdn.net/sbvfhp/article/details/7007090



Android的多媒体开发:
Recat-native的开发:
Android 混合开发
Android 自定义控件的使用:
Android的反编译工具:
网络分析,抓包工具Fiddler的使用:

android热修复框架Tinker的使用及框架原理:
android的第三方sdk开发的功能
android集成所有sdk支付,登录等功能的sdk,类似anySdk

android最近淘宝开源的插件化开发的框架:
学习android开发的过程中还可以了解很多其他的开发语言
比如gradle,groovy,php,python,JavaScript,ruby,reactnative,phoneGap



  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值