Androidの四つの成分のホワイトエッセイエントリー - 詳細なコンテンツ・プロバイダ(コンテンツプロバイダ)

コンテンツプロバイダ

コンテンツプロバイダの概要

コンテンツプロバイダ(コンテンツプロバイダ)が主に使用される異なるアプリケーション間の機能のデータ共有がするメカニズムの完全なセットを提供し、確実にデータが訪問している間、別のプログラムからのアクセスデータへの適用を可能にしますセキュリティは、現在、コンテンツプロバイダの使用は、クロスのAndroidアプリケーション共有データを達成するための標準的な方法です
-正式な学習コンテンツプロバイダの前に、私たちは別の非常に重要な知識を把握する必要がAndroidのランタイム許可を学習コンテンツプロバイダが、我々はこの知識を使用しますので、。また、知識のランタイム権限はしばしば私たちの将来の発展に関係しますので、知識のこの部分はあなたの仕事でしっかりとそれを把握する必要があります

ランタイム権限

Androidの許可メカニズムが存在していたシステムの最初のバージョンの初めから、新しいものではありません。しかし、実際には、ユーザーのセキュリティとプライバシーより限定された役割を保護して再生するにはAndroidの許可メカニズムの前に、特に一部の人は一般的に使用されるソフトウェアから切り離せないのは非常に簡単である「Diandaqike。」このためには、より良いユーザーのプライバシーとセキュリティを保護するために、この機能が動作しているのAndroid 6.0システム権限で参照Androidの開発チームは、このセクションでは、我々は6.0システムで導入された新機能について詳しく学びます。

詳細1.Android許可メカニズム

私たちは、Android郡BroadcastTestプロジェクトに関連するコンテンツに接触する前に、システムにアクセスし、ネットワークブロードキャストブーツの状況を監視するために、その後、AndroidManifest.xmlファイルで宣言された二つのそのような権利を追加しました:

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

ネットワークの状態がシステムにアクセスし、放送のリスニングをオンにするので、ユーザ機器関係のセキュリティを、したがって、文AndroidManifest.xmlファイルのパーミッションに追加する必要がありそうでない場合は、私たちのプログラムがクラッシュしました
だから、これらの二つの権利宣言を添加した後どのような影響を与えるのか、それ最終的にはユーザーのために?なぜ、ユーザ機器、それのセキュリティを保護することができますか?
実際には、メインユーザは二つの方法で保護され、一方で、プログラムはユーザが6.0システムよりも低い場合、プログラムは、インストール・インタフェースのデバイスの権限を要求するデバイスにインストールされています。ように、ユーザは明らかにプログラムがプログラムをインストールするかどうかを決定するために、どのような権利の合計に適用さを知ることができます。
一方、ユーザーは、プログラムへのアクセス許可のための任意のアプリケーションを表示するには、アプリケーション管理インターフェースでいつでも、そのようなすべての権利は、プログラムのパノラマビューに適用され、文は各アプリケーションが表示されないことを確実にするために、ユーザーの目から隠すことができることができます権限の乱用の例。
この設計思想許可メカニズムを使用すると、許可を申請している場合は、それをインストールすることを拒否し、その後、あなたが適用されている権利を認識しない場合、それは、あなたのプログラムをインストールするユーザーに認識されている、実際には非常に簡単です。
しかし、理想的には、我々は権威の一般的なソフトウェア広範な虐待の多くなしで行うことができないので、現実には、それは言うために許可を適用するには、あらかじめアクセス許可を見たくない場合は、使用しているか否か、いずれにせよ、最終的に取得するには、非常に残酷で、良いですそれは拒否したため、あなたはそれをインストールすることができますか?これは、我々が「Diantaiqike」と呼んでいます。
問題の確かに認識してAndroidの開発チームは、その後、実行6.0システム権限の機能を追加しました。言い換えれば、ユーザーは時にワンタイム認証の権限すべてのアプリケーションにソフトウェアをインストールする必要はありませんが、あなたは承認のために再適用するために与えられた権限でソフトウェアを再利用することができます。たとえば、ジオターゲティング権限のランタイムアプリケーションでのカメラアプリケーションは、私はこの権限を拒否したが、私はまだ、このアプリケーションの他の機能を使用できるようにした場合でも、前のように、それを直接インストールすることはできませんではありません。
もちろん、ないすべての権限は、実行時に適用するために必要とされている、ユーザーのために、許可は非常に面倒なまま。アンドロイドは現在2つのカテゴリが所有するすべての権利となり、一般的な権利危険な特権厳密に言えば、三つのカテゴリーがあり、ここで我々は導入しない特別な許可があります。

  • 標準:能力は、ユーザーのセキュリティとプライバシーへの直接的な脅威ではありませんそれらの権利を意味し、アプリケーションのこの部分のための権限は、システムが自動的に手動操作に行くために、ユーザを必要とせずに、私たちが認可するのに役立ちます。
  • 危険な権利:彼らは手動でクリックする前に、これらの権利は、ユーザーのプライバシーに触れたり、機器の安全性に影響を与える可能性があること、などの連絡先情報を取得するデバイスのロケーション、位置決め機器、などは、アクセス要求のこの部分のために、ユーザーは、ライセンスを取得する必要がありますそれ以外のプログラムは、対応する機能を使用することはできません。

そこで問題は、危険な力である私たちは普通の権威ある方法ですので、多くの権限を、ありますか?なぜなら危険の権限のいくつかは、権限の危険性に加えて、我々は普通の残りのすべての権利ですしていた、難しいことではありません。

権限がこの表にない場合は、特権を使用したいときはいつでも、それはこの表の範囲内であるかどうかを確認するために、このテーブルに行くことができる、あなたが実行している場合に対処するための許可を必要とする、あなただけのAndroidManifest.xmlファイルが必要その上にパーミッション文の追加。
また、各ハザード権限がグループの権限に属するテーブルに注意し、許可が実行権限の間に私たちの名前を扱うときに使用しますが、一旦権利が他のすべての権限に権利グループに対応し、ユーザーを承認することに合意しますまた、許可されます。次は、プログラムが実行されている場合、最終的に許可を適用する方法を学びます。

2.プログラムを実行するための許可申請

新しいプロジェクトRuntimePermissionTest、簡単にするために、我々はCALL_PHONEを紹介するこの権限を使用します。
CALL_PHONEこの権限は必要が宣言するときの呼び出しが危険な権威として表示されているユーザーの携帯電話に関連する関税の質問、になるように、関数呼び出しを記述することです。Androidの6.0システムの前に関数呼び出しが実際には非常に簡単であると認識、activity_main.xml次のようにレイアウトファイルを変更するために登場:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent" >

    <Button
        android:id="@+id/make_call"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="Make Call" />

</LinearLayout>

私たちは、ボタンを論理コールをトリガするためにクリックするだけで、ボタンレイアウトファイルを定義します。その後、次のようにMainActivityのコードを変更します。

public class MainActivity extends AppCompatActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        Button makeCall = (Button) findViewById(R.id.make_call);
        makeCall.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                try {
                    Intent intent = new Intent(Intent.ACTION_CALL);
                    intent.setData(Uri.parse("tel:10086"));
                    startActivity(intent);
                } catch (SecurityException e) {
                    e.printStackTrace();
                }
            }
        });
    }
}

また、ボタンのクリックイベントで見ることができ、我々は、アクションを呼び出すための組み込みシステムであるIntent.ACTION_CALLとして指定行動の暗黙の意思、意図を構築し、その後、データセクションが指定するプロトコルはTELで、数10086で、許可をここで宣言する必要があります。また、クラッシュを防止するために、すべての操作は、例外トラップブロックの中に配置されます。
それではここで、以下の権利を述べる、AndroidManifest.xmlファイルを変更します。

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.example.runtimepermissontest">

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

    <application
        android:allowBackup="true"
        android:icon="@mipmap/ic_launcher"
        android:label="@string/app_name"
        android:supportsRtl="true"
        android:theme="@style/AppTheme">
        <activity android:name=".MainActivity">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />

                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
    </application>

</manifest>

私たちではありません成功した達成の関数を呼び出し、電話でのAndroid 6.0システム未満では正常に動作しているが、我々は電話システムのバージョン6.0以降で実行する場合、メイクの通話]ボタンをクリックします何の効果は、印刷ログlogcatで、現時点では認められませんでした。
エラー・ログには、「許可拒否」は、6.0以降およびランタイム許可を処理する必要があります危険な権利の使用中のシステム上、禁止されているため、結果として許可に、見ることができることを私たちに思い出させます。
そこでここでは、次のように、MainActivityにコードを修正し、この問題を解決しようとする来ます。

public class MainActivity extends AppCompatActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        Button makeCall = (Button) findViewById(R.id.make_call);
        makeCall.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                if (ContextCompat.checkSelfPermission(MainActivity.this, Manifest.permission.CALL_PHONE
                ) != PackageManager.PERMISSION_GRANTED) {
                    ActivityCompat.requestPermissions(MainActivity.this, new String[]{ Manifest.permission.CALL_PHONE },1);
                } else {
                    call();
                }
            }
        });
    }

    private void call() {
        try {
            Intent intent = new Intent(Intent.ACTION_CALL);
            intent.setData(Uri.parse("tel:10086"));
            startActivity(intent);
        } catch (SecurityException e) {
            e.printStackTrace();
        }
    }

    @Override
    public void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults) {
        switch (requestCode) {
            case 1:
                if (grantResults.length > 0 && grantResults[0] == PackageManager.
                        PERMISSION_GRANTED) {
                    call();
                } else {
                    Toast.makeText(this, "You denied the permission", Toast.LENGTH_SHORT).show();
                }
                break;
            default:
        }
    }
}

上記のコードは、プロセスを完了しますのは、特定の分析を見てみましょう、権限がカバーされて実行されます。端的に言えば、実行時のコアコンピタンスをしているいくつかの危険な操作を実行するために、ユーザが実行するプログラムの間に私達を許可し、プログラムは、これらの危険な操作を実行するためのショットを呼び出すことはできませんしたがって、最初のステップは、ContextCompat.checkSelfPermission()メソッドであり、ユーザが既に私たちの援助の許可を与えないかどうかを決定することですcheckSelfPermission()メソッドの最初のパラメータがコンテキストで、2つのパラメータを受け入れ、これの何も言わない、2番目のパラメータは、このような名前の呼び出し元に許可がManifest.permission.CALL_PHONEあるように特定の権限の名前で、我々はメソッドの戻り値を使用します値とPackageManager.PERMISSION_GRANTEDの比較は、ユーザが、それは、ユーザーが許可されていないことの承認等しい、等しくないならないことを意味します。
あなたが許可した場合には、シンプル、ダイレクトコールはそれに論理演算を実行するために、ここではそれらの呼び出し()メソッドへのパッケージのロジックを呼び出します。許可されていない場合は、ユーザーからの許可を要求するためにActivityCompat.requestPermissions()メソッドを呼び出す必要があり、requestPermission()メソッドは、最初のパラメータは活動のインスタンスを必要とし、3つのパラメータを受け取り、2番目のパラメータは文字列の配列で、我々がしたいです三番目のパラメータ4つの配列の応募の権利は、それがここ1を通過した唯一の値であるとして、それを要求します。
呼び出しがrequestPermission()メソッドを超えていると、システムはユーザーが同意するかに関係なく、最終的にonRequestPermissionResult(メソッド)フォールバックします結果の種類、アクセスのために私たちの要求を拒否しないように選択することができ、ダイアログボックスの許可申請をポップアップ表示し、許可されますgrantResultパラメータにパッケージ化されます結果。ここでは、ユーザーが同意した場合、その後、あなたが拒否した場合、その後、我々は唯一の操作を放棄することができ、ポップアッププロンプトが失敗し、呼び出しを行うための呼び出し()メソッドを呼び出して、最終承認の結果を決定する必要があります。
コンテンツプロバイダ-今、あなたは、Android上の権限に関する様々な問題に対処する能力を持っていることを、ここで両方の章に着きます。

他のプログラムからデータにアクセスするには

コンテンツプロバイダは、一般的に2つの使用を持っています

  • 対応するプログラムにデータを読み込み、操作するために、既存のコンテンツプロバイダを使用します。
  • 外部アクセスROへのアクセスを提供するために、我々のプログラムのデータに独自のコンテンツプロバイダを作成します。
    それでは、私たちは、開始するために、既存のコンテンツプロバイダの利用から始めて、それを一つずつ学び始めました。アプリケーションは、コンテンツが提供するその外部データアクセスインターフェイスを提供した場合は、他のアプリケーションは、あなたがこのデータの一部にアクセスすることができます。Androidシステムは、電話帳、SMS、メディアライブラリおよびその他のプログラムサードパーティアプリケーションが、より良い機能を実現するために、データのこの部分をフルに活用することができますことができます同様のアクセスインタフェースを提供しますが付属しています。ここでは、最終的には、コンテンツプロバイダを見て、それを使用する方法である取ります。

ContentResolverのの基本的な使い方

あなたは、コンテンツプロバイダにアクセスしたい場合は、各アプリケーションでは、データがContentResolverのクラスによって共有されなければならなかった、あなたは(getContentResolverコンテキストにContentResolverのことで、このクラスのインスタンスを取得することができます)の方法を用いる一連のメソッドを提供しますデータのCRUD操作、ここで:

データを追加するために()メソッドを挿入し
、データが更新するための更新()メソッドを
削除()メソッドは、データを削除するために使用される
方法は、データ照会するために使用されるクエリ()
パラメータテーブル名で受信されていないContentResolverのSQLiteDatabase異なるが、CRUD方法代わりに、URIパラメータを使用するのではなく、このパラメータは、コンテンツURIと呼ばれています。:コンテンツデータは、主に2つの部分から構成されているコンテンツに固有の識別子を確立するためにURIの容器を供給機関パス当局は、異なるアプリケーション間の区別を行うために使用されます。一般的に、競合を避けるために、それが命名されるパッケージ名の道によるであろう。例えば、プログラムパッケージの名前です。comのExample.app、そして権限を対応するプログラムは、指定されcom.example.app.providerの
パスは、彼らは通常、異なるテーブル内の異なるアプリケーション間の区別をするために使用されています権威の後ろに加えます。例えば、二つのテーブルの存在下で、データベースプログラム:TABLE1とtable2の、あなたはTABLE1 /名前を付けて/テーブル2、その後、コンテンツURIを組み合わせた権限とパスがcom.example.appなりPAHすることができます.provider / TABLE1とcom.example.app.provider /テーブル2
しかし、それはこれらの2つの文字列が2つのコンテンツURIであることを認識するには非常に困難な作業である、我々はまた、ヘッド列におけるプロトコルの宣言を追加する必要があります。次のようにそのため、ほとんどの標準フォーマット書かれたコンテンツURIは以下のとおりです。

そこに見つからない、コンテンツURIは非常に我々がどの張テーブルへのアクセスデータをプログラムしたいのか明確にすることができます。あなたは、テーブル名を使用している場合、システムは、我々はテーブルでアプリケーションにアクセスすることを期待している知ることができませんので、検索方法ContentResolverのでは、追加や変更は唯一、パラメータとしてURIオブジェクトを受け取る理由もあります。URI文字列の内容を取得した後、我々はまた、引数として渡すことができるバイオウリオブジェクトにそれを解析する必要があります。次のように分析方法は、非常に簡単です:

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

ただ、Uri.parse()メソッドを呼び出して、コンテンツがURI文字列ウリオブジェクトに解析することができ、そして今、私たちはテーブル内のデータを照会するために、このtablelウリオブジェクトを使用することができ、次のように、コードは次のとおりです。

Cursor cursor = getContentResolver().query(
    uri, 
    projection,
    selection,
    selectionArgs,
    sortOrder);

これらのパラメータし、SQLiteDatabseは、クエリ()のようなパラメータの方法が、全体的に他のプログラムが簡単で、結局、これがアクセスしているデータは、必要があまりにも複雑なクエリを作成しないことです。パラメータのこの部分に使用されるテーブルについて詳細に説明します。

クエリの復帰の完了はまだCursorオブジェクトたら、我々は1つのアウトずつオブジェクトカーソルからデータを読み取ることができます。次のように考えは、まだ、すべての行カーソル位置を通過し、次に対応する列の各行のデータを削除するためにカーソルを移動させることによって読み取られます。

if(cursor != null){
    while(cursor.moveToNext()){
        String column1 = cursor.getString(cursor.getColumnIndex("column1"));
        int column2 =  cursor.getInt(cursor.getColumnIndex("column2"));
    }
    cursor.close();
}

最も困難なクエリ操作、追加の残りの部分をマスターし、修正し、操作も言うまでもない削除します。次のようにコードがあり、tablelにデータテーブルを追加する方法を見てみましょう:

ContentValues values = new ContentValues();
values.put("column1","text");
values.put("column2", 1);
getContentResolver().insert(uri, values);

組み立てられたデータがまだContentValuesに追加される見られ、次いでパラメータとして()メソッド、URIとContentValues後継とすることができる挿入ContentResolverのを呼び出すことができます。今、私たちはこの新しく追加されたデータを更新したい場合は、COLUMN1の値は空に、次のようにContentResolverのupdate()メソッドの実装コードを利用することができます。

ContentValues values = new ContentValues();
values.put( "column1" , "" );
getContentResolver().update( uri, values, "column1 = ? and column2 = ?", new String[] { "text" , "1" } );

影響を受けたすべての行を防ぐために、上記のコードを更新するに制約されるselectionArgs選択とデータのパラメータを使用することに注意してください。最後に、あなたが削除され、このデータを置くためにdelete()メソッドを呼び出すことができますContentResolverの次のように、コードは次のとおりです。

getContentResolver().delete( uri, "column2 = ?", new String[] { "1" } );

これまで、我々はすべて完成し、学校のCRUDメソッドContentResolverのを置きます。それでは、私たちは、これまでに学んだ知識を使っコンタクト情報システムの電話帳を読み取る方法を見てみます。

連絡先の読み取りシステム

まず、お使いの携帯電話に連絡先を追加する必要があり、読みやすいバック私は、このテストマシンには何の接点を持っていないので、連絡先を追加する必要があるため、ここでは2を追加します。次に、新しいContactsTestプロジェクトを作成します。
Activity_main.xmlは、コードを変更します。

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="vertical"
    android:layout_width="match_parent"
    android:layout_height="match_parent">
    
    <ListView
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:id="@+id/contacts_view">
        
    </ListView>
    
</LinearLayout> 

リストビューのレイアウトに加え
のコードMainActivityを変更します:

public class MainActivity extends AppCompatActivity {

    ArrayAdapter<String> adapter;
    List<String> contactsList = new ArrayList<>();

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        ListView contactsView = (ListView) findViewById(R.id.contacts_view);
        adapter = new ArrayAdapter<String>(this,android.R.layout.simple_list_item_1,contactsList);
        contactsView.setAdapter(adapter);
        if(ContextCompat.checkSelfPermission(this, Manifest.permission.READ_CONTACTS)!= PackageManager.PERMISSION_GRANTED){
            ActivityCompat.requestPermissions(this,new String[]{Manifest.permission.READ_CONTACTS},1);
        }else {
            readContacts();
        }
    }

    private void readContacts(){
        Cursor cursor = null;
        try{
            cursor = getContentResolver().query(ContactsContract.CommonDataKinds.Phone.CONTENT_URI,null,null,null,null);
            if(cursor != null){
                while(cursor.moveToNext()){
                    String displayName = cursor.getString(cursor.getColumnIndex(ContactsContract.CommonDataKinds.Phone.DISPLAY_NAME));
                    String number = cursor.getString(cursor.getColumnIndex(ContactsContract.CommonDataKinds.Phone.NUMBER));
                    contactsList.add(displayName+"\n"+number);
                }
                adapter.notifyDataSetChanged();
            }
        }catch (Exception e){
            e.printStackTrace();
        }finally {
            if (cursor != null){
                cursor.close();
            }
        }
    }

    @Override
    public void onRequestPermissionsResult(int requestCode,String[] permissions,int[] grantResults){
        switch (requestCode){
            case 1:
                if (grantResults.length > 0&& grantResults[0] == PackageManager.PERMISSION_GRANTED){
                    readContacts();
                }else {
                    Toast.makeText(this,"You denied the permission",Toast.LENGTH_SHORT).show();
                }
                break;
            default:
        }
    }
}

OnCreate関数()メソッドでは、まず、リストビューコントロールのインスタンスを取得し、それを良いアダプタを与え、その後、READ_CONTACTS権は危険な権限であるため、処理ロジック権限ランタイムを呼ぶようになりました。ランタイム権限のプロセスフローは、あなたが芸術をマスターしていると信じています。連絡先情報を読み取るために、ユーザ認証システムの後readContacts()メソッドを呼び出します。次のハイライトは、readContactsを見て()メソッドは、システムの連絡先データを照会するためにここにquery()メソッドのContentResolverの使用を見ることができます。しかし、入ってくるウリパラメータは奇妙なああは?ーコンテンツURI文字列を解決するためにUri.parse()メソッドを呼び出していないのはなぜ?これはContactsContract.CommonDataKinds.Phoneクラスが提供する、パッケージを行うために私たちを助けているされているため、どのように定数CONTENT_URI、この定数は、()メソッドは、結果を解析しUri.parseの使用です。その後、我々は、カーソルオブジェクトを横切る一つ一つは、連絡先の名前を削除し、この欄に連絡先の名前に対応する電話番号データを一定ContactsContract.CommonDataKinds.Phone.DISPLAY_NAMEあり、この列の連絡先の電話番号は、対応する定数ContactsContract.CommonDatakindsあります。 Phone.NUMBER。二つのデータが削除された後、彼らはスプライスされ、その後、リストビューのデータソースにスプライスされたデータを追加し、リフレッシュListViewコントロールに通知します。最後に、カーソルオブジェクトを遮断することを忘れないでください。
この結び目東まだ?まだ少し恥ずかしがり屋、システムが接触当局は声明を忘れてはならない読み込みます。AndroidManifest.xml内のコードを変更します。

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

おすすめ

転載: www.cnblogs.com/AleiCui/p/11691035.html