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" ?> <manifest xmlns:android= "http://schemas.android.com/apk/res/android" 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" 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" ?> <manifest xmlns:android= "http://schemas.android.com/apk/res/android" 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" 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> |
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앱
'Android' 카테고리의 다른 글
[안드로이드] 갤럭시 S8(18.5:9), LG G6(18:9) 화면비 적용하기 (0) | 2017.06.09 |
---|---|
[안드로이드] android canvas triangle, star, heart 예제 (TouchEvent) (0) | 2017.05.22 |
[안드로이드] android keypad 내의 Done(enter,search,...) 눌렀을 경우 이벤트 (0) | 2017.05.14 |
[안드로이드] Android studio vector image 사용하기 (0) | 2017.05.12 |
[안드로이드] App cash data 앱 캐시 지우기 예제 (1) | 2017.05.01 |