開發項目功能變數名稱想怎麼換就怎麼換,就是這麼任性! 這是一個很有意思的小工具! 這是一個方便開發人員和測試人員的小工具!! 吐槽: 一直在做Android開發,一直總有一個問題存在:做自己公司的apk開發時,線上包和測試包不可兼得~總是在 卸載、安裝、卸載、安裝。。。的迴圈操作。很是麻煩,而且另外一個不得 ...
開發項目功能變數名稱想怎麼換就怎麼換,就是這麼任性!
這是一個很有意思的小工具!
這是一個方便開發人員和測試人員的小工具!!
吐槽:
一直在做Android開發,一直總有一個問題存在:做自己公司的apk開發時,線上包和測試包不可兼得~總是在 卸載、安裝、卸載、安裝。。。的迴圈操作。很是麻煩,而且另外一個不得不正視的問題就是:只要跟服務端人員進行聯調時,就得修改項目中的測試功能變數名稱,重新打包,也是夠麻煩的。最近報名了公司的一個服務,就不得不使用線上包了,被逼無奈想起了這個小設計。
原理:
使用ContentProvider數據共用~
展示圖:
設計思路及源碼解析:
1.前期準備
a.ContentProvider在android中的作用是對外共用數據, 也就是說你可以通過ContentProvider把應用中的數據共用給其他應用訪問,其他應用可以通過ContentProvider對你應用中的數據進行添刪改查。
當應用需要通過ContentProvider對外共用數據時,第一步需要繼承ContentProvider並重寫下麵方法:
public class PersonContentProvider extends ContentProvider{ public boolean onCreate() public Uri insert(Uri uri, ContentValues values) public int delete(Uri uri, String selection, String[] selectionArgs) public int update(Uri uri, ContentValues values, String selection, String[] selectionArgs) public Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs, String sortOrder) public String getType(Uri uri) }
b.第二步需要在AndroidManifest.xml使用對該ContentProvider進行配置,為了能讓其他應用找到該ContentProvider ,ContentProvider採用了authorities(主機名/功能變數名稱)對它進行唯一標識,你可以把ContentProvider看作是一個網 站(想想,網站也是提供數據者),authorities 就是他的功能變數名稱
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.xc1217.contentprovider">
<application
android:allowBackup="true"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:supportsRtl="true"
android:theme="@style/AppTheme">
<activity
android:name=".activity.MainActivity"
android:label="@string/app_name"
android:theme="@style/AppTheme.NoActionBar">
<intent-filter>
<action android:name="android.intent.action.MAIN"/>
<category android:name="android.intent.category.LAUNCHER"/>
</intent-filter>
</activity>
<activity
android:name=".activity.UrlListActivity"
android:theme="@style/AppTheme.NoActionBar">
</activity>
<provider android:name=".db.MyContentProvider"
android:authorities="com.xc1217.contentprovider.myprovider"
android:exported="true"/>
</application>
</manifest>
2.資料庫設計
/** * Created by ding on 2016/11/15. */ public class DBOpenHelper extends SQLiteOpenHelper { private static final String DBNAME = "1217provider.db"; //資料庫名稱 private static final int DBVER = 1;//資料庫版本 public DBOpenHelper(Context context) { super(context, DBNAME, null, DBVER); } @Override public void onCreate(SQLiteDatabase db) { // id 主鍵id, url 路徑 selected 1 選中,0 未選中 String sql = "CREATE TABLE student (id integer primary key autoincrement, url varchar(500), selected int)"; String sql2 = "CREATE TABLE coach (id integer primary key autoincrement, url varchar(500), selected int)"; db.execSQL(sql);//執行有更改的sql語句 db.execSQL(sql2); initDb(db); } private void initDb(SQLiteDatabase db) { String sql = "INSERT INTO student VALUES (1,'http://www.1217.com/', 0)"; String sq2 = "INSERT INTO student VALUES (2,'http://www.1217.com/', 1)"; String sq3 = "INSERT INTO student VALUES (3,'http://www.1217.com/', 0)"; String sq4 = "INSERT INTO student VALUES (4,'http://www.1217.com/', 0)"; db.execSQL(sql); db.execSQL(sq2); db.execSQL(sq3); db.execSQL(sq4); initAddDbCoach(db); } private void initAddDbCoach(SQLiteDatabase db) { String sql = "INSERT INTO coach VALUES (1,'http://www.1217.com/', 0)"; String sq2 = "INSERT INTO coach VALUES (2,'http://www.1217.com/', 1)"; String sq3 = "INSERT INTO coach VALUES (3,'http://www.1217.com/', 0)"; String sq4 = "INSERT INTO coach VALUES (4,'http://www.1217.com/', 0)"; db.execSQL(sql); db.execSQL(sq2); db.execSQL(sq3); db.execSQL(sq4); } @Override public void onUpgrade(SQLiteDatabase db, int arg1, int arg2) { db.execSQL("DROP TABLE IF EXISTS student"); db.execSQL("DROP TABLE IF EXISTS coach"); onCreate(db); } }
3.繼承ContentProvider並重寫方法
/** * Created by ding on 2016/11/15. */ public class MyContentProvider extends ContentProvider { private DBOpenHelper dbOpenHelper; //常量UriMatcher.NO_MATCH表示不匹配任何路徑的返回碼 private static final UriMatcher MATCHER = new UriMatcher(UriMatcher.NO_MATCH); private static final int STUDENTS = 1; private static final int STUDENT = 2; private static final int COACHS = 3; private static final int COACH = 4; static { //如果match()方法匹配content://com.xc1217.contentprovider.myprovider/student路徑,返回匹配碼為1 MATCHER.addURI("com.xc1217.contentprovider.myprovider", "student", STUDENTS); //如果match()方法匹配content://com.xc1217.contentprovider.myprovider/student/123路徑,返回匹配碼為2 MATCHER.addURI("com.xc1217.contentprovider.myprovider", "student/#", STUDENT);//#號為通配符 MATCHER.addURI("com.xc1217.contentprovider.myprovider", "coach", COACHS); MATCHER.addURI("com.xc1217.contentprovider.myprovider", "coach/#", COACH);//#號為通配符 } @Override public int delete(Uri uri, String selection, String[] selectionArgs) { SQLiteDatabase db = dbOpenHelper.getWritableDatabase(); int count = 0; long id = 0; String where = ""; switch (MATCHER.match(uri)) { case STUDENTS: count = db.delete("student", selection, selectionArgs); return count; case STUDENT: //ContentUris類用於獲取Uri路徑後面的ID部分 id = ContentUris.parseId(uri); where = "id = " + id; if (selection != null && !"".equals(selection)) { where = selection + " and " + where; } count = db.delete("student", where, selectionArgs); return count; case COACHS: count = db.delete("coach", selection, selectionArgs); return count; case COACH: //ContentUris類用於獲取Uri路徑後面的ID部分 id = ContentUris.parseId(uri); where = "id = " + id; if (selection != null && !"".equals(selection)) { where = selection + " and " + where; } count = db.delete("coach", where, selectionArgs); return count; default: throw new IllegalArgumentException("Unkwon Uri:" + uri.toString()); } } /** * 該方法用於返回當前Url所代表數據的MIME類型。 * 如果操作的數據屬於集合類型,那麼MIME類型字元串應該以vnd.android.cursor.dir/開頭 * 如果要操作的數據屬於非集合類型數據,那麼MIME類型字元串應該以vnd.android.cursor.item/開頭 */ @Override public String getType(Uri uri) { switch (MATCHER.match(uri)) { case STUDENTS: return "vnd.android.cursor.dir/student"; case STUDENT: return "vnd.android.cursor.item/student"; case COACHS: return "vnd.android.cursor.dir/coach"; case COACH: return "vnd.android.cursor.item/coach"; default: throw new IllegalArgumentException("Unkwon Uri:" + uri.toString()); } } @Override public Uri insert(Uri uri, ContentValues values) { SQLiteDatabase db = dbOpenHelper.getWritableDatabase(); long rowid = 0; Uri insertUri = null;//得到代表新增記錄的Uri switch (MATCHER.match(uri)) { case STUDENTS: rowid = db.insert("student", "url", values); insertUri = ContentUris.withAppendedId(uri, rowid);//得到代表新增記錄的Uri this.getContext().getContentResolver().notifyChange(uri, null); return insertUri; case COACHS: rowid = db.insert("coach", "url", values); insertUri = ContentUris.withAppendedId(uri, rowid);//得到代表新增記錄的Uri this.getContext().getContentResolver().notifyChange(uri, null); return insertUri; default: throw new IllegalArgumentException("Unkwon Uri:" + uri.toString()); } } @Override public boolean onCreate() { this.dbOpenHelper = new DBOpenHelper(this.getContext()); return false; } @Override public Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs, String sortOrder) { SQLiteDatabase db = dbOpenHelper.getReadableDatabase(); long id = 0; String where = null; switch (MATCHER.match(uri)) { case STUDENTS: return db.query("student", projection, selection, selectionArgs, null, null, sortOrder); case STUDENT: id = ContentUris.parseId(uri); where = "id = " + id; if (selection != null && !"".equals(selection)) { where = selection + " and " + where; } return db.query("student", projection, where, selectionArgs, null, null, sortOrder); case COACHS: return db.query("coach", projection, selection, selectionArgs, null, null, sortOrder); case COACH: id = ContentUris.parseId(uri); where = "id = " + id; if (selection != null && !"".equals(selection)) { where = selection + " and " + where; } return db.query("coach", projection, where, selectionArgs, null, null, sortOrder); default: throw new IllegalArgumentException("Unkwon Uri:" + uri.toString()); } } @Override public int update(Uri uri, ContentValues values, String selection, String[] selectionArgs) { SQLiteDatabase db = dbOpenHelper.getWritableDatabase(); int count = 0; long id = 0; String where = null; switch (MATCHER.match(uri)) { case STUDENTS: count = db.update("student", values, selection, selectionArgs); return count; case STUDENT: id = ContentUris.parseId(uri); where = "id = " + id; if (selection != null && !"".equals(selection)) { where = selection + " and " + where; } count = db.update("student", values, where, selectionArgs); return count; case COACHS: count = db.update("coach", values, selection, selectionArgs); return count; case COACH: id = ContentUris.parseId(uri); where = "id = " + id; if (selection != null && !"".equals(selection)) { where = selection + " and " + where; } count = db.update("coach", values, where, selectionArgs); return count; default: throw new IllegalArgumentException("Unkwon Uri:" + uri.toString()); } } }
4.MainActivity. java
public class MainActivity extends AppCompatActivity { private static final String TAG = "MainActivity"; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar); setSupportActionBar(toolbar); findViewById(R.id.lay_student).setOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) { Intent intent = new Intent(MainActivity.this, UrlListActivity.class); intent.putExtra("table", "student"); startActivity(intent); } }); findViewById(R.id.lay_coach).setOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) { Intent intent = new Intent(MainActivity.this, UrlListActivity.class); intent.putExtra("table", "coach"); startActivity(intent); } }); } }
5.UrlListActivity.java
public class UrlListActivity extends AppCompatActivity { private static final String TAG = "UrlListActivity"; String uriString = "content://com.xc1217.contentprovider.myprovider/"; private String table = ""; private List<UrlBean> mList = new ArrayList<UrlBean>(); private ListView listView; private int position; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_url_list); Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar); setSupportActionBar(toolbar); Intent intent = getIntent(); if (intent != null) { table = intent.getStringExtra("table"); if (TextUtils.isEmpty(table)) return; setTitle(table); uriString = uriString + table; } initUI(); getUrlList(); } private void initUI() { listView = (ListView) findViewById(R.id.list_url); findViewById(R.id.btn_add).setOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) { try { showAddPop(); } catch (Throwable throwable) { throwable.printStackTrace(); } } }); listView.setOnItemClickListener(new AdapterView.OnItemClickListener() { @Override public void onItemClick(AdapterView<?> adapterView, View view, int i, long l) { position = i; showClickPop(); } }); } private void showAddPop() { final EditText editText = new EditText(this); editText.setText("http://www.1217.com/"); editText.setHint("http://www.1217.com/"); final AlertDialog alertDialog = new AlertDialog.Builder(this). setTitle("添加") .setNegativeButton("取消", new DialogInterface.OnClickListener() { @Override public void onClick(DialogInterface dialog, int which) { // TODO Auto-generated method stub } }) .setPositiveButton("確定", new DialogInterface.OnClickListener() { @Override public void onClick(DialogInterface dialog, int which) { String url = editText.getText().toString(); insertUrl(url); } }).setView(editText).create(); alertDialog.show(); alertDialog.getButton(AlertDialog.BUTTON_POSITIVE).setOnClickListener(new View .OnClickListener() { @Override public void onClick(View v) { String url = editText.getText().toString(); if (TextUtils.isEmpty(url)) { Toast.makeText(UrlListActivity.this, "不能為空", Toast.LENGTH_SHORT).show(); return; } insertUrl(url); alertDialog.dismiss(); getUrlList(); } }); } private void showClickPop() { final String[] arrayFruit = new String[]{"選擇", "刪除"}; Dialog alertDialog = new AlertDialog.Builder(this). setTitle("編輯") .setItems(arrayFruit, new DialogInterface.OnClickListener() { @Override public void onClick(DialogInterface dialog, int which) { switch (which) { case 0: for (int i = 0; i < mList.size(); i++) { UrlBean urlBean = mList.get(i); urlBean.selected = (position == i ? 1 : 0); update(urlBean); } UrlAdapter urlAdapter = new UrlAdapter(UrlListActivity.this, mList); listView.setAdapter(urlAdapter); break; case 1: int id = mList.get(position).id; deleteById(id); getUrlList(); break; default: break; } } }).setNegativeButton("取消", new DialogInterface.OnClickListener() { @Override public void onClick(DialogInterface dialog, int which) { // TODO Auto-generated method stub } }). create(); alertDialog.show(); } //往內容提供者添加數據 public void insertUrl(String url) { try { ContentResolver contentResolver = this.getContentResolver(); Uri insertUri = Uri.parse(uriString); ContentValues values = new ContentValues(); values.put("url", url); values.put("selected", 0); Uri uri = contentResolver.insert(insertUri, values); Log.i(TAG, uri.toString()); } catch (Exception e) { e.printStackTrace(); } } //更新內容提供者中的數據 public void update(UrlBean urlBean) { try { ContentResolver contentResolver = this.getContentResolver(); Uri updateUri = Uri.parse(uriString + "/" + urlBean.id); ContentValues values = new ContentValues(); values.put("url", urlBean.url); values.put("selected", urlBean.selected); contentResolver.update(updateUri, values, null, null); } catch (Exception e) { e.printStackTrace(); } } //從內容提供者中刪除數據 public void deleteById(Integer id) { try { ContentResolver contentResolver = this.getContentResolver(); Uri deleteUri = Uri.parse(uriString + "/" + id); contentResolver.delete(deleteUri, null, null); } catch (Exception e) { e.printStackTrace(); } } //獲取內容提供者中的數據 public void getUrlList() { try { ContentResolver contentResolver = this.getContentResolver(); Uri selectUri = Uri.parse(uriString); Cursor cursor = contentResolver.query(selectUri, null, null, null, null); if (cursor == null) return; mList.clear(); while (cursor.moveToNext()) { int id = cursor.getInt(cursor.getColumnIndex("id")); String url = cursor.getString(cursor.getColumnIndex("url")); int selected = cursor.getInt(cursor.getColumnIndex("selected")); Log.i(TAG, "id=" + id + ",url=" + url + ",selected=" + selected); UrlBean urlBean = new UrlBean(id, url, selected); mList.add(urlBean); } UrlAdapter urlAdapter = new UrlAdapter(this, mList); listView.setAdapter(urlAdapter); } catch (Exception e) { e.printStackTrace(); } } }
6.UrlAdapter.java
public class UrlAdapter extends BaseAdapter { private Context mContext; private List<UrlBean> mList; public UrlAdapter(Context c, List<UrlBean> l) { // TODO Auto-generated constructor stub mContext = c; mList = l; } @Override public int getCount() { // TODO Auto-generated method stub return mList.size(); } @Override public Object getItem(int arg0) { // TODO Auto-generated method stub return mList.get(arg0); } @Override public long getItemId(int arg0) { // TODO Auto-generated method stub return arg0; } @Override public View getView(final int i, View view, ViewGroup arg2) { ViewHoldel holdel; if (view == null) { holdel = new ViewHoldel(); view = LayoutInflater.from(mContext).inflate(R.layout.url_item, null); holdel.tvContent = (TextView) view.findViewById(R.id.tv_content); holdel.imageView = (ImageView) view.findViewById(R.id.imv_right); view.setTag(holdel); } else { holdel = (ViewHoldel) view.getTag(); } holdel.tvContent.setText(mList.get(i).url); if (mList.get(i).selected == 1) { holdel.imageView.setVisibility(View.VISIBLE); } else { holdel.imageView.setVisibility(View.GONE); } return view; } class ViewHoldel { TextView tvContent; ImageView imageView; } }
7.url_item.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" android:padding="@dimen/activity_horizontal_margin" android:orientation="horizontal"> <TextView android:id="@+id/tv_content" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_weight="1" android:text=",," android:textSize="15sp"/> <ImageView android:id="@+id/imv_right" android:layout_width="wrap_content" android:layout_height="wrap_content" android:src="@mipmap/icon_true_big"/> </LinearLayout>
重點來了!!!
開發人員接入代碼,替換功能變數名稱:
代碼加入到 Application 初始化方法中;根據需要修改下代碼即可。
private void changeServerHostFromProvider() { Uri uri = Uri.parse("content://com.xc1217.contentprovider.myprovider/student"); Cursor cursor = getContentResolver().query(uri, null, null, null, null); if (cursor != null) { while (cursor.moveToNext()) { String url = cursor.getString(cursor.getColumnIndex("url")); int selected = cursor.getInt(cursor.getColumnIndex("selected"));// 1 選中,否則未選中 if (selected == 1 && !TextUtils.isEmpty(url)) { Urls.BASE_URL_TEST = url; Urls.BASE_URL_ONLINE = url; return; } } cursor.close(); } }