Android學習筆記(6)

myxs發表於2017-03-28

內容提供器和多媒體

標籤: Anroid


1.內容提供器簡介

Content Provider用於在不同的應用程式間實現資料共享。

1.1執行時許可權

  1. 判斷使用者是否已經授權。ContextCompat.checkSelfPermission方法的返回值是否為PackageManager.pERMISSSION_GRANTED
  2. 沒有得到授權,需要申請授權。requestPermissions方法,引數Activity例項,字串陣列存放許可權名,以及請求碼
  3. 使用者處理彈出的許可權申請對話方塊
  4. 回撥onRequestPermissionsResult方法,判斷授權結果

    if (ContextCompat.checkSelfPermission(this, Manifest.permission.READ_CONTACTS) != PackageManager.PERMISSION_GRANTED) {
        ActivityCompat.requestPermissions(this, new String[]{ Manifest.permission.READ_CONTACTS }, 1);
    } else {
        method();
    }
    
    
    public void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults) {
        switch (requestCode) {
            case 1:
                if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
                    method();
                } else {
                    Toast.makeText(this, "You denied the permission", Toast.LENGTH_SHORT).show();
                }
                break;
            default:
        }
    }
    

    1.2訪問其它程式的資料

當程式通過內容提供器給其資料提供外部訪問介面,其它程式都能訪問這些資料。通過Contextd的getContextResolver的幾個方法完成查詢、新增、刪除和更新資料的操作。不同於資料庫操作需要提供表名,這裡需要的是內容Uri,如content://com.example.app.provider/table1

Uri uri = Uri.parse("content://com.example.app.provider/table1");

查詢

query5個引數,分別是uri,列名,where約束條件,具體值,查詢結果排序方式

Uri uri = Uri.parse("content://com.example.databasetest.provider/book");
Cursor cursor = getContentResolver().query(uri, null, null, null, null);
if (cursor != null) {
        while (cursor.moveToNext()) {
            String name = cursor.getString(cursor. getColumnIndex("name"));
            String author = cursor.getString(cursor. getColumnIndex("author"));
            int pages = cursor.getInt(cursor.getColumnIndex ("pages"));
            double price = cursor.getDouble(cursor. getColumnIndex("price"));
        }
        cursor.close();
}

更新

update方法中後2個引數相當於SQL中的where子句的作用

     Uri uri = Uri.parse("content://com.example.databasetest.provider/book/" + newId);
     ContentValues values = new ContentValues();
    values.put("name", "A Storm of Swords");
    values.put("pages", 1216);
    values.put("price", 24.05);
    getContentResolver().update(uri, values, null, null);

刪除

Uri uri = Uri.parse("content://com.example.databasetest.provider/book/" + newId);
getContentResolver().delete(uri, null, null);

插入

Uri uri = Uri.parse("content://com.example.databasetest.provider/book");
ContentValues values = new ContentValues();
values.put("name", "A Clash of Kings");
values.put("author", "George Martin");
values.put("pages", 1040);
values.put("price", 55.55);
Uri newUri = getContentResolver().insert(uri, values);
newId = newUri.getPathSegments().get(1);

1.3建立內容提供器

步驟

  1. 繼承ContentProvider新建內容提供器類,重寫6個抽象方法

    • onCreate:只有ContentResolver訪問此程式資料時,初始化內容提供器時呼叫
    • query:從內容提供器重查詢資料
    • insert:向內容提供器中新增資料
    • update:更新內容提供器中的資料
    • delete:從內容提供器中刪除資料
    • getType:根據內容URI返回MIME型別
  2. UriMatcher中的addURI方法,傳遞authority、path和自定義程式碼

    在query,insert,update,delete,getType方法中,當呼叫UriMatcher的match方法,傳入Uri物件,返回值是某個自定義的程式碼,確定訪問資料

  3. 因為需要對資料庫操作,在每個方法內都要獲取到SQLiteDatabase物件,通過SQLiteOpenHelper物件獲取。呼叫資料庫物件的方法進行資料操作。

    private MyDatabaseHelper dbHelper;
    SQLiteDatabase db = dbHelper.getReadableDatabase();
    

    1.4總結

    即一個程式中有資料庫相關類,提供外部訪問的ContentProvider類,其它程式才能通過getContentResolver訪問到資料。

2.多媒體

2.1通知

2.1.1通知基本用法

  1. NotificationManager對通知進行管理,呼叫Context的getSystemService獲取

    NotificationManager manager = (NotificationManager) getSystemService(NOTIFICATION_SERVICE);
    
  2. 使用Builder構造器建立Notification物件,通過在最終得到build方法前連綴設定方法建立豐富的Notification物件

    Notification notification = nw NotificationCompat.Builder(context).build();
    

    通知豐富後

    setContentTitle("This is content title")
                    .setContentText("This is content text")
                    .setWhen(System.currentTimeMillis())
                    .setSmallIcon(R.mipmap.ic_launcher)
                    .setLargeIcon(BitmapFactory.decodeResource(getResources(), R.mipmap.ic_launcher))
                    .setContentIntent(pi)
            //        .setSound(Uri.fromFile(new File("/system/media/audio/ringtones/Luna.ogg")))
            //        .setVibrate(new long[]{0, 1000, 1000, 1000})
            //        .setLights(Color.GREEN, 1000, 1000)
                    .setDefaults(NotificationCompat.DEFAULT_ALL)
            //        .setStyle(new NotificationCompat.BigTextStyle().bigText("Learn how to build notifications, send and sync data, and use voice actions. Get the official Android IDE and developer tools to build apps for Android."))
                    .setStyle(new NotificationCompat.BigPictureStyle().bigPicture(BitmapFactory.decodeResource(getResources(), R.drawable.big_image)))
                    .setPriority(NotificationCompat.PRIORITY_MAX)
                    .build();
            manager.notify(1, notification);
    
  3. 呼叫NotificationManager物件的notify方法顯示通知

    manager.notify(1, notification);
    
  4. 優化通知,如點選後啟動一個活動

    Intent intent = new Intent(this, XXXActivity.class);
    PendingIntent pi = PendingIntent.getActivity(this, 0, inent, 0);
    Notification notification = new NotificationCompat.Builder(this)
                        ...
                        .setContentIntent(pi)
                        build();
    ...
    
  5. 關閉通知 有2種方式,自動取消和利用NotificationManager的cancel方法

    ...
    .setAutoCancel(true);
    .build();
    
    
    NotificationManager manager = (NotificationManager) getSystemService(NOTIFICATION_SERVICE);
    manager.cancel(1);
    

2.1.2通知的高階用法

如加振動和LED閃爍以及設定文字和圖片,優先順序,都需要連綴在通知的建立方法中

2.2呼叫攝像頭和相簿

2.2.1啟動相機程式
Intent intent = new Intent("android.media.action.IMAGE_CAPTURE");
            intent.putExtra(MediaStore.EXTRA_OUTPUT, imageUri);//圖片的書櫥地址
            startActivityForResult(intent, TAKE_PHOTO);//拍完照後回撥onActivityResult顯示圖片


public void onActivityResult(int resultCode, int resultCode, Intent data){
    switch(requestCode){
        case TAKE_PHOTO:
            if (resultCode == RESULT_OK){
                try{
                    Bitmap bitmap =                                                  BitmapFactory.decodeFile(imagePath);
                    picture.setImageBitmap(bitmap);
                }catch(FileNotFouncException e){
                    e.printStackTrace();
                }
            }
            break;
            ...
        }
    }
}

針對Android系統版本的不同,呼叫不同的方法獲取到圖片的Uri物件.低於7.0呼叫Uri的fromFile方法可以將File物件轉換成Uri物件,否則呼叫FileProvider的gerUriForFile方法將File物件轉換成封裝後的Uri物件,因為用到了FileProvider這種特殊內容提供器,需要對內容提供器註冊,指定Uri的共享路徑,引用建立的@xml/file_paths資源

<paths xmlns:android="http://schemas.android.com/apk/res/android">
    <external-path name="my_images" path="" />
</paths>

2.2.2從相簿中選取照片

相簿的照片是在外存中儲存的,需要申請許可權,獲得授權後,利用Intent物件,開啟相簿程式

Intent intent = new Intent("android.intent.action.GET_CONTENT");
intent.setType("image/*");
startActivityForResult(intent, CHOOSE_PHOTO);

當從相簿選擇照片後,回撥onActivityForResult方法,處理照片。

注意 Android4.4以後,照片不再是真實的Uri,封裝過,需要解析。考慮到相容,需要對不同的系統版本編寫不同的程式碼。具體可參考<<第一行程式碼>> P300

2.3播放多媒體檔案

2.3.1播放音訊

藉助MediaPlayer類,以及控制方法如

  • setDataSource:設定音訊檔案位置
  • prepare:播放前呼叫
  • start:開始或繼續
  • pause:暫停
  • reset:重置
  • seekTo:指定位置
  • stop:停止
  • release:釋放資源
  • isPlaying:播放狀態
  • getDuration:時長

工作流程:

  1. 建立MediaPlayer物件
  2. 呼叫setDataSource設定音訊檔案的路徑
  3. 呼叫prepare是MediaPlayer物件進入到準備狀態
  4. 呼叫start開始播放,pause暫停 reset停止播放
  5. 5.

2.3.2播放視訊

使用VidioView類,類似於MediaPlayer的用法
  • setVideoPath
  • start
  • pause
  • resume
  • seekTo
  • isPlaying
  • getDuration

相關文章