• android 笔记


    依赖关系在 build.gradle 中的 配置 (在具体的项目文件夹)
    
    # application
    	程序初始化 重写 Application 
    	在 AndroidManifest 中的 <application android:name=".your app" ... 注册
    	可以实现一些APP启动时候的操作
    
    # 视图 View
    	view 对象就是一个透明的块,可直接用
    	视图常量 ViewConfiguration 
    	当前视图常量 如滚动条的宽度,BAR的高度等 通过 ViewConfiguration.get(Context) 获得
    	ViewGroup 是从view继承的
    	ImageView 只支持 本地资源或代码资源,
    	ImageLoader:
    		网络图片资源用外部库 ImageLoader.getInstance() 或建线程加载后填充
    		ImageLoader 的 gradle 为 compile 'com.nostra13.universalimageloader:universal-image-loader:1.9.4'
    	fresco:	 支持圆角 加载自定义 保存宽高比
    		gradle 为 compile 'com.facebook.fresco:fresco:0.6.0+'
    		XML 为:
    		<com.facebook.drawee.view.SimpleDraweeView
    			android:id="@+id/img"
    			android:layout_width="100dp"
    			android:layout_height="wrap_content"
    			fresco:placeholderImage="@drawable/aa"
    			fresco:viewAspectRatio="2"
    			fresco:roundedCornerRadius="10dp"
    			/>
    		 代码:
    		 初始化:  Fresco.initialize(this);
    		 Uri uri = Uri.parse(/*http://xxxx.jpg*/);
    		 SimpleDraweeView draweeView = (SimpleDraweeView) view.findViewById(R.id.img);
    		 draweeView.setImageURI(uri);
    		 
    	glide
    		gradle 为
    			compile 'com.github.bumptech.glide:glide:3.6.1'
    			compile 'com.android.support:support-v4:19.1.0'
    		无需初始化 支持GIF 圆角通过 transform() 实现或 compile 'de.hdodenhof:circleimageview:1.3.0'  实现
    		ImageView imageView = (ImageView) findViewById(R.id.my_image_view);
    		Glide.with(this).load("http://goo.gl/gEgYUd").into(imageView);
    		
    	Picasso:
    		compile 'com.squareup.picasso:picasso:2.5.2'
    		无需初始化 圆角通过 transform() 实现或 compile 'de.hdodenhof:circleimageview:1.3.0'  实现
    		Picasso.with(context)
    				.load(R.drawable.landing_screen)
    				.placeholder(R.id.progressBarDetails)
                    .error(R.drawable.friend_request)
    				.into(imageView1);
    		Picasso.with(context).load("file:///android_asset/DvpvklR.png").into(imageView2);
    		Picasso.with(context).load(new File(...)).into(imageView3);
    		//自定义下载
    		Picasso picasso = new Picasso.Builder(myslideAcitivty.this).downloader(
    			//OkHttpDownloader
    			//UrlConnectionDownloader
    			new OkHttpDownloader(new File(imageCacheDir))
    		).build();
    	
    	ImageView 宽高比 https://github.com/hongyangAndroid/android-percent-support-extend
    	
    	视图在 onCreate onStart 等方法中未渲染,高宽为0 需要高宽请重写 onWindowFocusChanged 设置
    	示例:
    		@Override //重设margin
    		public void onWindowFocusChanged(boolean hasFocus) {
    			super.onWindowFocusChanged(hasFocus);
    			AppBarLayout abl = (AppBarLayout) findViewById(R.id.app_bar_layout);
    			LinearLayout ll = (LinearLayout) findViewById(R.id.linearLayout);
    			ViewGroup.MarginLayoutParams layoutParams = (ViewGroup.MarginLayoutParams)ll.getLayoutParams();
    			layoutParams.topMargin=abl.getHeight();
    			ll.setLayoutParams(layoutParams);
    		}
    		
    	设置布局:setLayoutParams 为父布局类型
    		LinearLayout LayoutHead = (LinearLayout)findViewById(R.id.layline);
        	Button DateButton = (Button)findViewById(R.id.but);
    		//LinearLayout.LayoutParams ly=DateButton.getLayoutParams(); //ly may be null
    		//ly.width=100;
    		//DateButton.setLayoutParams(ly);
    		//OR 
            DateButton.setLayoutParams(
    			new LinearLayout.LayoutParams(
    				LinearLayout.LayoutParams.MATCH_PARENT,
                    LinearLayout.LayoutParams.WRAP_CONTENT)
    		);
            layoutHead.addView(DateButton);
    	
    	动态加ID:
    		idx.xml
    			<resources>
    				<item type="id" name="return_scan_result"/>
    			</resources>
    		代码:
    			TextView tt = new TextView(this);
    			tt.setId(R.id.return_scan_result);
    	
    	窗口管理,屏幕高宽等
    		Display display = getWindowManager().getDefaultDisplay();
    		Point size = new Point();
    		display.getSize(size);
    		int width = size.x;
    		int height = size.y;
    	
    	获取 基本组件可以通过 ComponentName 来获取,支持Context 中获取指定的view组件 
    	示例
    		new ComponentName(context, myreceiver.class);
    		new ComponentName("包名","类或类名")
    		
    	加载提示
    		final ProgressDialog dialog = new ProgressDialog(this);
            dialog.setMessage("加载中");
            dialog.show();
    		
    	用在非本身的视图 RemoteViews 
    		new RemoteViews(context.getPackageName(), R.layout.aa);
    		
    	排版页面时,样式可独立到style中,通过style来引用 (类似CSS) style 通过 parent实现继承
    	
    	自定义视图,继承至view 示例
    		定义 view
    			public class MyView extends View {
    				private Paint mPaint;
    				private int textColor;
    				public MyView(Context context) {
    					super(context);
    					mPaint = new Paint();
    				}
    				public MyView(Context context, AttributeSet attrs) {
    					super(context, attrs);
    					//自定义属性 参考/values/attrs.xml
    					TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.MyView);
    					textColor = a.getColor(R.styleable.MyView_bgcolor, 0XFFFFFFFF);
    					float textSize = a.getDimension(R.styleable.MyView_textSize, 36);
    					a.recycle();
    					mPaint = new Paint();
    					mPaint.setTextSize(textSize);
    					mPaint.setColor(textColor);
    				}
    				@Override
    				protected void onDraw(Canvas canvas) {
    					super.onDraw(canvas);
    					mPaint.setStyle(Paint.Style.FILL);
    					canvas.drawRect(new Rect(10, 10, 100, 100), mPaint);
    					mPaint.setColor(textColor);
    				}
    				@Override //可不重写此方法
    				protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
    					//设置自己的高宽
    					super.onMeasure(widthMeasureSpec, heightMeasureSpec);
    					//父元素推荐宽高
    				   // int w = MeasureSpec.getSize(widthMeasureSpec);
    				  //  int h = MeasureSpec.getSize(heightMeasureSpec);
    					//当前元素的模式
    				  //  int wMode = MeasureSpec.getMode(widthMeasureSpec);
    				  //  int hMode = MeasureSpec.getMode(heightMeasureSpec);
    					//MeasureSpec.AT_MOST //元素的宽高超过此值将不可见
    					//MeasureSpec.EXACTLY //元素已指定宽或高
    					//MeasureSpec.UNSPECIFIED //其他
    					//告知父元素本身高宽
    				  //  setMeasuredDimension(w, h);
    				}
    			}
    		定义 /values/attrs.xml
    			<?xml version="1.0" encoding="utf-8"?>
    			<resources>
    				<!--name 为自定义视图类名-->
    				<declare-styleable name="MyView">
    					<!-- color:颜色值 -->
    					<attr name="bgcolor" format="color" />
    					<!-- reference:参考某一资源ID 多种类型用|分割 -->
    					<attr name="backgroupd" format="reference|color" />
    					<!-- fraction:表示百分比 -->
    					<attr name = "pivotX" format = "fraction" />
    					<!-- string:表示字符串 -->
    					<attr name = "apiKey" format = "string" />
    					<!-- integer:表示整形 -->
    					<attr name = "count" format="integer" />
    					<!-- float:表示浮点数 -->
    					<attr name = "namefloat" format = "float" />
    					<!-- dimension:表示尺寸 -->
    					<attr name = "namedimension" format = "dimension" />
    					<!-- dimension:表示布尔 -->
    					<attr name = "nameboolean" format = "boolean" />
    					<!-- flag TAG:表示可以进行位运算 使用 mode1|mode2 -->
    					<attr name="mode">
    						<flag name = "mode1" value = "0" />
    						<flag name = "mode2" value = "1" />
    					</attr>
    					<!-- enum TAG:选择其中一个 -->
    					<attr name="orientation">
    						<enum name="horizontal" value="0" />
    						<enum name="vertical" value="1" />
    					</attr>
    					<attr name="textSize" format="dimension" />
    				</declare-styleable>
    			</resources>
    		使用自定义view
    			 <LinearLayout
    				android:layout_width="wrap_content"
    				android:layout_height="wrap_content"
    				xmlns:custom="http://schemas.android.com/apk/res-auto"
    				>
    				<com.example.dome1.MyView
    					custom:bgcolor="#000000"
    					android:layout_width="wrap_content"
    					android:layout_height="wrap_content"
    					/>
    			</LinearLayout>
    			
    	自定义视图组
    		public class myviewgroup extends ViewGroup {
    			public ccimg(Context context) {
    				super(context);
    			}
    			public ccimg(Context context, AttributeSet attrs) {
    				super(context, attrs);
    				//设置属性
    		//        TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.MyView);
    		//        textColor = a.getColor(R.styleable.MyView_bgcolor, 0XFFFFFFFF);
    		//        float textSize = a.getDimension(R.styleable.MyView_textSize, 36);
    		//        a.recycle();
    		//        mPaint = new Paint();
    		//        mPaint.setTextSize(textSize);
    		//        mPaint.setColor(textColor);
    			}
    			@Override
    			protected void onDraw(Canvas canvas) {
    				super.onDraw(canvas);
    				//绘制自己的内容
    			}
    			@Override
    			protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
    				// 设置子视图
    				int padding=20,
    					wh=100;
    				for (int i = 0, size = getChildCount(); i < size; i++) {
    					View view = getChildAt(i);
    					// 放置子View,宽高都是100
    					view.layout(left, top, left + wh, top + wh);
    					left += wh + padding;
    				}
    			}
    			@Override
    			protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
    				//设置自己的高宽
    				super.onMeasure(widthMeasureSpec, heightMeasureSpec);
    				//getMeasuredWidth() //运算得到实际内容宽度
    				//getMeasuredHeight() //运算得到实际内容高度
    				//父元素推荐宽高
    			   // int w = MeasureSpec.getSize(widthMeasureSpec);
    			  //  int h = MeasureSpec.getSize(heightMeasureSpec);
    				//当前元素的模式
    			  //  int wMode = MeasureSpec.getMode(widthMeasureSpec);
    			  //  int hMode = MeasureSpec.getMode(heightMeasureSpec);
    				//MeasureSpec.AT_MOST //元素的宽高超过此值将不可见
    				//MeasureSpec.EXACTLY //元素已指定宽或高
    				//MeasureSpec.UNSPECIFIED //其他
    				//告知父元素本身高宽
    			  //  setMeasuredDimension(w, h);
    			}
    		}
    		
    	弹出窗口
    		1. 对话框 Dialog 子类
    			一般对话框可以直接用 AlertDialog.Builder alert= new AlertDialog.Builder(this);
    			或者重写 AlertDialog 类实现一些自己的弹框提示 示例:
    				AlertDialog.Builder alert = new AlertDialog.Builder(TouchActivity.this);
    				alert.setTitle("Alert");
    				alert.setMessage("messgae");
    				alert.show();
    			或继承 dialog 示例:
    				 public class MyCustomDialog extends Dialog {
    					public MyCustomDialog(Context context) {
    						super(context);
    					}
    					@Override
    					protected void onCreate(Bundle savedInstanceState) {
    						super.onCreate(savedInstanceState);
    						setContentView(R.layout.xxx);
    						//设置标题
    						setTitle("this is title");
    						Button clickBtn = (Button) findViewById(R.id.button);
    						clickBtn.setOnClickListener(new View.OnClickListener() {
    							@Override
    							public void onClick(View v) {
    								MyCustomDialog.this.dismiss();
    							}
    						});
    					}
    				}
    				
    				
    		2. 使用 Activity 加样式 
    			样式:
    				<style name="MyDialogStyle">
    					<item name="android:windowBackground">@android:color/transparent</item>
    					<item name="android:windowFrame">@null</item>
    					<item name="android:windowNoTitle">true</item>
    					<item name="android:windowIsFloating">true</item>
    					<item name="android:windowIsTranslucent">true</item>
    					<item name="android:windowContentOverlay">@null</item>
    					<item name="android:windowAnimationStyle">@android:style/Animation.Dialog</item>
    					<item name="android:backgroundDimEnabled">true</item>
    				</style>
    			在 AndroidManifest.xml 注册
    				<activity android:name=".tabactivity" android:theme="@style/MyDialogStyle"></activity>
    			使用:
    				Intent i= new Intent(MainActivity.this,tabactivity.class);
                    startActivityForResult(i);
    				
    		3. 使用 PopupWindow 类 示例:
    			 //选择布局填充视图
    			View contentView = LayoutInflater.from(MainActivity.this).inflate(
    					R.layout.tab, null);
    			Button button = (Button) contentView.findViewById(R.id.button3);
    			//创建弹出窗口
    			final PopupWindow popupWindow = new PopupWindow(contentView,
    					LayoutParams.MATCH_PARENT, LayoutParams.WRAP_CONTENT, true);
    			button.setOnClickListener(new View.OnClickListener() {
    				@Override
    				public void onClick(View v) {
    					popupWindow.dismiss();//关闭
    				}
    			});
    			popupWindow.setTouchable(true);
    			popupWindow.setTouchInterceptor(new View.OnTouchListener() {
    				@Override
    				public boolean onTouch(View v, MotionEvent event) {
    					return false;
    				}
    			});
    			popupWindow.setBackgroundDrawable(getDrawable(R.drawable.a));
    			popupWindow.showAsDropDown(contentView);
    
    # 运行时授权 
    	要添加在 AndroidManifest.xml 添加 uses-permission
    	 @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_main);
    
            if(Build.VERSION.SDK_INT>=23) {
                //单个
                int hasWriteContactsPermission = checkSelfPermission(Manifest.permission.CAMERA);
                if (hasWriteContactsPermission != PackageManager.PERMISSION_GRANTED) {
                    if (!shouldShowRequestPermissionRationale(Manifest.permission.ACCESS_FINE_LOCATION)) {
    					//false 表示授权拒绝
                        Log.i("xxx", "auth bad 4");
                    }else{
                        requestPermissions(new String[]{Manifest.permission.CAMERA},222);
                    }
                }else{
                    Log.i("xxx", "auth ok 2");
                }
                //多个
                final List permissionsNeeded = new ArrayList();
                final List<String> permissionsList = new ArrayList<String>();
                if (checkSelfPermission(Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED) {
                    permissionsList.add(Manifest.permission.ACCESS_FINE_LOCATION);
                    // Check for Rationale Option
                    if (!shouldShowRequestPermissionRationale(Manifest.permission.ACCESS_FINE_LOCATION)) {
                        //false 表示授权拒绝
                        permissionsNeeded.add("need location");
                    }
                }
                if (checkSelfPermission(Manifest.permission.WRITE_CONTACTS) != PackageManager.PERMISSION_GRANTED) {
                    permissionsList.add(Manifest.permission.WRITE_CONTACTS);
                    // Check for Rationale Option
                    if (!shouldShowRequestPermissionRationale(Manifest.permission.WRITE_CONTACTS)) {
                        //false 表示授权拒绝
                        permissionsNeeded.add("need contats");
                    }
                }
                if (permissionsList.size() > 0) {
                    if (permissionsNeeded.size() > 0) {
                        Log.i("xxx", "auth bad 1");
                    }
                    requestPermissions(permissionsList.toArray(new String[permissionsList.size()]), 111);
                }else{
                    Log.i("xxx", "auth ok 3");
                }
            }
        }
        @Override
        public void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults) {
            switch (requestCode) {
                case 111:
                    Map<String, Integer> perms = new HashMap<String, Integer>();
                    // Initial
                    perms.put(Manifest.permission.WRITE_CONTACTS, PackageManager.PERMISSION_GRANTED);
                    perms.put(Manifest.permission.ACCESS_FINE_LOCATION, PackageManager.PERMISSION_GRANTED);
                    // Fill with results
                    for (int i = 0; i < permissions.length; i++  )
                        perms.put(permissions[i], grantResults[i]);
                    // Check for ACCESS_FINE_LOCATION
                    if (perms.get(Manifest.permission.ACCESS_FINE_LOCATION) == PackageManager.PERMISSION_GRANTED
                            && perms.get(Manifest.permission.WRITE_CONTACTS) == PackageManager.PERMISSION_GRANTED) {
                        Log.i("xxx","auth ok 4");
                    } else {
                        Log.i("xxx","auth bad 2");
                    }
                break;
                case 222:
                    if (grantResults[0] == PackageManager.PERMISSION_GRANTED) {
                        Log.i("xxx","auth ok 1");
                    } else {
                        Log.i("xxx","auth bad 3");
                    }
                break;
                default:
                    super.onRequestPermissionsResult(requestCode, permissions, grantResults);
            }
        }
    			
    # 视图坐标
    	获取屏幕区域的宽高等尺寸获取
    		DisplayMetrics metrics = new DisplayMetrics();
    		getWindowManager().getDefaultDisplay().getMetrics(metrics);
    		int widthPixels = metrics.widthPixels;
    		int heightPixels = metrics.heightPixels;
    	
    	应用程序App区域宽高等尺寸获取
    		Rect rect = new Rect();
    		getWindow().getDecorView().getWindowVisibleDisplayFrame(rect);
    	
    	获取状态栏高度
    		Rect rect= new Rect();
    		getWindow().getDecorView().getWindowVisibleDisplayFrame(rect);
    		int statusBarHeight = rectangle.top;
    	
    	View布局区域宽高等尺寸获取
    		Rect rect = new Rect();  
    		getWindow().findViewById(Window.ID_ANDROID_CONTENT).getDrawingRect(rect);  
    
    	View的静态坐标方法
    		getScrollY() 返回View竖向滚动距离
    		getScrollX() 返回View横向滚动距离
    		getLeft()	返回View自身左边到父布局左边的距离
    		getTop()	返回View自身顶边到父布局顶边的距离
    		getRight()	返回View自身右边到父布局左边的距离
    		getBottom()	返回View自身底边到父布局顶边的距离
    		getX()	返回值为getLeft()+getTranslationX(),当setTranslationX()时getLeft()不变,getX()变。
    		getY()	返回值为getTop()+getTranslationY(),当setTranslationY()时getTop()不变,getY()变。	
    	
    	MotionEvent坐标方法
    		getX()	当前触摸事件距离当前View左边的距离
    		getY()	当前触摸事件距离当前View顶边的距离
    		getRawX()	当前触摸事件距离整个屏幕左边的距离
    		getRawY()	当前触摸事件距离整个屏幕顶边的距离
    	
    	View宽高方法
    		getWidth()	layout后有效,返回值是mRight-mLeft,一般会参考measure的宽度(measure可能没用),但不是必须的。
    		getHeight()	layout后有效,返回值是mBottom-mTop,一般会参考measure的高度(measure可能没用),但不是必须的。
    		getMeasuredWidth()	返回measure过程得到的mMeasuredWidth值,供layout参考,或许没用。
    		getMeasuredHeight()	返回measure过程得到的mMeasuredHeight值,供layout参考,或许没用。
    	
    	View的方法
    	getLocalVisibleRect()	
    		获取View自身可见的坐标区域,坐标以(0,0)开始,另一点为可见区域右下角相对自己(0,0)点的坐标
    		例子:(0, 0 - 410, 100)
    	getGlobalVisibleRect()
    		获取View在屏幕绝对坐标系中的可视区域,坐标以原点开始的坐标,另一点为可见区域右下角原点的坐标
    		例子:(30, 100)	(30, 250)
    	getLocationOnScreen()
    		坐标是相对整个屏幕而言,Y坐标为View左上角到屏幕顶部的距离。
    	getLocationInWindow()		
    		如果为普通Activity则Y坐标为View左上角到屏幕顶部(此时Window与屏幕一样大);如果为对话框式的Activity则Y坐标为当前Dialog模式Activity的标题栏顶部到View左上角的距离。
    		
    	View的滑动方法
    		offsetLeftAndRight(int offset)	水平方向挪动View,offset为正则x轴正向移动,移动的是整个View,getLeft()会变的,自定义View很有用。
    		offsetTopAndBottom(int offset)	垂直方向挪动View,offset为正则y轴正向移动,移动的是整个View,getTop()会变的,自定义View很有用。
    		scrollTo(int x, int y)	将View中内容(不是整个View)滑动到相应的位置,参考坐标原点为ParentView左上角,x,y为正则向xy轴反方向移动,反之同理。
    		scrollBy(int x, int y)	在scrollTo()的基础上继续滑动xy。
    		setScrollX(int value)	实质为scrollTo(),只是只改变Y轴滑动。
    		setScrollY(int value)	实质为scrollTo(),只是只改变X轴滑动。
    		getScrollX()/getScrollY()	获取当前滑动位置偏移量。
    
    
    # 组件调用 Intent
    
    	1. 隐式添加
    		向系统注册静态 Intent 在 AndroidManifest 加 intent-filter
    			<activity
    				android:name=".activity.MyActivity"
    				android:label="@string/ac_name_image_list" >
    				<intent-filter>
    					<action android:name="mxp"/>
    					<category android:name="android.intent.category.DEFAULT" />
    				</intent-filter>
    			</activity>
    		在 MyActivity 添加  public static final String MY_ACTION = "mxp";
    		启动: startActivity(new Intent(MyActivity.MY_ACTION));
    		关于 category 匹配
    			如下 AndroidManifest
    			<intent-filter>  
                    <action android:name="action1" />
                    <category android:name="cate1"/>
                    <category android:name="android.intent.category.DEFAULT" />  
                </intent-filter>
    			启动 
    			Intent intent = new Intent("action1");
    			intent.addCategory("cate1");//有无都匹配
    			startActivity(intent);
    		关于 data 匹配
    			如下 AndroidManifest
    			 <intent-filter>
                    <action android:name="action1" />
                    <category android:name="android.intent.category.DEFAULT" />
                    <data android:scheme="file" />
                    <data android:mimeType="audio/*" />
                    <data android:pathPattern=".*.mp3" /><!-路径匹配->
                </intent-filter>
    			启动 
    			Uri uri=Uri.parse("file://aaaa.mp3");
    			Intent intent = new Intent("action1");
    			intent.setData(uri);
    			startActivity(intent);
    		
    	2. 基本组件通过Intent来相互调用  setExtras getExtras 参数传递
    	
    	3. PendingIntent
    		包装Intent,使Intent延时触发,有以下类型
    		PendingIntent.getBroadcast()
    		PendingIntent.getActivity() & PendingIntent.getActivities()
    		PendingIntent.getService()
    		
    	4. 可通过 ComponentName 进行调用
    		Intent it=new Intent();
            it.setComponent(new ComponentName(getPackageName(),MyActivity.class.getName()));
            startActivity(it)
    
    	
    			
    			
    
    # 加载管理 Loader
    	
    	CursorLoader 使用示例,一般使用在 Cursor 数据源下
    		public static class CursorLoaderListFragment extends ListFragment
    				implements LoaderManager.LoaderCallbacks<Cursor> {
    			SimpleCursorAdapter mAdapter;
    			@Override
    			public void onActivityCreated(Bundle savedInstanceState) {
    				super.onActivityCreated(savedInstanceState);
    				mAdapter = new SimpleCursorAdapter(getActivity(),
    						android.R.layout.simple_list_item_2, null,
    						new String[] { ContactsContract.Contacts.DISPLAY_NAME, ContactsContract.Contacts.CONTACT_STATUS },
    						new int[] { android.R.id.text1, android.R.id.text2 }, 0);
    				setListAdapter(mAdapter);
    				getLoaderManager().initLoader(0, null, this);
    			}
    			static final String[] CONTACTS_SUMMARY_PROJECTION = new String[] {
    					ContactsContract.Contacts._ID,
    					ContactsContract.Contacts.DISPLAY_NAME,
    					ContactsContract.Contacts.CONTACT_STATUS,
    					ContactsContract.Contacts.CONTACT_PRESENCE,
    					ContactsContract.Contacts.PHOTO_ID,
    					ContactsContract.Contacts.LOOKUP_KEY,
    			};
    			public Loader<Cursor> onCreateLoader(int id, Bundle args) {
    				Uri baseUri;
    				baseUri = ContactsContract.Contacts.CONTENT_URI;
    				String select = "";
    				//返回游标Loader
    				return new CursorLoader(getActivity(), baseUri,
    						CONTACTS_SUMMARY_PROJECTION, select, null,
    						ContactsContract.Contacts.DISPLAY_NAME + " COLLATE LOCALIZED ASC");
    			}
    			public void onLoadFinished(Loader<Cursor> loader, Cursor data) {
    				//加载完成回调,重设游标
    				mAdapter.swapCursor(data);
    				// The list should now be shown.
    				if (isResumed()) {
    					setListShown(true);
    				} else {
    					setListShownNoAnimation(true);
    				}
    			}
    			public void onLoaderReset(Loader<Cursor> loader) {
    				//重设
    				mAdapter.swapCursor(null);
    			}
    		}
    		
    	AsyncTaskLoader 使用示例,一般用在数据加载,如列表等, 
    	如 Activity 里多个 Fragment 时候 方便管理,只有简单数据加载 可直接用 封装AsyncTask 
    		class  myloader extends AsyncTaskLoader<List<String>>{
    			Bundle args;
    			public myloader(Context context, Bundle args) {
    				super(context);
    				this.args=args;
    			}
    			@Override
    			public List<String> loadInBackground() {
    				// 根据 this.args 不同进行处理
    				Log.i("myout","out");
    				List<String> my= new ArrayList<String>();
    				my.add("hi");
    				return my;
    			}
    			@Override
    			public void cancelLoadInBackground() {
    				//当发生取消时候调用.如请求服务器数据.这里进行取消操作
    			}
    			@Override
    			protected void onStartLoading() {
    				forceLoad();
    			}
    			@Override
    			protected void onStopLoading() {
    				cancelLoad();
    			}
    			@Override
    			protected void onReset() {
    				super.onReset();
    				onStopLoading();
    			}
    		}
    		使用AsyncTask
    		final ListView lv= (ListView)findViewById(R.id.listView);
            final ArrayAdapter apt=new ArrayAdapter<String>(this,android.R.layout.simple_list_item_1,android.R.id.text1);
            lv.setAdapter(apt);
    		final LoaderManager.LoaderCallbacks loadercallback = new LoaderManager.LoaderCallbacks<List<Map<String,String>>>(){
                @Override
                public Loader<List<Map<String,String>>> onCreateLoader(int id, Bundle args) {
                    return new myloader(MainActivity.this,args);
                }
                @Override
                public void onLoadFinished(Loader<List<Map<String,String>>> loader, List<Map<String,String>> data) {
                    apt.addAll(data);
                    //加载完成,进行其他视图更新
                }
                @Override
                public void onLoaderReset(Loader<List<Map<String,String>>> loader) {
    				//当调用 getLoaderManager().destroyLoader(1);
                    apt.clear();
    				//进行视图清空处理等
                }
            };
    		//初始化加载
            getLoaderManager().initLoader(1, null, loadercallback);
    		//重新加载数据
    		getLoaderManager().destroyLoader(1);
    		getLoaderManager().initLoader(1, null, loadercallback);
    		//重新启动加载器(非重新加载数据,如需要加载下一页数据)
    		getLoaderManager().restartLoader(1,b,loadercallback);
    		
    
    # 页面 Activity
    
    	R.drawable 图片资源 
    	R.string 字符资源
    	R.menu 菜单 比较特殊的一个View 菜单填充用 MenuInflater
    		示例:
    			xml:
    			<menu xmlns:android="http://schemas.android.com/apk/res/android" >
    				<item
    					android:id="@+id/share_item"
    					android:orderInCategory="100"
    					app:showAsAction="always"
    					android:title="分享"
    					/>
    			</menu>
    		添加及监听:
    			@Override
    			public boolean onCreateOptionsMenu(Menu menu) {
    				getMenuInflater().inflate(R.menu.my,menu);
    				return super.onCreateOptionsMenu(menu);
    			}
    			@Override
    			public boolean onOptionsItemSelected(MenuItem item) {
    				switch (item.getItemId()) {
    					case R.id.share_item:
    						break;
    				}
    				return super.onOptionsItemSelected(item);
    			}
    			
    	资源 assets 通过 getAssets().open() 来访问
    	
    	资源 Resources 通过 get** 系列获取函数 如getDrawable(R.drawable.a1); 获得 drawable 对象
    	
    		
    	填充获取布局View (注意:获取到后未添加到显示视图中)
    		getLayoutInflater().inflate(R.layout.activity_touch, null);
            ((LayoutInflater){Context}.getSystemService(Context.LAYOUT_INFLATER_SERVICE)).inflate(R.layout.activity_touch, null);
    	
    	ViewGroup 下 Layout 用来布局页面	
    		LayoutInflater 处理layout XML 资源 返回View
    	R.id 在ids.xml有部分预设ID,在android.R.id 下 如content为当前视图根节点
    		ViewGroup rootnode = (ViewGroup)findViewById(android.R.id.content);//根节点
    	遍历ViewGroup的子视图
    		ViewGroup viewById = (ViewGroup)findViewById(android.R.id.content);
            for (int i=0;i<viewById.getChildCount();i++)
            viewById.getChildAt(i);
    	
    	添加视图(ViteGroup对象可用)
    		TextView t=new TextView(this);
            t.setText("fsadf");
            rootnode.addView(t);
    		
    	片段 Fragment 及管理 可添加,替换等 (未显示的页面) (XML不能是空的Fragment)
    		填充 附属至相应的Activity生效
    		通过getView() 处理里面的view
    		FragmentActivity 提供辅助 Fragment 的方法
    		示例代码
    			代码方式添加
    			public static class PlaceholderFragment extends Fragment {
    				public PlaceholderFragment() {
    				}
    				@Override
    				public View onCreateView(LayoutInflater inflater, ViewGroup container,
    						Bundle savedInstanceState) {
    					View rootView = inflater.inflate(R.layout.fragment_main, container,
    							false);
    					return rootView;
    				}
    			}
    			添加进显示
    			if (savedInstanceState == null) {
    				getFragmentManager().beginTransaction()
    					.add(R.id.container, new PlaceholderFragment()).commit();
    			}
    			//添加但不显示
    			getFragmentManager().beginTransaction().add(ttt, "ttt").commit();
    			//获取
    			Fragment ttt = getFragmentManager().findFragmentByTag("ttt");
    			
    		XML 方式添加 (必须要有id属性)
    			<fragment 
    				android:id="@+id/id_fragment_title"
    				android:name="com.example.xxx.MainActivity$PlaceholderFragment"
    				android:layout_width="match_parent"
    				android:layout_height="match_parent"
    			 />
    			通过 setContentView(R.layout.activity_main);
    	
    		
    	数据传递
    		设置
    			Intent intent = new Intent("action1");
    			intent.putExtra("test","xxx");
    			startActivity(intent);
    		获取 get...Extra 系列方法
    			getIntent().getStringExtra("test");
    		通过Uri 的数据
    			Uri uri=getIntent().getData();
    		跳转返回
    			//起始 Activity: 1->requestCode
    			{...
    			Intent intent=new Intent("action1");
    			startActivityForResult(intent, 1);
    			...}
    			@Override
    			rotected void onActivityResult(int requestCode, int resultCode, Intent data) {
    				super.onActivityResult(requestCode, resultCode, data);
    				switch(requestCode){
    					case 1:
    						switch(resultCode){
    							case 1:
    								//处理数据
    							break;
    						}
    					break;
    				}
    			}
    			//数据 Activity: 1->resultCode
    			setResult(1, intent);
    			finish();
    		于 Fragment 的数据传递
    			Activity 设置数据
    			PlaceholderFragment my = new PlaceholderFragment();
    			Bundle bundle = new Bundle();
    			bundle.putString("test","test");
    			my.setArguments(bundle);
    			在 PlaceholderFragment 的 onCreateView 中获取
    			Bundle arguments = my.getArguments();
    			
    
    
    			
    
    # 数据适配器
    	1. 视图分配
    		a. 重写 Adapter 的getView
    		b. setViewBinder 重写 ViewBinder的setViewValue方法
    		
    	2. BaseAdapter 基本适配器
    		完全自主 适配器基类 数据源可不定格式
    		
    	3. SimpleAdapter 简单适配器 (简单键值对数据)
    		格式:Context context, List<? extends Map<String, ?>> data,
    			int resource, String[] from, int[] to
    			
    		提供数据(MAP LIST) 布局 数据格式 布局元素
    		根据提供的格式渲染
    		示例:
    			List<Map<String,String>> list= new ArrayList<Map<String, String>>();
    			Map<String,String> m1= new HashMap<String,String>();
    			m1.put("aa","aaa");
    			m1.put("bb", "bbb");
    			list.add(m1);
    			SimpleAdapter sa= new SimpleAdapter(this,list,R.layout.text,
    				new String[]{"aa","bb"},new int[]{R.id.aa,R.id.bb});
    				
    	4. ArrayAdapter<T> 数组适配器 (类型固定,非简单键值对,如建模的对象,或String)
    		a. 简单String
    		示例:
    			ArrayAdapter aa=new ArrayAdapter<String>(this,R.layout.text,R.id.aa);
    			aa.add("sssssssssssss");
    			
    		b. 指定类类型 一般需重写:视图分配
    		
    	5. CursorAdapter 游标适配器
    		一般用于通过 Content Provider 的数据,如果联系人,本地数据库等
    		示例:
    			Cursor curContacts=getContentResolver().query(ContactsContract.Contacts.CONTENT_URI,new String[]{
    				ContactsContract.Contacts._ID,
    				ContactsContract.Contacts.DISPLAY_NAME,
    				ContactsContract.Contacts.HAS_PHONE_NUMBER,
    				ContactsContract.Contacts.LOOKUP_KEY}, null, null, null);
    			CursorAdapter aa = new MyCursorAdapter(this,curContacts);
    			//重写 newView bindView 方法实现视图
    			class MyCursorAdapter extends CursorAdapter {
    				public MyCursorAdapter(Context context, Cursor c) {
    					super(context, c,true);
    				}
    				public View newView(Context context, Cursor cursor, ViewGroup parent) {
    					LayoutInflater vi = null;
    					vi = getLayoutInflater();
    					View v=vi.inflate(R.layout.text, parent, false);
    					TextView view = (TextView)v.findViewById(R.id.aa);
    					return view;
    				}
    				@Override
    				public void bindView(View v, Context context, Cursor cursor) {
    					TextView nameView = (TextView)v.findViewById(R.id.aa);
    					nameView.setText(cursor
    							.getString(cursor.getColumnIndex(ContactsContract.Contacts.DISPLAY_NAME)));
    				}
    			}
    			
    	6.? ResourceCursorAdapter & SimpleCursorAdapter 对 CursorAdapter 的再次封装
    		其中 SimpleCursorAdapter 实现了类似于 SimpleAdapter 的封装
    		示例:
    			Cursor curContacts=getContentResolver().query(ContactsContract.Contacts.CONTENT_URI,new String[]{
    					ContactsContract.Contacts._ID,
    					ContactsContract.Contacts.DISPLAY_NAME,
    					ContactsContract.Contacts.HAS_PHONE_NUMBER,
    					ContactsContract.Contacts.LOOKUP_KEY}, null, null, null);
    			lv.setAdapter(new SimpleCursorAdapter(this,R.layout.text,curContacts,new String[]{
    					ContactsContract.Contacts.DISPLAY_NAME, ContactsContract.Contacts.HAS_PHONE_NUMBER
    			},new int[]{
    					R.id.aa,R.id.bb
    			},CursorAdapter.FLAG_REGISTER_CONTENT_OBSERVER));
    			
    	7. 数据修改 
    		a. 数据源变动 适配器的数据为初始化时候的源,或通过适配器修改数据,将会自动反应到视图
    		2. 视图数据变动 修改视图后,调用适配器的 notifyDataSetChanged 方法,将会把视图数据反应到数据源
    
    
    	
    # 异步执行与数据交互
    	1. 请求线程创建
    		1. 手动创建线程
    			 final Handler h = new Handler(){
    				@Override
    				public void handleMessage(Message msg) {
    					super.handleMessage(msg);
    					Bundle b= msg.getData();
    					//视图线程,处理视图
    				}
    			};
    			new Thread(){
    				@Override
    				public void run() {
    					//请求数据等...
    					Message msg= new Message();
    					Bundle b=new Bundle();
    					//设置数据
    					msg.setData(b);
    					h.sendMessage(msg);
    					super.run();
    				}
    			}.start();
    			
    		2. 使用AsyncTask
    			//AsyncTask 类型: 根据需要传递
    			// 请求参数,进度参数,执行完返回结果
    			private class MyTask extends AsyncTask<String, Integer, String> {
    				@Override
    				protected void onPreExecute() {
    					//请求前调用,可处理UI
    				}
    				@Override
    				protected String doInBackground(String... params) {
    					//处理请求等操作,请求线程,不处理UI
    					//setProgress();操作进度
    					return null;
    				}
    				@Override
    				protected void onProgressUpdate(Integer... progresses) {
    				   //进度操作,处理UI
    				}
    				@Override
    				protected void onPostExecute(String result) {
    					//执行完操作.处理UI
    				}
    				@Override
    				protected void onCancelled() {
    					//用户取消操作,处理UI
    				}
    			}
    			调用:
    			new MyTask().execute("/*request prams*/");
    		
    	2. 请求方式
    		a. 使用OkHttpClient 库 compile 'com.squareup.okhttp:okhttp:2.4.0'
    			全局公用 OkHttpClient client= new OkHttpClient();
    			有 Request 请求对象 和 Response 返回对象
    			示例
    				OkHttpClient client= new OkHttpClient();
    				Request request = new Request.Builder().url("url").build();
    				Response response = null;
    				try {
    					response = client.newCall(request).execute();
    				} catch (IOException e) {
    					e.printStackTrace();
    					return null;
    				}
    				if(response.isSuccessful()){
    					String c=response.body().toString();
    					return c;
    				}
    				
    		b. 使用JAVA网络库
    			URL url;
    			StringBuffer sb=new StringBuffer();
    			try {
    				url=new URL("url");
    				InputStreamReader isr=new InputStreamReader(url.openStream());
    				BufferedReader br= new BufferedReader(isr);
    				String str;
    				while((str=br.readLine())!=null)
    				{
    					sb.append(str);
    				}
    			} catch (Exception e) {
    				e.printStackTrace();
    				return null;
    			}
    			return sb.toString();
    			
    	3. 数据处理
    		a. JSON 处理 (还有GSON等库可用)
    			内置JSON:
    				String json="{}";
    				JSONTokener jsontoken= new JSONTokener(json);
    				JSONObject jsonobject = null;
    				JSONArray jsonarr;
    				ArrayList<String>outarr;
    				try {
    					jsonobject = (JSONObject) jsontoken.nextValue();
    					//JSON 简单数据类型:
    					String strval=jsonobject.getString("strkey");
    					//JSON 复合数据类型:
    					jsonarr =jsonobject.getJSONArray("arrkey");
    					outarr =new ArrayList<String>();
    					for (int i=0;i<jsonarr.length();i++){
    						outarr.add(jsonarr.get(i).toString());
    					}
    				} catch (JSONException e) {
    					e.printStackTrace();
    				}
    				
    				String json="[]";
    				JSONTokener jsontoken= new JSONTokener(json);
    				try {
    					JSONArray jsonarr = (JSONArray) jsontoken.nextValue();
    					for (int i=0;i<jsonarr.length();i++){
    						JSONObject t=(JSONObject)jsonarr.get(i);
    						Log.i("xxx",t.getString("tit"));
    					}
    				} catch (JSONException e) {
    					e.printStackTrace();
    				}
    				
    				
    			GSON: 可以直接把JSON转成MODEL
    				JsonParser parser = new JsonParser();
    				String json1="{}";
    				JsonElement objel = parser.parse(json1);
    				if(!objel.isJsonObject())  return ;
    				//User u = gson.fromJson(objel, User.class);
    				JsonObject jobj = objel.getAsJsonObject();
    				Log.i("xxx",jobj.get("tit").getAsString());
    
    				
    				String json1="{users:[]}";
    				JsonParser parser = new JsonParser();
    				JsonElement objel = parser.parse(json1);
    				if(!objel.isJsonObject())  return ;
    				JsonObject jobj = objel.getAsJsonObject();
    				Gson gson = new Gson();
    				List users = gson.fromJson(jobj.get("users"), new TypeToken<List>() {
    				}.getType());
    
    				String json="[]";
    				JsonParser parser = new JsonParser();
    				JsonElement el = parser.parse(json);
    				JsonArray jsonArray = null;
    				if(el.isJsonArray()){
    					jsonArray = el.getAsJsonArray();
    				}
    				Gson gson = new Gson();
    				Iterator it = jsonArray.iterator();
    				while(it.hasNext()){
    					JsonElement e = (JsonElement)it.next();
    					User u = gson.fromJson(e, User.class);
    					Log.i("xxx",u.getSrc());
    				}
    			
    		b. XML 处理 (还有DOM SAX库可用)
    			try {
    				URL url;
    				url=new URL("http://www.urltest.tk/a.php");
    				InputStream is= null;
    				is = url.openStream();
    				XmlPullParser parser = Xml.newPullParser();
    				int eventType = 0;
    				parser.setInput(is, "UTF-8");
    				eventType = parser.getEventType();
    				while (eventType != XmlPullParser.END_DOCUMENT) {
    					switch (eventType) {
    						case XmlPullParser.START_DOCUMENT:
    						   //文档开始
    							break;
    						case XmlPullParser.START_TAG:
    							if (parser.getName().equals("book")) {
    								//标签开始
    							}
    							break;
    						case XmlPullParser.END_TAG:
    							//标签结束
    							break;
    					}
    					eventType = parser.next();
    				}
    			} catch (Exception e) {
    				e.printStackTrace();
    				return ;
    			}
    
    # dataBinding 数据绑定 启用 android {... dataBinding { enabled = true }}
    	1. 视图绑定
    		XML:
    			<layout 
    				xmlns:android="http://schemas.android.com/apk/res/android"
    				xmlns:app="http://schemas.android.com/apk/res-auto"
    				>
    				<data class=".dataclassname">
    					<import type="com.example.dome2.User" alias="Myuser" />
    					<variable name="u" type="Myuser"/>
    				</data>
    				<TextView
    					android:text='@{u.hi}'
    					android:layout_width="wrap_content"
    					android:layout_height="wrap_content"
    					android:id="@+id/lastname"/>
    			</layout>
    			
    		注释:
    			class 属性表示视图绑定类的名 可不填,根据文件名生成
    			import 引入其他类方式 alias 防止类冲突
    			variable 定义变量
    			
    		used:
    			dataclassname binding = DataBindingUtil.setContentView(this, R.layout.activity_main);
    			binding.setU(/*xxx*/);// 根据 variable 自动生成方法
    			binding.lastname;//TextView 对象 根据 @+id 自动生成
    			
    		变量使用:
    			普通对象 @{user.lastName}
    			Map 对象 @{user["lastName"]}
    			Liset 对象 @{user[0]}
    			静态方法 @{String.valueOf(1 + (Integer)user["age"])}
    			运算 	@{user.displayName ?? user.lastName}
    					@{user.displayName != null ? user.displayName : user.lastName}
    					@{age < 13 ? View.GONE : View.VISIBLE} //<import type="android.view.View" />
    					@{@string/nameFormat(firstName)}
    
    	2. 数据模型
    		a. 自定义数据模型
    			//方式一 继承 BaseObservable
    				model:
    				public class User extends BaseObservable {
    					 private String hi;
    					@Bindable //必须有注释,在BR 中生成对应KEY
    					public String getHi() {
    						return this.hi;
    					}
    					public void setHi(String hi){
    						this.hi=hi;
    						notifyPropertyChanged(BR.hi);//提醒修改
    					}
    					//定义属性的操作方式
    					//定义组件属性
    					//app:imageUrl="@{user.src}" 方式使用
    					@BindingAdapter({"bind:imageUrl"}) 
    					public static void loadImage(SimpleDraweeView view, String url) {
    						Uri uri = Uri.parse(url);
    						view.setImageURI(uri);
    					}
    					//使用自带属性
    					@BindingAdapter("android:paddingLeft")
    					public static void setPaddingLeft(View view, int padding) {
    					   view.setPadding(padding,
    						   view.getPaddingTop(),
    						   view.getPaddingRight(),
    						   view.getPaddingBottom());
    					}
    				}
    				xml:
    				<layout 
    					xmlns:android="http://schemas.android.com/apk/res/android"
    					xmlns:app="http://schemas.android.com/apk/res-auto"
    					>
    					<data class=".dataclassname">
    						<import type="com.example.dome2.User" alias="Myuser" />
    						<variable name="u" type="Myuser"/>
    					</data>
    					<TextView
    						android:text='@{u.hi}'
    						android:layout_width="wrap_content"
    						android:layout_height="wrap_content"
    						android:id="@+id/lastname"/>
    					<com.facebook.drawee.view.SimpleDraweeView
    						app:imageUrl="@{u.hi}"
    						android:id="@+id/img"
    						android:layout_width="100dp"
    						android:layout_height="wrap_content"
    						/>
    				</layout>
    				used:
    				dataclassname binding = DataBindingUtil.setContentView(this, R.layout.activity_main);
    				User data=new User();//其他代码...
    				data.setHi('xxx');
    				binding.setU(data);
    
    			//方式二 属性用 Observable 系列类
    				model:
    				public class User{
    					public final ObservableField<String> lastName =
    					   new ObservableField<>();
    					public final ObservableInt age = new ObservableInt();
    				}
    				xml:
    				<layout xmlns:android="http://schemas.android.com/apk/res/android">
    					<data class=".dataclassname">
    						<import type="com.example.dome2.User" alias="Myuser" />
    						<variable name="userdata" type="Myuser"/>
    					</data>
    					<TextView
    						android:text='@{userdata.lastName}'
    						android:layout_width="wrap_content"
    						android:layout_height="wrap_content"
    						android:id="@+id/lastname"/>
    				</layout>
    				used:
    				dataclassname binding = DataBindingUtil.setContentView(this, R.layout.activity_main);
    				User data=new User();//其他代码...
    				data.firstName.set("xxx");
    				binding.setUserdata(data);
    				
    			//方式三 无模型非列表
    				xml:
    				<layout xmlns:android="http://schemas.android.com/apk/res/android">
    					<data class=".dataclassname">
    						<import type="android.databinding.ObservableMap"/>
    						<variable name="prs" type="ObservableMap<String, Object>"/>
    					</data>
    					<TextView
    						android:text='@{prs["index"]}'
    						android:layout_width="wrap_content"
    						android:layout_height="wrap_content"
    						android:id="@+id/lastname"/>
    				</layout>
    				used:
    				ObservableArrayMap<String, Object> prs = new ObservableArrayMap<>();
    				prs.put("index", String.valueOf(position));
    				binding.setPrs(prs);
    				
    			//方式四 无模型简单列表
    				xml:
    				<layout xmlns:android="http://schemas.android.com/apk/res/android">
    					<data class=".dataclassname">
    						<import type="android.databinding.ObservableList"/>
    						<variable name="xxx" type="ObservableList<Object>"/>
    					</data>
    					<TextView
    						android:text='@{xxx[0]}'
    						android:layout_width="wrap_content"
    						android:layout_height="wrap_content"
    						/>
    					<TextView
    						android:text='@{xxx[1]}'
    						android:layout_width="wrap_content"
    						android:layout_height="wrap_content"
    						/>
    				</layout>
    				used:
    				dataclassname binding = DataBindingUtil.setContentView(this, R.layout.activity_main);
    				ObservableArrayList<Object> user = new ObservableArrayList<>();
    				user.add("Google");
    				user.add("Inc.");
    				binding.setXxx(user);
    	3. 调用
    		1. 未知视图绑定类
    			dataclassname binding = DataBindingUtil.setContentView(this, R.layout.activity_main);
    			dataclassname binding = DataBindingUtil.inflate(LayoutInflater, layoutId, parent, attachToParent);
    		2. 已知视图绑定类
    			dataclassname binding = dataclassname.inflate(layoutInflater);
    			dataclassname binding = dataclassname.inflate(LayoutInflater, viewGroup, false);
    			dataclassname binding = dataclassname.bind(viewRoot);
    			
    	4. 返回视图
    		dataclassname binding = dataclassname.inflate(LayoutInflater, viewGroup, false);
    		binding.getRoot();
    
    # GestureDetector VelocityTracker 触摸手势 及 触摸速度
    	对屏幕的常用手势操作:
    		private GestureDetector gestureDetector;
    		@Override
    		protected void onCreate(Bundle savedInstanceState) {
    			super.onCreate(savedInstanceState);
    			setContentView(R.layout.tab);
    			gestureDetector = new GestureDetector(this, new GestureListener());
    			gestureDetector.setIsLongpressEnabled(false);
    		}
    		@Override
    		public boolean onTouchEvent(MotionEvent event) {
    			return gestureDetector.onTouchEvent(event);
    		}
    		// 继承于SimpleOnGestureListener,实现所有事件监听方法
    		private class GestureListener extends GestureDetector.SimpleOnGestureListener {
    			@Override
    			public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY) {
    				Log.i("2222", velocityX + "");
    				Log.i("2222", velocityY + "");
    				return super.onFling(e1, e2, velocityX, velocityY);
    			}
    			@Override
    			public boolean onDoubleTap(MotionEvent e) {
    				Log.i("test", "doubletap");
    				return super.onDoubleTap(e);
    			}
    		}
    	对屏幕的触摸速度:
    		private VelocityTracker mVelocityTracker = null;
    		@Override
    		public boolean onTouchEvent(MotionEvent event) {
    			int action = event.getAction();
    			if (mVelocityTracker == null)
    				mVelocityTracker = VelocityTracker.obtain();
    			mVelocityTracker.addMovement(event);
    			switch (action) {
    				case MotionEvent.ACTION_UP:
    					mVelocityTracker.computeCurrentVelocity(1000);//设置单位为毫秒
    					//移动像素距离
    					Log.i("11111", mVelocityTracker.getXVelocity(0) + "");
    					Log.i("11111", mVelocityTracker.getYVelocity(0) + "");
    					break;
    			}
    			return true;
    		}			
    			
    	
    # 图像资源 drawable
    	1. 缩放图片
    		<scale xmlns:android="http://schemas.android.com/apk/res/android"
    			android:scaleWidth="50%"
    			android:scaleHeight="50%"
    			android:drawable="@drawable/a6"
    			android:scaleGravity="center_vertical|center_horizontal"
    			>
    		</scale>
    		
    	2. 旋转图片
    		<rotate xmlns:android="http://schemas.android.com/apk/res/android"
    			android:drawable="@drawable/a1"
    			android:visible="true"
    			android:fromDegrees="-90"
    			android:toDegrees="180"
    			android:pivotX="50%"
    			android:pivotY="50%"
    			>
    		</rotate>
    	
    	3. 叠加图片
    		<?r circrsion="1.0" encoding="utf-8"?>
    		<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
    			<item>
    				<shape android:shape="oval" >
    					<solid android:color="#FFACB8C3" />
    				</shape>
    			</item>
    			<item
    				android:bottom="2dp"
    				android:left="2dp"
    				android:right="2dp"
    				android:top="2dp">
    				<shape android:shape="oval">
    					<solid android:color="#FFbdcad6" />
    				</shape>
    			</item>
    		</layer-list>
    		
    	4. 各种状态图片
    		<?xml version="1.0" encoding="utf-8"?>
    		<selector xmlns:android="http://schemas.android.com/apk/res/android">
    			<!-- 默认时的背景图片-->
    			<item android:drawable="@drawable/a2" android:state_focused="false" android:state_pressed="false"/>
    			<!-- 按下时状态-->
    			<item android:drawable="@drawable/a" android:state_pressed="true"/>
    			<!--获得焦点时的图片背景-->
    			<item android:drawable="@drawable/a3"  android:state_focused="true"/>
    			<!--无焦点状态-->
    			<item android:drawable="@drawable/a4" android:state_focused="false"/>
    		</selector>
    		<?xml version="1.0" encoding="utf-8" ?>
    		
    	5. 选择图片显示
    		<?xml version="1.0" encoding="utf-8" ?>
    		<level-list xmlns:android="http://schemas.android.com/apk/res/android" >
    			<item
    				android:drawable="@drawable/a1"
    				android:maxLevel="0" />
    			<item
    				android:drawable="@drawable/a2"
    				android:maxLevel="1" />
    		</level-list>
    		代码修改显示
    		final ImageView imageView = (ImageView) findViewById(R.id.imgView); 
    		imageView.setImageLevel(1);//默认的level为0,将到设置为1
    		//或 imageView.getDrawable().setLevel(1);
    		
    	6. 部分显示
    		<clip xmlns:android="http://schemas.android.com/apk/res/android"
    			android:drawable="@drawable/a1"
    			android:clipOrientation="horizontal"
    			android:gravity="left" />
    		代码修改显示
    		ImageView imageview = (ImageView) findViewById(R.id.image);
    		ClipDrawable drawable = (ClipDrawable) imageview.getDrawable();
    		drawable.setLevel(drawable.getLevel() + 1000);
    		
    	7. 9 PNG
    		将图片命名为 **.9.png 放入 drawable 之后调整边框即可
    	
    	8. 形状
    		shape 形状 如矩形等
    		<?xml version="1.0" encoding="utf-8"?>
    		<shape xmlns:android="http://schemas.android.com/apk/res/android">
    		<!-- 
    		shape 
    		android:shape=["rectangle" | "oval" | "line" | "ring"]
    		矩形(rectangle)、椭圆形(oval)、线性形状(line)、环形(ring)
    		-->
    			<!-- 实心 -->
    			<solid android:color="#ff9d77"/>
    			<!-- 渐变 -->
    			<gradient
    				android:startColor="#ff8c00"
    				android:endColor="#FFFFFF"
    				android:angle="270" />
    			<!-- 描边 -->
    			<stroke
    				android:width="2dp"
    				android:color="#dcdcdc" />
    			<!-- 圆角 -->
    			<corners
    				android:radius="2dp" />
    			<padding
    				android:left="10dp"
    				android:top="10dp"
    				android:right="10dp"
    				android:bottom="10dp" />
    		</shape>
    		环行实例
    		<?xml version="1.0" encoding="utf-8"?>
    		<shape xmlns:android="http://schemas.android.com/apk/res/android"
    			android:shape="ring"
    			android:innerRadius="20dp"
    			android:thickness="50dp"
    			android:useLevel="false">
    			<!--
    				innerRadius 内部半径
    				innerRadiusRatio 内部半径比例 innerRadius 存在 此值无效
    				thickness 环厚度
    				thicknessRatio 环厚度比例 thickness 存在 此值无效
    			-->
    			<stroke android:width="10dp"  android:color="#22ee0000" />
    			<!--
    			  stroke 描边
    			 -->
    			<solid android:color="#33ee0033"/>
    			<!--
    			solid  内容填
    			-->
    		</shape>
    	9. 偏移图片
    		<transition
    			xmlns:android="http://schemas.android.com/apk/res/android">
    			<item  android:top="-10dp" android:bottom="10dp" android:drawable="@drawable/a1" >
    		    </item>
    		</transition>
    		
    	10. 自定义图标SVG
    		<?xml version="1.0" encoding="utf-8"?>
    		<vector  xmlns:android="http://schemas.android.com/apk/res/android"
    			android:viewportWidth="1024"
    			android:viewportHeight="1024"
    			android:width="1024px"
    			android:height="1024px">
    			<!--pathData 放置 svg path 数据-->
    			<path android:fillColor="#963"  android:pathData="M511.417227 536.082488l81.180927 0 0 60.886719-81.180927 0 0-60.886719Z" />
    		</vector>
    		
    		
    # 动画 anim
    	
    	补间动画 anim 文件夹
    		效果支持:
    			Alpha:淡入淡出效果
    			Scale:缩放效果
    			Rotate:旋转效果
    			Translate:移动效果
    			
    		XML 文件通过  AnimationUtils.loadAnimation(Context, R.anim.**) 获取 XML示例
    			<?xml version="1.0" encoding="utf-8"?>
    			<set xmlns:android="http://schemas.android.com/apk/res/android">
    			<scale
    				android:fromXScale="0" android:toXScale="5"
    				android:fromYScale="0" android:toYScale="5"
    				android:pivotX="50%" android:pivotY="50%"
    				android:duration="1000" />
    			</set>	
    			使用
    			Animation animation = (Animation) AnimationUtils.loadAnimation(Context, R.anim.**);
    			
    		代码里new对象 例如: AlphaAnimation alphaAnimation = new AlphaAnimation(1, 0);
    		
    		动画次数和方式
    			animation.setRepeatCount(Animation.INFINITE);
    			animation.setRepeatMode(Animation.RESTART);
    			
    		动画事件 setAnimationListener 示例
    			animation.setAnimationListener(new Animation.AnimationListener() {
    				@Override
    				public void onAnimationStart(Animation animation) {
    					//动画开始
    				}
    				@Override
    				public void onAnimationEnd(Animation animation) {
    					//动画结束
    				}
    				@Override
    				public void onAnimationRepeat(Animation animation) {
    					//重复动画事件
    				}
    			});
    			
    		动画效果 AccelerateInterpolator ()
    			animation.setInterpolator(new AccelerateInterpolator());
    			
    		布局动画
    			建立布局动画
    				<layoutAnimation
    					xmlns:android="http://schemas.android.com/apk/res/android"
    					android:delay="0.5"
    					android:animationOrder="normal"
    					android:animation="@anim/list_anim"/>
    					<!-- android:animationOrder 执行循序 normal 顺序 random 随机 reverse 反向 -->
    					
    			XML使用布局动画
    				<LinearLayoutxmlns:android="http://schemas.android.com/apk/res/android"
    					android:orientation="vertical"
    					android:layout_width="fill_parent"
    					android:layout_height="fill_parent"
    					android:layoutAnimation="@anim/list_anim_layout"
    				> 
    				
    			代码建立及使用
    				Animation animation = (Animation) AnimationUtils.loadAnimation(
                      {Context}, R.anim.list_anim);
    				LayoutAnimationController controller = new LayoutAnimationController(animation);
    				controller.setOrder(LayoutAnimationController.ORDER_NORMAL); 
    				controller.setDelay(0.5f);
    				listView.setLayoutAnimation(controller);
    				
    		Activity 间切换 跳转之后调用 如 startActivity 之后
    			overridePendingTransition(android.R.anim.slide_in_left,android.R.anim.slide_out_right);
    			
    		动画集
    			代码: 通过 AnimationSet 包含多个动画,使用 addAnimation 添加
    				 AnimationSet animationset = new AnimationSet(true);
    				 animationset.addAnimation(animation);
    			XML:
    				<set xmlns:android="http://schemas.android.com/apk/res/android">
    					<scale
    						android:fromXScale="0" android:toXScale="5"
    						android:fromYScale="0" android:toYScale="5"
    						android:pivotX="50%" android:pivotY="50%"
    						android:duration="1000" />
    				</set>
    			使用:
    			AnimationSet animationset = (AnimationSet) AnimationUtils.loadAnimation({Context}, R.anim.**);
    			
    		使用动画: 调用view.startAnimation() 或 setAnimation()后在修改view内容
    		
    	帧动画 anim 文件夹
    		建立帧
    			<?xml version="1.0" encoding="utf-8"?>
    			<animation-list xmlns:android="http://schemas.android.com/apk/res/android"
    				android:oneshot="false">
    				<item android:drawable="@drawable/a_01" android:duration="50"/>
    				<item android:drawable="@drawable/a_02" android:duration="50"/>
    				<item android:drawable="@drawable/a_03" android:duration="50"/>
    				<item android:drawable="@drawable/a_04" android:duration="50"/>
    				<item android:drawable="@drawable/a_05" android:duration="50"/>
    				<item android:drawable="@drawable/a_06" android:duration="50"/>
    			</animation-list>
    		
    		普遍view通过 setBackgroundResource
    			ImageView imageView= (ImageView)findViewById(R.id.image);
    			imageView.setBackgroundResource(R.anim.anim);
    			AnimationDrawable animationDrawable = (AnimationDrawable)
    			 imageView.getBackground();
    			animationDrawable.start();
    			ImageView 还有 setImageResource
    			image.setImageResource(R.anim.li);
    			((AnimationDrawable)image.getDrawable()).start();
    		
    	差值动画 animator 文件夹
    		代码建立
    			TextView text = (TextView) findViewById(R.id.textView1);
    			//根据属性的类型不同来调用 ofFloat ofInt ofArgb 等函数
    			ObjectAnimator oa= ObjectAnimator.ofFloat(text,"TextSize",60,5);
    			oa.setDuration(1000);
    			oa.start();
    			
    		XML文件建立
    			<?xml version="1.0" encoding="utf-8"?>
    			<objectAnimator xmlns:android="http://schemas.android.com/apk/res/android"
    				android:duration="100"
    				android:propertyName="TextSize"
    				android:valueTo="60"
    				android:valueFrom="20"
    				android:valueType="floatType">
    			</objectAnimator>
    			调用
    			ObjectAnimator obj = (ObjectAnimator) AnimatorInflater.loadAnimator({Context}, R.animator.ts);
    			TextView text = (TextView) findViewById(R.id.textView1);
    			obj.setTarget(text);
    			obj.start();
    			
    		动画集
    			代码: 通过 AnimationSet 包含多个动画,使用 addAnimation 添加
    				 AnimationSet animationset = new AnimationSet(true);
    				 animationset.addAnimation(animation);
    
    			XML:
    				<?xml version="1.0" encoding="utf-8"?>
    				<set xmlns:android="http://schemas.android.com/apk/res/android">
    					<objectAnimator xmlns:android="http://schemas.android.com/apk/res/android"
    					android:duration="100"
    					android:propertyName="TextSize"
    					android:valueTo="60"
    					android:valueFrom="20"
    					android:valueType="floatType">
    					</objectAnimator>
    					<objectAnimator xmlns:android="http://schemas.android.com/apk/res/android"
    						android:duration="100"
    						android:propertyName="Height"
    						android:valueTo="60"
    						android:valueType="intType">
    					</objectAnimator>
    				</set>
    				使用:
    				AnimatorSet obj = (AnimatorSet) AnimatorInflater.loadAnimator({Context}, R.animator.**);
                    TextView text = (TextView) findViewById(R.id.textView1);
                    obj.setTarget(text);
                    obj.start();
    
    # 挂件 Widget
    	1. 在 AndroidManifest 注册
    		.activity.TouchActivity$myreceiver 继承自 AppWidgetProvider的类
    		@xml/aa Widget 的配置文件
    		<receiver android:name=".activity.TouchActivity$myreceiver" android:label="@string/app_name">
    	    <intent-filter>
    		     <action android:name="android.appwidget.action.APPWIDGET_UPDATE" />
    		  </intent-filter>
    			<meta-data
    				android:name="android.appwidget.provider"
    				android:resource="@xml/aa" />
    	  </receiver>
    	
    	2. 配置文件
    		@layout/aa 指定布局文件
    		<?xml version="1.0" encoding="utf-8"?>
    		<appwidget-provider xmlns:android="http://schemas.android.com/apk/res/android"
    			android:minWidth="146dip" android:minHeight="72dip" android:initialLayout="@layout/aa">
    		</appwidget-provider>
    		
    	3. 实现 AppWidgetProvider的类
    		public static class myreceiver extends AppWidgetProvider {
    			@Override
    			public void onUpdate(Context context, AppWidgetManager appWidgetManager, int[] appWidgetIds) {
    				//定期更新对象,如实现动画等
    				Timer timer = new Timer();
    				timer.scheduleAtFixedRate(new MyTime(context, appWidgetManager), 1, 1000);
    				super.onUpdate(context, appWidgetManager, appWidgetIds);
    			}
    			public class MyTime extends TimerTask {
    				RemoteViews remoteViews;
    			   AppWidgetManager appWidgetManager;
    				ComponentName thisWidget;
    				DateFormat format = SimpleDateFormat.getTimeInstance(SimpleDateFormat.MEDIUM, Locale.getDefault());
    				public MyTime(Context context, AppWidgetManager appWidgetManager) {
    					this.appWidgetManager = appWidgetManager;
    					//建立视图
    					remoteViews = new RemoteViews(context.getPackageName(), R.layout.aa);
    					//往指定包里查找视图
    					thisWidget = new ComponentName(context, myreceiver.class);
    				}
    				@Override
    				public void run() {
    					//修改视图
    					remoteViews.setTextViewText(R.id.text_content, "Time = " + format.format(new Date()));
    					//重新设置视图
    					appWidgetManager.updateAppWidget(thisWidget, remoteViews);
    				}
    			}
    		}
    
    # 网页 WebView
    	于JS交互绑定在JS的window对象中
    		final WebView vw = new WebView(this);
    		vw.setWebChromeClient(new WebChromeClient() {
    			@Override
    			public boolean onJsAlert(WebView view, String url, String message, JsResult result) {
    				//需重写各种JS事件才能实现各种JS的方法
    				AlertDialog.Builder alert = new AlertDialog.Builder(TouchActivity.this);
    				alert.setTitle("Alert");
    				alert.setMessage(message);
    				alert.show();
    				return super.onJsAlert(view, url, message, result);
    			}
    		});
    		vw.setWebViewClient(new WebViewClient() {
    			@Override
    			public void onPageFinished(WebView view, String url) {
    				//调用JS方法
    				vw.loadUrl("javascript:hiandroid()");
    			}
    		});
    		vw.addJavascriptInterface(new Object() {
    			@JavascriptInterface
    			public String alert(String string) {
    				//JS调用方法
    				AlertDialog.Builder alert = new AlertDialog.Builder(TouchActivity.this);
    				alert.setMessage(string);
    				alert.show();
    				return "HI";
    			}
    		}, "dome");
    		vw.getSettings().setJavaScriptEnabled(true);
    		vw.loadUrl("http://www.urltest.tk/a.html");
    		setContentView(vw);
    	
    # 定时器 Alarm
    	设置时间已超过,将立即触发
    		AlarmManager al= (AlarmManager)getSystemService(ALARM_SERVICE);
    		Intent it= new Intent(MyActivity.MY_ACTION);
    		PendingIntent pi=PendingIntent.getActivity(this,0,it,0);
    		//AlarmManager.RTC; //指定时间,System.currentTimeMillis()+N毫秒 激活时不唤醒
    		//AlarmManager.RTC_WAKEUP //指定时间,System.currentTimeMillis()+N毫秒 激活时唤醒
    		//AlarmManager.ELAPSED_REALTIME;//开机时间+N毫秒 激活时不唤醒
    		//AlarmManager.ELAPSED_REALTIME_WAKEUP; //开机时间+N毫秒 激活时唤醒
    		al.set(AlarmManager.RTC_WAKEUP, System.currentTimeMillis() + 10000, pi);
    		//重复触发
    		//al.setRepeating(AlarmManager.RTC_WAKEUP,System.currentTimeMillis()+10000,10000,pi);
    		//按系统预定义重复触发 AlarmManager.INTERVAL_*
    		//al.setInexactRepeating(AlarmManager.RTC_WAKEUP,System.currentTimeMillis()+10000,AlarmManager.INTERVAL_DAY,pi);
    
    	
    # 广播 Broadcast Receiver
    	//常量
    	public final static String MYINTERFER = "myfilterkey";
    	1. 注册
    		a. 代码注册
    			IntentFilter intentfilter = new IntentFilter(MYINTERFER);
    			BroadcastReceiver myreceiver = new BroadcastReceiver() {
    				@Override
    				public void onReceive(Context context, Intent intent) {
    					//不要做长时间处理操作
    					Toast.makeText(context,"msg",Toast.LENGTH_LONG).show();
    				}
    			};
    			registerReceiver(myreceiver,intentfilter);
    		b. AndroidManifest注册 (如果是内部类,加 static !!!应用未启动可用!!!)
    			public class myreceiver extends BroadcastReceiver {
    				@Override
    				public void onReceive(Context context, Intent intent) {
    					//不要做长时间处理操作
    					Toast.makeText(context,"msg",Toast.LENGTH_LONG).show();
    				}
    			}
    			AndroidManifest:
    			<receiver android:name=".activity.TouchActivity$myreceiver">
    				<intent-filter>
    					<action android:name="myfilterkey" />
    				</intent-filter>
    			</receiver>
    			
    	2. 发送
    		 Intent intent = new Intent(TouchActivity.MYINTERFER);
             sendBroadcast(intent);
    		 
    	3. 本地广播
    		LocalBroadcastManager localbcm = LocalBroadcastManager.getInstance(this);
            localbcm.registerReceiver(new BroadcastReceiver() {
                @Override
                public void onReceive(Context context, Intent intent) {
                    //处理本地广播
                }
            },new IntentFilter(TouchActivity.MYINTERFER));
            localbcm.sendBroadcast(new Intent(TouchActivity.MYINTERFER));
    		
    	4. 有序广播 sendOrderedBroadcast(new Intent(TouchActivity.MYINTERFER),"权限字符串");
    	
    	5. 可覆盖广播,会覆盖成最后一个值 sendStickyBroadcast(new Intent(TouchActivity.MYINTERFER));
    	
    	6. 示例 (处理下载)
    		String url = "http://dlsw.baidu.com/sw-search-sp/soft/6c/23675/Photoshop_CS6.3510481888.7z";
    		Uri uri = Uri.parse(url);
    		DownloadManager download = (DownloadManager) getSystemService(DOWNLOAD_SERVICE);
    		DownloadManager.Request request = new DownloadManager.Request(uri);
    		request.setAllowedNetworkTypes(DownloadManager.Request.NETWORK_WIFI);//只在WIFI下下载
    		final long enqueue = download.enqueue(request);
    		//还有其他事件等等
    		IntentFilter interf = new IntentFilter(DownloadManager.ACTION_DOWNLOAD_COMPLETE);
    		BroadcastReceiver br = new BroadcastReceiver() {
    			@Override
    			public void onReceive(Context context, Intent intent) {
    				long downid = intent.getLongExtra(DownloadManager.EXTRA_DOWNLOAD_ID, -1);
    				if (downid == enqueue) {
    					//your download
    				}
    			}
    		};
    		registerReceiver(br, interf);
    	
    # 服务 Service (长时间执行代码)
    	1. 服务可加权限,供其他程序调用
    	2. 服务可以在 Activity,Broadcast Receiver 等启动
    	3. 服务的Activity交互通过 bindService 的 ServiceConnection (IBinder service) 进行
    	5. 在服务中可通过回调来处理视图
    	6. 服务处理过程: 创建和绑定
    	7. 回调用 Handler 处理或自定义回调函数,如下示例:
    		a. 服务添加
    			//创建
    			public static class myservice extends Service{
    				private IBinder binder=new myservice.LocalBinder();
    				@Override
    				public IBinder onBind(Intent intent) {
    					return binder;
    				}
    				@Override
    				public void onCreate() {
    					super.onCreate();
    					Timer timer = new Timer();
    					timer.schedule(new TimerTask() {
    						@Override
    						public void run() {
    							if(h!=null){
    								Message msg= new Message();
    								Bundle b=new Bundle();
    								b.putString("hehe", "Date:" + new Date().toString());
    								msg.setData(b);
    								h.sendMessage(msg);
    							}
    						}
    					}, 0, 1000);
    				}
    				@Override
    				public int onStartCommand(Intent intent, int flags, int startId) {
    					//开始执行 根据返回值不同,可能会有多次调用
    					return START_STICKY;
    				}
    				@Override
    				public void onDestroy() {
    					//开始结束
    					super.onDestroy();
    				}
    				public class LocalBinder extends Binder {
    					public LocalBinder() {
    						super();
    					}
    					public myservice get_service(){
    						return myservice.this;
    					}
    				}
    				Handler h;
    				public void sethandle(Handler h){
    					this.h=h;
    				}
    			}
    			//启动
    			Intent intent = new Intent(this,myservice.class);
    			startService(intent);
    			
    	b. 服务绑定 在 Activity 中
    		bindService(intent, new ServiceConnection() {
                @Override
                public void onServiceConnected(ComponentName name, IBinder service) {
                    myservice localser=((myservice.LocalBinder)service).get_service();
                    localser.sethandle(h);
                }
                @Override
                public void onServiceDisconnected(ComponentName name) {
    
                }
            },BIND_AUTO_CREATE);
    		
    	8. Service 多次启动请求处理之类 IntentService 处理多个请求服务,任务完成会终结自己
    		重写 onHandleIntent 方法即可 Intent 为请求的Intent,主要用于多个类同的服务请求
    	
    	
    # 资源接口 Content Provider
    	1. Uri 使用 
            Uri muri = Uri.parse("content://www.urltest.tk/people/111");
            UriMatcher match = new UriMatcher(UriMatcher.NO_MATCH);
            match.addURI("www.urltest.tk", "people/#", 1);
            switch (match.match(muri)) {
                case 1:
                    //匹配进这里
                    break;
                default:
                    break;
            }
            //Uri 解析ID 和添加ID
            long id=ContentUris.parseId(muri);
            ContentUris.withAppendedId(muri,111);
    		//Uri 处理路径
    		Uri.withAppendedPath("content://www.urltest.tk","people"); => Uri.parse("content://www.urltest.tk/people")
    		
    	2. Uri 注册 provider provider实现见:3
    		<provider android:name=".activity.TouchActivity$myconentp"
                android:authorities="www.urltest.tk"
                android:multiprocess="false"
                >
            </provider>
    		
    	3. 实现示例
    		public static class myconentp extends ContentProvider{
    			private static String TAG="provider";
    			public static final String AUTHORITY = "www.urltest.tk";
    			public static final int PEOPLES = 1;
    			public static final int PEOPLE = 2;
    			public static final UriMatcher match;
    			static {
    				match = new UriMatcher(UriMatcher.NO_MATCH);
    				match.addURI(AUTHORITY, "people", PEOPLES);
    				match.addURI(AUTHORITY, "people/#", PEOPLE);
    			}
    			public static final String CONTENT_TYPE = "vnd.android.cursor.dir/www.urltest.tk";
    			public static final String CONTENT_TYPE_ITME = "vnd.android.cursor.item/www.urltest.tk";
    			@Override
    			public boolean onCreate() {
    				Log.i(TAG,"create");
    				return true;
    			}
    			@Nullable
    			@Override
    			public String getType(Uri uri) {
    				switch (match.match(uri)) {
    					case PEOPLES:
    						return CONTENT_TYPE;
    					case PEOPLE:
    						return CONTENT_TYPE_ITME;
    					default:
    						throw new IllegalArgumentException("Unknown URI " + uri);
    				}
    			}
    			@Nullable
    			@Override
    			public Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs, String sortOrder) {
    				//projection 字段列表
    				//selection WHERE 条件
    				//selectionArgs WHERE 绑定数据
    				//sortOrder 排序
    				Log.i(TAG, "query");
    				switch (match.match(uri)) {
    					case PEOPLE://单个查询
    						long id=ContentUris.parseId(uri);//解析到ID
    						break;
    					case PEOPLES://批量查询
    						break;
    					default:
    						throw new IllegalArgumentException("Unknown URI " + uri);
    				}
    				return null;
    			}
    			@Nullable
    			@Override
    			public Uri insert(Uri uri, ContentValues values) {
    				//values 新值
    				switch (match.match(uri)) {
    					case PEOPLES:
    						//进行添加操作
    						String title=values.getAsString("title");
    						Log.i(TAG, "insert:" + title);
    						long insert_id=100;
    						return ContentUris.withAppendedId(uri,insert_id);
    					default:
    						throw new IllegalArgumentException("Unknown URI " + uri);
    				}
    			}
    			@Override
    			public int delete(Uri uri, String selection, String[] selectionArgs) {
    				//selection WHERE 条件
    				//selectionArgs WHERE 绑定数据
    				switch (match.match(uri)) {
    					case PEOPLES:
    						Log.i(TAG, "delete");
    						//执行删除操作
    						break;
    					default:
    						throw new IllegalArgumentException("Unknown URI " + uri);
    				}
    				return 1;
    			}
    			@Override
    			public int update(Uri uri, ContentValues values, String selection, String[] selectionArgs) {
    				//values 新值
    				//selection WHERE 条件
    				//selectionArgs WHERE 绑定数据
    				switch (match.match(uri)) {
    					case PEOPLES:
    						Log.i(TAG, "update");
    						//进行更新操作
    						break;
    					default:
    						throw new IllegalArgumentException("Unknown URI " + uri);
    				}
    				return 0;
    			}
    		}
    		
    	4. 使用
    		Uri uri = Uri.parse("content://www.urltest.tk/people");
            ContentResolver cr = getContentResolver();
            //增
            ContentValues cv = new ContentValues();
            cv.put("title", "title");
            Uri insert_uri=cr.insert(uri, cv);
            long insert_id=ContentUris.parseId(insert_uri);
            Log.i(TAG, "INSERTID:" + insert_id);
            //删
            cr.delete(uri, "id=?", new String[]{"1"});
            //改
            cv.put("title", "newtitle");
            cr.update(uri, cv, "id=" + insert_id, new String[]{String.valueOf(insert_id)});
            //查
            Cursor all_rs = cr.query(uri,null,null,null,null);
            if(all_rs!=null) {
                while (all_rs.moveToNext()) {
                    String title = all_rs.getString(all_rs.getColumnIndex("title"));
                }
            }
            Uri uriitem = Uri.parse("content://www.urltest.tk/people/111");
            Cursor item_rs = cr.query(uriitem, null, null, null, null);
            if(item_rs!=null){
                String title=all_rs.getString(item_rs.getColumnIndex("title"));
            }
    		
    	5. 本地资源存储
    		a. 数据库 SQLite 
    			class myDBHelp extends SQLiteOpenHelper{
    				public myDBHelp(Context context, String name, SQLiteDatabase.CursorFactory factory,
    									int version) {
    					super(context, name, factory, version);
    				}
    				public myDBHelp(Context context, String name, int version) {
    					this(context, name, null, version);
    				}
    				@Override
    				public void onCreate(SQLiteDatabase db) {
    					//初始化数据库
    					db.execSQL("create table mytable("
    							+" id INTEGER PRIMARY KEY autoincrement,"
    							+ " title varchar(20)"
    							+");");
    				}
    				@Override
    				public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
    					//升级数据库
    				}
    			}
    			使用
    			myDBHelp dbhelp= new myDBHelp(this,"db_name",5);
    			SQLiteDatabase db = dbhelp.getWritableDatabase();
    			//增
    			ContentValues insval = new ContentValues();
    			insval.put("title", "title");
    			long id = db.insert("mytable", null, insval);
    			//改
    			insval.put("title", "newtitle");
    			db.update("mytable",insval , "id=?",new String[]{String.valueOf(id)} );
    			//查
    			Cursor db_rs = db.query("mytable", new String[]{"title"},null, null, null, null, null);
    			if(db_rs!=null) {
    				while (db_rs.moveToNext()) {
    					String title = db_rs.getString(db_rs.getColumnIndex("title"));
    					Log.i(TAG,title);
    				}
    			}
    			//删
    			db.delete("mytable", "id=?", new String[]{String.valueOf(id)});
    			
    		b. 键值对 SharedPreferences 示例
    			SharedPreferences mySharedPreferences= getSharedPreferences("test", Activity.MODE_PRIVATE);
    			SharedPreferences.Editor editor = mySharedPreferences.edit();
    			editor.putString("name", "Karl");
    			editor.commit();
    			String name=mySharedPreferences.getString("name","unkown");
    			Log.i("myout",name);	
    			
    		c. 文件 
    			try {
    				String msg="hi";
    				String file="message.txt";
    				FileOutputStream fos = openFileOutput(file,
    						MODE_APPEND);
    				fos.write(msg.getBytes());
    				fos.close();
    
    				FileInputStream inStream = this.openFileInput(file);
    				byte[] buffer = new byte[1024];
    				int hasRead = 0;
    				StringBuilder sb = new StringBuilder();
    				while ((hasRead = inStream.read(buffer)) != -1) {
    					sb.append(new String(buffer, 0, hasRead));
    				}
    				inStream.close();
    				Log.i("myout",sb.toString());
    			} catch (Exception e) {
    				e.printStackTrace();
    			}
    			
    		d. SD卡文件
    			缓存文件夹 getCacheDir(); getExternalCacheDir()
    			if (Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED)) {
    				String filename="filename.txt";
    				String msg="this is txt";
    				File file = new File(Environment.getExternalStorageDirectory()
    						.toString()
    						+ File.separator
    						+ filename);
    				if (!file.getParentFile().exists()) { // 父文件夹不存在
    					file.getParentFile().mkdirs(); // 创建文件夹
    				}
    				PrintStream out = null; // 打印流对象用于输出
    				try {
    					out = new PrintStream(new FileOutputStream(file, true)); // 追加文件
    					out.println(msg);
    				} catch (Exception e) {
    					e.printStackTrace();
    				} finally {
    					if (out != null) {
    						out.close(); // 关闭打印流
    					}
    				}
    				Scanner scan = null; // 扫描输入
    				StringBuilder sb = new StringBuilder();
    				try {
    					scan = new Scanner(new FileInputStream(file)); // 实例化Scanner
    					while (scan.hasNext()) { // 循环读取
    						sb.append(scan.next()); // 设置文本
    					}
    					Log.i("myout",sb.toString());
    				} catch (Exception e) {
    					e.printStackTrace();
    				} finally {
    					if (scan != null) {
    						scan.close(); // 关闭打印流
    					}
    				}
    			} else {
    				// SDCard不存在,使用Toast提示用户
    			}
    
    			
    
    # 提醒 Notification
    	//常量
    	public final static int TAG = 1;
    	1. API 11 后示例
    		PendingIntent pendingIntent2 = PendingIntent.getActivity(this, 0,
    				new Intent(this, TouchActivity.class), 0);
    		Notification notify2 = new Notification.Builder(this)
    				.setSmallIcon(R.drawable.abc_btn_check_to_on_mtrl_015) 
    				.setTicker("TickerText:" + "您有新短消息,请注意查收!")
    				.setContentTitle("Notification Title")
    				.setContentText("This is the notification message")
    				.setContentIntent(pendingIntent2)
    				.setNumber(1)
    				.getNotification(); // 需要注意build()是在API level
    		// 16及之后增加的,在API11中可以使用getNotificatin()来代替
    		notify2.flags |= Notification.FLAG_AUTO_CANCEL;
    		manager.notify(TAG, notify2);
    		
    	2. API 16 后示例
    		PendingIntent pendingIntent3 = PendingIntent.getActivity(this, 0,
    				new Intent(this, TouchActivity.class), 0);
    		Notification notify3 = new Notification.Builder(this)
    				.setSmallIcon(R.drawable.notification_template_icon_bg)
    				.setTicker("TickerText:" + "您有新短消息,请注意查收!")
    				.setContentTitle("Notification Title")
    				.setContentText("This is the notification message")
    				.setContentIntent(pendingIntent3).setNumber(1).build(); 
    		notify3.flags |= Notification.FLAG_AUTO_CANCEL; // FLAG_AUTO_CANCEL表明当通知被用户点击时,通知将被清除。
    		manager.notify(TAG, notify3);
    		
    	3. 自定义提醒视图 (Deprecated)
    		Notification myNotify = new Notification();
    		myNotify.icon = R.drawable.notification_template_icon_bg;
    		myNotify.tickerText = "TickerText:您有新短消息,请注意查收!";
    		myNotify.when = System.currentTimeMillis();
    		myNotify.flags = Notification.FLAG_NO_CLEAR;// 不能够自动清除
    		RemoteViews rv = new RemoteViews(getPackageName(),
    				R.layout.aa);
    		rv.setTextViewText(R.id.text_content, "hello wrold!");
    		myNotify.contentView = rv;
    		Intent intent = new Intent(Intent.ACTION_MAIN);
    		PendingIntent contentIntent = PendingIntent.getActivity(this, 1,
    				intent, 1);
    		myNotify.contentIntent = contentIntent;
    		manager.notify(TAG, myNotify);
    		
    	4. 关闭提醒
    		manager.cancel(TAG);
    

      

  • 相关阅读:
    Qt之QLineEdit
    Redis与Java
    Qt之属性系统
    Qt之Meta-Object系统
    设计模式(八)外观模式
    Qt之QRadioButton
    Qt之QSystemTrayIcon
    Redis与Java
    JSP公用COMMON文件
    eclipse远程调试Tomcat方法[转]
  • 原文地址:https://www.cnblogs.com/liushannet/p/3113196.html
Copyright © 2020-2023  润新知