編輯:關於Android編程
[1]內容觀察者不是四大組件,就不需要在清單文件裡面配置
實現的步驟
1)注冊內容觀察者
1.getContentResolver().registerContentObserver(uri, true, new MyContentObserver(new Handler()));
2)定義內容觀察者
1.//定義內容觀察者 2. private class MyContentObserver extends ContentObserver{ 3. 4. public MyContentObserver(Handler handler) { 5. super(handler); 6. } 7. //當我們觀察的內容發生變化 這個方法就執行 8. @Override 9. public void onChange(boolean selfChange) { 10. System.out.println("哈哈 數據庫被人操作了"); 11. super.onChange(selfChange); 12. } 13. 14. }
3)內容觀察者想要接收到通知,需要被操作的數據庫自己主動發消息
1.getContext().getContentResolver().notifyChange(uri, null); //[2]注冊內容觀察者 參數二:如果是false 那麼第一個參 數的uri必須是一個精確的uri true:可以不用是一個精確的uri getContentResolver().registerContentObserver(uri, true, new MyContentObserver(new Handler()));
3. @Override 4. protected void onCreate(Bundle savedInstanceState) { 5. super.onCreate(savedInstanceState); 6. setContentView(R.layout.activity_main); 7. //[1]注冊內容觀察者 8. Uri uri = Uri.parse("content://sms/"); 9. getContentResolver().registerContentObserver(uri, true, new MyContentObserver(new Handler())); 10. 11. } 12. //定義內容觀察者 13. private class MyContentObserver extends ContentObserver{ 14. public MyContentObserver(Handler handler) { 15. super(handler); 16. } 17. //當我們觀察的內容發生變化 這個方法就執行 18. @Override 19. public void onChange(boolean selfChange) { 20. Uri uri = Uri.parse("content://sms/"); 21. Cursor cursor = getContentResolver().query(uri, new String[]{"address","body","date"}, null, null, null); 22. cursor.moveToFirst(); 23. String address = cursor.getString(cursor.getColumnIndex("address")); 24. String body = cursor.getString(1); 25. System.out.println("address:"+address+"~~~"+body); 26. } 27. 28. }
jpg :以良好質量保存 用於計算機
png:以高質量保存 用於計算機或者網絡
bmp :以高質量保存 用於計算機 無損(沒有警告壓縮的)
圖片大小 = 圖片的總像素 * 每個像素大小
單色 :每個像素最多可以表示2種顏色. 只能表示黑 和 白.用二進制表示的化,那麼只需要使用長度為1的二進制位來表示 ,那麼占1/8byte
16色 :每個像素最多可以表示16種顏色,0~15 ,0000 -1111 那麼只需要使用長度為4的二進制位來表示 ,那麼一個像素占1/2byte
256色.每個像素最多可以表示256種顏色 0~255 ,0000 0000 -1111 1111 那麼只需要使用長度為8,那麼一個像素占1byte
24位: 16777215色
R :8位 1bye G :8位 1byte B : 8位 1byte 那麼每個像素占3byte
Android中表示顏色更加豐富.采用ARGB 一個占4byte
10-16 02:11:10.443: I/dalvikvm-heap(22693): Forcing collection of SoftReferences for 30720012-byte allocation
圖片大小 2400 * 3200 寬高都除以100 240 和320 手機大小:320 * 480 計算縮放比:7 6 按照大的去縮放. 所以需要我們動態的獲取手機的分辨率和圖片的分辨率 在算出縮放比 獲取手機分辨率的2種方式 ★使用過時的api 1.//[2]獲取手機的分辨率 2. WindowManager wm = (WindowManager) getSystemService(WINDOW_SERVICE); 3. int width = wm.getDefaultDisplay().getWidth(); 4. int height = wm.getDefaultDisplay().getHeight(); ★使用新的api 1.Point point = new Point(); 2. wm.getDefaultDisplay().getSize(point); 3. int width = point.x; 4. int height = point.y; 5. System.out.println("手機的分辨率:"+width+"~~~~"+height); 什麼情況需要縮放加載大圖片:圖片的分辨率遠遠大於手機的分辨率. 實現代碼 public class MainActivity extends Activity { private ImageView iv; private int x; private int y; private int height; private int width; @SuppressWarnings("deprecation") @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); iv = (ImageView) findViewById(R.id.iv); // [1]獲取手機分辨率 WindowManager wm = (WindowManager) getSystemService(WINDOW_SERVICE); height = wm.getDefaultDisplay().getHeight(); width = wm.getDefaultDisplay().getWidth(); System.out.println(height + "---" + width); // [2]獲取手機分辨率 // Point point = new Point(); // wm.getDefaultDisplay().getSize(point); // x = point.x; // y = point.y; // System.out.println(x + "---" + y); } public void click(View v) { /* * Bitmap bitmap = BitmapFactory.decodeFile("/mnt/sdcard/dog.jpg"); * iv.setImageBitmap(bitmap); */ // [1]創建位圖工廠配置參數 BitmapFactory.Options opts = new Options(); // [1.1]不去真正的解析位圖 返回一個null(no bitmap) 但是還可以獲取圖片的寬高信息 opts.inJustDecodeBounds = true; BitmapFactory.decodeFile("/mnt/sdcard/dog.jpg", opts); // [1.2]獲取圖片寬和高 int outWidth = opts.outWidth; int outHeight = opts.outHeight; System.out.println("圖片寬"+outWidth); // [1.3]算出縮放比 圖片的高/手機高 圖片的寬/手機的寬 按照大的去縮放 int scale = 1; int scalex = outWidth / width; int scaley = outHeight / height; System.out.println(scalex); if (scalex >= scaley && scalex > scale) { scale = scalex; } else if (scaley >= scalex && scaley > scale) { scale = scaley; } System.out.println("縮放比:"+scale); // [1.4]按照縮放比加載圖片 opts.inSampleSize = scale; // [1.5]按照這個縮放比解析位圖,false時去解析位圖 opts.inJustDecodeBounds = false; // [0]展示圖片 Bitmap bitmap = BitmapFactory.decodeFile("/mnt/sdcard/dog.jpg", opts); iv.setImageBitmap(bitmap); } }
想修改原圖: 注意 原圖不可以修改 所以我才創建原圖的副本 public class MainActivity extends Activity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); ImageView copy = (ImageView) findViewById(R.id.iv_copy); ImageView iv = (ImageView) findViewById(R.id.iv); //[1]把res下圖片展示到iv上 Bitmap srcbitmap = BitmapFactory.decodeResource(getResources(), R.drawable.qq); iv.setImageBitmap(srcbitmap); //[2]創建原圖的副本 相當於我們創建了一個模板 相當於你有了一張白紙 Bitmap copyBitmap = Bitmap.createBitmap(srcbitmap.getWidth(), srcbitmap.getHeight(), srcbitmap.getConfig()); //[3.1]想作畫需要一個畫筆類 Paint paint = new Paint(); //[3.2]想作畫還需要一個畫布 相當於把白紙鋪到了畫布上 Canvas canvas = new Canvas(copyBitmap); //[3.3]就可以開始作畫了 參考原圖去作畫 把原圖的內容畫到了白紙上 canvas.drawBitmap(srcbitmap, new Matrix(), paint); copy.setImageBitmap(copyBitmap); } }
//[4.1]縮放 //matrix.setScale(1.5f, 1f); //[4.2]位移 //matrix.setTranslate(4f, 1f); //[4.3]旋轉,中心坐標 //matrix.setRotate(25, srcbitmap.getWidth()/2, srcbitmap.getHeight()/2); //[4.4]鏡面,使用縮放和位移的一個組合就可以使用鏡面, //postTranslate是在上一次的基礎上進行在次修改 set是每次的操作都是最新的 會覆蓋上一次的操作 //matrix.setScale(-1.0f, 1.0f); //matrix.postTranslate(srcbitmap.getWidth(), 0); //[4.5]倒影 matrix.setScale(1.0f, -1f); matrix.postTranslate(0, srcbitmap.getHeight()); //[3.3]就可以開始作畫了 參考原圖去作畫 把原圖的內容畫到了白紙上 canvas.drawBitmap(srcbitmap, matrix, paint); copy.setImageBitmap(copyBitmap);
想實現隨手塗鴉 實際上就是在屏幕上不停的畫線就可以了 1. 2. 3. private Bitmap copyBimap; 4. private Bitmap srcBitmap; 5. private ImageView iv; 6. private Paint paint; 7. private Canvas canvas; 8. 9. @Override 10. protected void onCreate(Bundle savedInstanceState) { 11. super.onCreate(savedInstanceState); 12. setContentView(R.layout.activity_main); 13. // [1]找到iv 用來展示我們畫的內容 14. iv = (ImageView) findViewById(R.id.iv); 15. 16. // [2]先獲取bg.png的原圖 17. srcBitmap = BitmapFactory.decodeResource(getResources(), R.drawable.bg); 18. 19. copyBimap = Bitmap.createBitmap(srcBitmap.getWidth(), 20. srcBitmap.getHeight(), srcBitmap.getConfig()); 21. // [3.1]創建畫筆類 22. paint = new Paint(); 23. // [3.2]創建一個畫布類 相當於把白紙鋪到了畫布上 24. canvas = new Canvas(copyBimap); 25. // [3.3]開始作畫 當32行代碼執行完畢後 白紙上就有內容了 26. canvas.drawBitmap(srcBitmap, new Matrix(), paint); 27. // [3.4]畫一條線 線由2個點確定一條線 28. // canvas.drawLine(20, 30, 40, 70, paint); 29. // [4]把質的內容展示到iv上 30. iv.setImageBitmap(copyBimap); 31. // [5]給iv設置觸摸事件 32. iv.setOnTouchListener(new OnTouchListener() { 33. float startX = 0; 34. float startY = 0; 35. 36. @Override 37. public boolean onTouch(View v, MotionEvent event) { 38. // [6]具體判斷一下觸摸事件的類型 39. int action = event.getAction(); 40. switch (action) { 41. case MotionEvent.ACTION_DOWN: // 按下 42. // [7]獲取手指按下的坐標 43. startX = event.getX(); 44. startY = event.getY(); 45. System.out.println("按下:" + startX + "~~~~" + startY); 46. break; 47. case MotionEvent.ACTION_MOVE: // 移動 48. // [8]獲取移動後的坐標 49. float stopX = event.getX(); 50. float stopY = event.getY(); 51. // [9]不停的畫線 52. canvas.drawLine(startX, startY, stopX, stopY, paint); 53. System.out.println("移動:" + stopX + "~~~~" + stopY); 54. // [10]更新iv 55. iv.setImageBitmap(copyBimap); 56. // [11]更新一下開始的坐標 startX startY 57. startX = stopX; 58. startY = stopY; 59. 60. break; 61. 62. case MotionEvent.ACTION_UP: // 抬起 63. 64. break; 65. } 66. 67. // 如果返回值是true,才能看到畫上的線條 68. return true; 69. } 70. }); 71. 72. } 73. 74. // 點擊按鈕讓畫筆變紅色 75. public void click1(View v) { 76. paint.setColor(Color.RED); 77. } 78. 79. // 點擊按鈕讓畫筆加粗 80. public void click2(View v) { 81. paint.setStrokeWidth(19); 82. } 83. 84. //點擊按鈕保存 大作 85. public void click3(View v) { 86. try { 87. File file = new File(Environment.getExternalStorageDirectory().getPath(),"dazuo.png"); 88. FileOutputStream fos = new FileOutputStream(file); 89. //參1:保存圖片的格式 參數2:quality 質量 90. copyBimap.compress(CompressFormat.PNG, 100, fos); 91. fos.close(); 92. Toast.makeText(getApplicationContext(), "sucess", 1).show(); 93. } catch (Exception e) { 94. e.printStackTrace(); 95. } 96. } 觸摸事件分 按下 移動 和 抬起 ★:觸摸事件的返回值要返回true ★ 畫完線後 要記得更新iv.
public class MainActivity extends Activity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); final ImageView iv = (ImageView) findViewById(R.id.iv); Bitmap prebitmap = BitmapFactory.decodeResource(getResources(), R.drawable.pre19); // 創建模板 final Bitmap srcBitmap = Bitmap.createBitmap(prebitmap.getWidth(), prebitmap.getHeight(), prebitmap.getConfig()); // 畫筆 Paint paint = new Paint(); // 畫布 Canvas canvas = new Canvas(srcBitmap); canvas.drawBitmap(prebitmap, new Matrix(), paint); // 把圖展示到iv上 iv.setImageBitmap(srcBitmap); // 設置觸摸事件 iv.setOnTouchListener(new OnTouchListener() { @Override public boolean onTouch(View v, MotionEvent event) { int action = event.getAction(); switch (action) { case MotionEvent.ACTION_MOVE: for (int i = -15; i < 15; i++) { for (int j = -15; j < 15; j++) { //要try -catch try { srcBitmap.setPixel((int) event.getX() + i, (int) event.getY() + j, Color.TRANSPARENT); iv.setImageBitmap(srcBitmap); } catch (Exception e) { // TODO Auto-generated catch block e.printStackTrace(); } } } break; } return true; } }); } }
………….
public class MusicService extends Service { private MediaPlayer mediaPlayer; private Timer timer; private TimerTask task; @Override public IBinder onBind(Intent intent) { // TODO Auto-generated method stub return new Mybinder(); } @Override public void onCreate() { mediaPlayer = new MediaPlayer(); super.onCreate(); } // [1]調用播放音樂的方法 public void playMusic() { // [1.1]設置播放路徑 try { mediaPlayer.setDataSource("/mnt/sdcard/Baby.mp3"); mediaPlayer.prepare(); mediaPlayer.start(); } catch (Exception e) { e.printStackTrace(); } } // [1.2]調用暫停音樂的方法 public void pauseMusic() { mediaPlayer.pause(); } // [1.3] 繼續播放音樂的方法 public void rePlayMusic() { mediaPlayer.start(); } // [3]更新進度條的方法 public void updateseekbar() { // [3.1]獲取當前歌曲的總時長 final int duration = mediaPlayer.getDuration(); timer = new Timer(); task = new TimerTask() { @Override public void run() { int currentPosition = mediaPlayer.getCurrentPosition(); // [4]更新進度條 Message message = Message.obtain(); // [4.1]准備bundle Bundle bundle = new Bundle(); bundle.putInt("duration", duration); bundle.putInt("currentPosition", currentPosition); // [4.2]使用msg攜帶多條數據 message.setData(bundle); // [4.3]發消息 maniActivity的handlemessage方法就會執行 MainActivity.handler.sendMessage(message); // [4.4]給mediaplayer設置播放完成的監聽 mediaPlayer.setOnCompletionListener(new OnCompletionListener() { @Override public void onCompletion(MediaPlayer mp) { System.out.println("歌曲播放完成了"); timer.cancel(); task.cancel(); } }); } }; // [3.4]方法意思再隔1秒後,每一秒執行一次,更新進度條 timer.schedule(task, 1000, 1000); } // 設置歌曲播放位置的方法 public void playSeekToPosition(int position) { mediaPlayer.seekTo(position); } private class Mybinder extends Binder implements Iservice { // [2]調用播放音樂的方法 @Override public void callplayMusic() { playMusic(); } // [2.1]調用暫停音樂的方法 @Override public void callpauseMusic() { pauseMusic(); } // [2.2]調用繼續播放音樂的方法 @Override public void callreplayMusic() { rePlayMusic(); } @Override public void callplaySeekToPosition(int position) { playSeekToPosition(position); } } }
……………………..
MainActivity代碼
……………………….
public class MainActivity extends Activity { private MediaPlayer player; private Iservice iservice; private Myconn conn; private static SeekBar sb; // [5]這個方法處理消息的時候執行 public static Handler handler = new Handler() { @Override public void handleMessage(Message msg) { // [5.1]獲取發消息攜帶的數據 數據是怎麼發的 就怎麼取 數據發的是什麼類型就取什麼類型 Bundle bundle = msg.getData(); // [5.2]獲取歌曲的總時長和 當前進度 int duration = bundle.getInt("duration"); int currentPosition = bundle.getInt("currentPosition"); // [5.3]更新進度條 sb.setMax(duration); sb.setProgress(currentPosition); super.handleMessage(msg); } }; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); // [1]調用startservice 保證服務在後台長期運行 Intent intent = new Intent(this, MusicService.class); startService(intent); // [2]想點擊按鈕的時候 調用服務裡面的方法 獲取我們在服務內部定義的中間人對象 conn = new Myconn(); bindService(intent, conn, BIND_AUTO_CREATE); sb = (SeekBar) findViewById(R.id.sb_1); // [4]給seekbar設置監聽 sb.setOnSeekBarChangeListener(new OnSeekBarChangeListener() { // [4.1]當拖動進度條停止 執行 @Override public void onStopTrackingTouch(SeekBar seekBar) { // [4.11]在這個方法裡面實現拖動到哪就播放歌曲對應的位置 iservice.callplaySeekToPosition(sb.getProgress()); } // [4.2]剛開始托 @Override public void onStartTrackingTouch(SeekBar seekBar) { } @Override public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) { } }); } // 監視服務的狀態 private class Myconn implements ServiceConnection { // 當連接成功後執行 @Override public void onServiceConnected(ComponentName name, IBinder service) { iservice = (Iservice) service; } // 當失去連接執行 @Override public void onServiceDisconnected(ComponentName name) { } } // 當Activity銷毀的時候 解綁服務 @Override protected void onDestroy() { unbindService(conn); super.onDestroy(); } public void click1(View v) { iservice.callplayMusic(); } public void click2(View v) { iservice.callpauseMusic(); } public void click3(View v) { iservice.callreplayMusic(); } }
……………………………..
定義接口………………..
public interface Iservice { public void callplayMusic(); public void callpauseMusic(); public void callreplayMusic(); public void callplaySeekToPosition(int position); }
//[3]播放sd卡裡面的小蘋果音樂 mediaPlayer = new MediaPlayer(); //[4]設置播放視頻的路徑 mediaPlayer.setDataSource("http://192.168.101.88:8080/cc.mp4"); //[5]准備播放 mediaPlayer.prepare(); //同步 比如張三喊李四吃飯 mediaPlayer.prepareAsync(); //異步 張三喊李四吃飯 //[7]設置一個准備完成的一個監聽 mediaPlayer.setOnPreparedListener(new OnPreparedListener() { //當這個方法執行說明我們要播放的數據一定緩沖好了 @Override public void onPrepared(MediaPlayer mp) { //[4]播放音樂 mediaPlayer.start(); //[5]繼續上次的位置繼續播放 }
[1] 播放視頻要比播放音頻多一個畫面 [2] 這個畫面的展示使用surfaceView(表面的view) [3]surfaceView這個類是一個重量級控件, [4]播放視頻的代碼
……………………………………
new Thread() { public void run() { SystemClock.sleep(500); } }.start(); 休眠會能播放
……………………………………..
public class MainActivity extends Activity { private MediaPlayer mediaPlayer; private int currentPosition; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); SurfaceView sf = (SurfaceView) findViewById(R.id.sf); // [1.1]展示畫面 SurfaceHolder holder = sf.getHolder(); // [1.2]為了確保surfaceview完全實例化 不采用睡眠的方式, holder內部通過一個監聽來維護 holder.addCallback(new Callback() { @Override public void surfaceCreated(SurfaceHolder holder) { try { mediaPlayer = new MediaPlayer(); mediaPlayer .setDataSource("http://192.168.101.72:8080/cc.mp4"); // [2.1]從網絡獲取 mediaPlayer.prepareAsync(); // [2.2]把播放的畫面數據放到sfv上 SurfaceHolder 是用來維護視頻表面的數據 // 這個實例通過surfaceView來獲取 mediaPlayer.setDisplay(holder); // [2.3]設置一個准備完成的一個監聽 mediaPlayer.setOnPreparedListener(new OnPreparedListener() { // 當這個方法執行說明我們要播放的數據一定緩沖好了 @Override public void onPrepared(MediaPlayer mp) { // [2.4]播放音樂 mediaPlayer.start(); // [2.5]繼續上次的位置繼續播放 mediaPlayer.seekTo(currentPosition); } }); } catch (Exception e) { e.printStackTrace(); } } @Override public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) { } // 當surfaceView 表面看不見 就代表銷毀 @Override public void surfaceDestroyed(SurfaceHolder holder) { // [1.21]獲取當前視頻播放的位置 if (mediaPlayer != null && mediaPlayer.isPlaying()) { currentPosition = mediaPlayer.getCurrentPosition(); mediaPlayer.stop(); mediaPlayer.release(); } } }); } }
播放視頻的代碼 //[1]找到控件 播放視頻 VideoView vv = (VideoView) findViewById(R.id.vv); //[2]設置播放的數據原 vv.setVideoPath("http://192.168.101.88:8080/cc.mp4"); //[3]播放視頻 vv.start(); 底層實際上就是對mediaplayer和surfaceview的封裝. mediaplayer播放視頻只支持mp4 或者3gp格式.avi rmvb不支持
類庫 相當於jar 使用vitamio步驟 1 引入vitamio框架 加入library 2 在布局中定義VideoView3 mainactivity代碼 插件vitamio框架檢查是否可用 if (!LibsChecker.checkVitamioLibs(this)) { return; } final VideoView vv = (VideoView) findViewById(R.id.vv); vv.setVideoPath("http://192.168.1.2:8080/haha.avi"); vv.setOnPreparedListener(new OnPreparedListener() { @Override public void onPrepared(MediaPlayer mp) { vv.start(); } }); //設置video的控制器 vv.setMediaController(new MediaController(this)); 4 一定要在清單文件初始化InitActivity
……………………………………………..
解碼器 都使用的是另外一個開源項目:ffmpeg 播放視頻三種方式 [1]surfaceview [2]videoView [3]viamio 實際開發中用哪個.
首先弄懂怎麼設置adb wifi無線調試的功能,如下所示。1. 手機端開啟adb tcp連接端口:/$setprop service.adb.tcp.port 5555:
如何在圖片上畫畫呢?這裡寫了一個demo,供大家參考一、先看一眼工程結構工程結構:二、自定義view這個自定義view實現了保留軌跡的功能,代碼如下package pic
Android中通過子線程連接網絡獲取資料,同時顯示加載進度對話框給用戶的操作,需要Thread和Handler來完成,在Thread中執行比較耗時的代碼,完成後再通過H
Android實現九宮格圖案解鎖,自帶將圖案轉化成數字密碼的功能,代碼如下:LockPatternView.javapackage com.jackie.lockpatt