ContentProvider 기능이 필요해서 가져다 사용 하려는데,

현재 검색되는 코드들은 대부분 되는 것들이 없어서 (코드 자체로는 전혀 문제가 없었지만 추가사항이 있어서..) 코드 공유 합니다.


기본적인 설명으로는 여기를 

https://developer.android.com/guide/topics/providers/content-provider-creating.html?hl=ko


이외 코드 관련 부분은 아래에서 참고하였습니다.

참고URL : https://www.tutorialspoint.com/android/android_content_providers.htm



주의사항!

studio가 불안정한건지, 아님 저의 툴 설정이 문제인건지, 여러번 빌드시 이전 provider 설정들이 남아 있는건지

정상 동작하지 않던 문제가 있었습니다. 

저같은 경우는 항상 A,B 앱을 uninstall 후에 빌드 시 제대로된 결과을 얻을 수 있었습니다.

(Permission Denial: opening provider com.app.first.myContentProvider from ..... 등등이 나온다면...)



1. A앱 작업 Mainfests (퍼미션을 추가합니다. 프로바이더 내에서도 readPermission과 writePermission , exprted를 명시합니다.)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
<p><?xml version="1.0" encoding="utf-8"?>
    package="com.app.first">
 
    <!-- 퍼미션 추가 -->
    <permission android:name="com.app.first.READ_DATABASE" android:protectionLevel="normal" />
    <permission android:name="com.app.first.WRITE_DATABASE" android:protectionLevel="normal" />
 
    <application
        android:allowBackup="true"
        android:icon="@mipmap/ic_launcher"
        android:label="@string/app_name"
        android:roundIcon="@mipmap/ic_launcher_round"
        android:supportsRtl="true"
        android:theme="@style/AppTheme">
        <activity
            android:name=".MainActivity"
            android:label="@string/app_name">
 
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />
 
                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
 
    <!-- 프로바이더 등록 -->
        <provider android:name=".myContentProvider"
            android:authorities="com.app.first.myContentProvider"
            android:exported="true"
            android:readPermission="com.app.first.READ_DATABASE"
            android:writePermission="com.app.first.WRITE_DATABASE"/>
 
    </application>
</manifest></p>

activity_main.xml (레이아웃 만들기)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:padding="16dp"
    tools:context="com.app.first.MainActivity">
 
    <Button
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="데이터 불러오기"
        android:id="@+id/bt_renew"/>
 
    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginTop="16dp"
        android:layout_below="@id/bt_renew"
        android:textSize="15sp"
        android:text="Hello World!"
        android:id="@+id/tv_text"/>
 
</RelativeLayout>

MainActivity.java (메인 화면 처리)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
package com.app.first;
 
import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.view.View;
import android.widget.Button;
import android.widget.TextView;
 
import java.util.ArrayList;
import java.util.List;
 
public class MainActivity extends AppCompatActivity {
 
    DBHelper mDatabase;
 
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
 
        mDatabase = new DBHelper(getBaseContext());
 
        // 데이터 입력
        mDatabase.setDelete();
        List<ItemRow> mList = new ArrayList<>();
        mList.add(new ItemRow("식사","미역국",5000));
        mList.add(new ItemRow("간식","우유",4000));
        mList.add(new ItemRow("간식","바나나",3000));
        mList.add(new ItemRow("식사","오이",2000));
        mList.add(new ItemRow("식사","당근",1000));
        for(ItemRow item : mList) {
            mDatabase.setItem(item.contents, item.name, item.num);
        }
 
        Button bt_renew = (Button) findViewById(R.id.bt_renew);
        bt_renew.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                // 데이터 불러오기
                loadData();
            }
        });
    }
 
    private void loadData() {
        StringBuilder sb = new StringBuilder();
        List<ItemRow> row = mDatabase.getItem();
        sb.append("Total count : "+row.size()+"\n\n");
        for(ItemRow item : row) {
            sb.append(item.contents+" , "+item.name+" , "+item.num+"\n");
        }
        TextView tv_text = (TextView) findViewById(R.id.tv_text);
        tv_text.setText(sb.toString());
    }
 
    @Override
    protected void onDestroy() {
        super.onDestroy();
        if(mDatabase != null)
            mDatabase.close();
    }
}
 
class ItemRow {
    public String contents;
    public String name;
    public int num;
 
    public ItemRow(String contents, String name, int num) {
        this.contents = contents;
        this.name = name;
        this.num = num;
    }
}

DBHelper.java (디비 로직 작업)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
package com.app.first;
 
import android.content.ContentValues;
import android.content.Context;
import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteException;
import android.database.sqlite.SQLiteOpenHelper;
import android.provider.BaseColumns;
 
import java.util.ArrayList;
import java.util.List;
 
public class DBHelper extends SQLiteOpenHelper {
 
    private static final int db_version = 1;                    // Database Version
    private static final String DB_FILE_NAME = "UserData.db";
 
    private static final String [] COLUMNS = {"contents TEXT", "name TEXT", "num INTEGER"};
    public static String TABLE_NAME = "my_table";
 
    public DBHelper(Context context) {
        super(context, DB_FILE_NAME, null, db_version);
    }
 
    @Override
    public void onCreate(SQLiteDatabase db) {
        String sql = "create table " + TABLE_NAME +
                " (" + BaseColumns._ID + " integer primary key autoincrement ";
        for (int i = 0; i < COLUMNS.length; i++) {
            sql += ", " + COLUMNS[i];
        }
        sql += " ) ";
        db.execSQL(sql);
    }
 
    @Override
    public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
    }
 
    public List<ItemRow> getItem() {
        List<ItemRow> list = new ArrayList<>();
        try {
            beginTransaction();
            Cursor c = getAll(TABLE_NAME);
            if (c != null) {
                int total = c.getCount();
                if (total > 0) {
                    c.moveToFirst();
                    while (!c.isAfterLast()) {
                        String contents = c.getString(1);
                        String name = c.getString(2);
                        int num = c.getInt(3);
                        list.add(new ItemRow(contents, name, num));
                        c.moveToNext();
                    }
                }
                c.close();
            }
        } catch (SQLiteException e) {
            e.printStackTrace();
        } finally {
            endTransaction();
        }
        return list;
    }
 
    public void setItem(String contents, String name, int num) throws SQLiteException{
        ContentValues values = new ContentValues();
        values.put("contents", contents);
        values.put("name", name);
        values.put("num", num);
        insert(TABLE_NAME, values);
    }
 
    public void setDelete() {
        AllDelete(TABLE_NAME);
    }
 
    protected Cursor getAll(String tableName) throws SQLiteException {
        return getReadableDatabase().query(tableName, null, null, null, null, null, /*"date desc"*/null);
    }
 
    protected void beginTransaction() {
        getWritableDatabase().beginTransaction();
    }
    protected void endTransaction() {
        getWritableDatabase().setTransactionSuccessful();   // db 속도 향상
        getWritableDatabase().endTransaction();
    }
 
    protected void insert(String tableName, ContentValues values) throws SQLiteException {
        getWritableDatabase().insert(tableName, null, values);
    }
 
    protected void AllDelete(String tableName) throws SQLiteException{
        getWritableDatabase().delete(tableName, null, null);
    }
}

myContentProvider.java (컨텐트프로바이더 내의 쿼리 처리)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
<p>package com.app.first;
 
import android.content.ContentProvider;
import android.content.ContentValues;
import android.content.UriMatcher;
import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteQueryBuilder;
import android.net.Uri;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import android.util.Log;
 
import java.util.HashMap;
 
public class myContentProvider extends ContentProvider {
 
    private SQLiteDatabase mDatabase;
    static final String PROVIDER_NAME = "com.app.first.myContentProvider";
    private static HashMap<String, String> STUDENTS_PROJECTION_MAP;
    static final int GET_ALL = 1;
    static final int INSERT = 2;
    static final int UPDATE = 3;
    static final int DELETE = 4;
    static final UriMatcher uriMatcher;
    static {
        uriMatcher = new UriMatcher(UriMatcher.NO_MATCH);
        uriMatcher.addURI(PROVIDER_NAME, "getAll", GET_ALL);
        uriMatcher.addURI(PROVIDER_NAME, "insert", INSERT);
    }
 
    @Override
    public boolean onCreate() {
        DBHelper dbHelper = new DBHelper(getContext());
        mDatabase = dbHelper.getWritableDatabase();
        return (mDatabase == null)? false:true;
    }
 
    @Nullable
    @Override
    public Cursor query(@NonNull Uri uri, @Nullable String[] projection, @Nullable String selection, @Nullable String[] selectionArgs, @Nullable String sortOrder) {
        Log.d("test","uri : "+uri);
        SQLiteQueryBuilder qb = new SQLiteQueryBuilder();
        qb.setTables("my_table");
            //switch (uriMatcher.match(uri)) {
              //  case STUDENTS:
                //    qb.setProjectionMap(STUDENTS_PROJECTION_MAP);
                  //  break;
               // case STUDENT_ID:
                 //   qb.appendWhere( _ID + "=" + uri.getPathSegments().get(1));
                  //  break;
              //  default:
           // }
        qb.setProjectionMap(STUDENTS_PROJECTION_MAP);
         
        if (sortOrder == null || sortOrder == ""){
            sortOrder = /*NAME*/"contents";
        }
         
        Cursor c = qb.query(mDatabase, projection, selection, selectionArgs,null, null, sortOrder);
        c.setNotificationUri(getContext().getContentResolver(), uri);
        return c;
    }
 
    @Nullable
    @Override
    public String getType(@NonNull Uri uri) {
        return null;
    }
 
    @Nullable
    @Override
    public Uri insert(@NonNull Uri uri, @Nullable ContentValues values) {
        return null;
    }
 
    @Override
    public int delete(@NonNull Uri uri, @Nullable String selection, @Nullable String[] selectionArgs) {
        return 0;
    }
 
    @Override
    public int update(@NonNull Uri uri, @Nullable ContentValues values, @Nullable String selection, @Nullable String[] selectionArgs) {
        return 0;
    }
}</p>


2. B앱 Mainfests (퍼미션 설정을 추가합니다.)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
<?xml version="1.0" encoding="utf-8"?>
    package="com.app.second">
 
    <!-- 퍼미션 설정 -->
    <uses-permission android:name="com.app.first.READ_DATABASE" />
    <uses-permission android:name="com.app.first.WRITE_DATABASE" />
    <!-- 퍼미션 설정 -->
 
    <application
        android:allowBackup="true"
        android:icon="@mipmap/ic_launcher"
        android:label="@string/app_name"
        android:roundIcon="@mipmap/ic_launcher_round"
        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>

activity_main.xml

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
<?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context="com.app.second.MainActivity">
 
    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Hello World!"
        android:id="@+id/text"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintLeft_toLeftOf="parent"
        app:layout_constraintRight_toRightOf="parent"
        app:layout_constraintTop_toTopOf="parent" />
 
</android.support.constraint.ConstraintLayout>
MainActivity.java (A앱의 myContentProvider에 쿼리를 날려 데이터를 가져옵니다.)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
package com.app.second;
 
import android.database.Cursor;
import android.net.Uri;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.util.Log;
import android.widget.TextView;
 
public class MainActivity extends AppCompatActivity {
 
    String authority = "com.app.first.myContentProvider";
 
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
 
        Cursor c = getContentResolver().query(Uri.parse("content://"+authority+"/getdataall"), null, null, null, null);
        if(c == null)
            return;
        Log.e("test","aaabbb "+c.getCount());
 
        StringBuilder aa = new StringBuilder();
        while(c.moveToNext()) {
            String str = c.getLong(0) + " , " + c.getString(1)+" , "+c.getString(2)+" , "+c.getInt(3);
            System.out.println(str);
            aa.append(str+"\n");
        }
        c.close();
 
        TextView text = (TextView) findViewById(R.id.text);
        text.setText(aa);
    }
}



3. 결과 화면 


A앱                                                         B앱

    

+ Recent posts