• ContentProvider


     ContentProvider表示“内容提供者”。
      ContentProvider是一种数据共享机制,它将同意其他应用程序对自身应用程序中的数据
      运行增删改查操作;
      ContentProvider是Android核心组件之中的一个,因此,开发者在创建它时,须要自己定义继承
      ContentProvider,并且,它须要在项目清单文件里(AndroidMainfest.xml)中注冊。
      ContentProvider须要定义用于訪问数据的URI,当其它应用程序知晓相应的URI时,就可以
      运行数据的相关操作。


      ContentProvider无需被激活,当配置了ContentProvider的应用程序被安装到设备上。
      同一台设备上的其他应用程序随时都能够訪问它的数据。
    ContentProvider的开发步骤:
         自己定义类继承android,content.ContentProvider类。
         重写android.content.ContentProvider类中声明的抽象方法;
         在AndroidMainfest.xml文件里配置ContentProvider:
                创建<application>节点下加入<provider>子节点。
        配置android.name属性,指定ContentProvider类;
        配置android.authorities属性,指定用于訪问数据的URI的host部分;
       配置android:exported属性,指定值为true。
         标准URI:scheme://host:port/path
         比如:http://www.goole.com:80/android

       注意:基于ContentProvider中数据增删改查的方法与使用SQLite数据库时使用的方法极为相似。因此,
       大多数的ContentProvider共享的数据的方式都是通过操作SQLite数据库完毕的,可是,ContentProvider
       与SQLite数据库没有必定的关联。

          ContentProvider样例:

         package com.example.lianxi;
    
    import android.content.ContentProvider;
    import android.content.ContentValues;
    import android.database.Cursor;
    import android.database.sqlite.SQLiteDatabase;
    import android.net.Uri;
    
    public class StudentProvider extends ContentProvider{
    
    	private DBOpenHelper helper;
    	@Override
    	public int delete(Uri arg0, String selection, String[] selectionArgs) {
    		SQLiteDatabase db = helper.getReadableDatabase();
    		db.delete("students", selection, selectionArgs);
    		return 0;
    	}
    
    	@Override
    	public String getType(Uri uri) {
    		// TODO Auto-generated method stub
    		return null;
    	}
    
    	@Override
    	public Uri insert(Uri uri, ContentValues values) {
    		//插入
    		SQLiteDatabase db = helper.getReadableDatabase();
    		db.insert("students", null, values);
    		return null;
    	}
    
    	@Override
    	public boolean onCreate() {
    		// 完毕初始化的操作
    		helper = new DBOpenHelper(getContext());
    		return false;
    	}
    
    	@Override
    	public Cursor query(Uri uri, String[] projection, String selection,
    			String[] selectionArgs, String sortOrder) {
    		// 查询
    		SQLiteDatabase db = helper.getReadableDatabase();
    		Cursor cursor = db.query("students", projection, selection, selectionArgs, null, null, sortOrder);
    		return cursor;
    	}
    
    	@Override
    	public int update(Uri uri, ContentValues values, String selection,
    			String[] selectionArgs) {
    		SQLiteDatabase db = helper.getReadableDatabase();
    		db.update("students", values, selection, selectionArgs);
    		return 0;
    	}
    
    }

    DBOpenHelper:

     package com.example.lianxi;
    
    import android.content.Context;
    import android.database.sqlite.SQLiteDatabase;
    import android.database.sqlite.SQLiteOpenHelper;
    
    public class DBOpenHelper extends SQLiteOpenHelper{
     
    	public DBOpenHelper(Context context){
    		super(context,"number2.db",null,1);
    	}
    	@Override
    	public void onCreate(SQLiteDatabase db) {
    		// TODO Auto-generated method stub
    		String sql = "CREATE TABLE [students] (" 
    				+"[_id] INTEGER PRIMARY KEY AUTOINCREMENT,"
    				+"[_name] VARCHAR(50) UNIQUE NOT NULL,"
    				+"[_age] INT NOT NULL DEFAULT 16"
    				+")";
    		db.execSQL(sql);
    		
    	}
    
    	@Override
    	public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
    		// TODO Auto-generated method stub
    		
    	}
    
    }

    MainActivity:

    package com.example.lianxi;
    
    import android.app.Activity;
    import android.content.ContentValues;
    import android.content.SharedPreferences;
    import android.content.SharedPreferences.Editor;
    import android.database.Cursor;
    import android.database.sqlite.SQLiteDatabase;
    import android.os.Bundle;
    import android.view.View;
    import android.widget.EditText;
    import android.widget.Toast;
    
    
    public class MainActivity extends Activity {
    	private DBOpenHelper helper;
    	private SQLiteDatabase db;
    	private EditText name;
    	
        @Override
    	protected void onCreate(Bundle savedInstanceState) {
    		super.onCreate(savedInstanceState);
    		setContentView(R.layout.activity_main);
    		
    		helper = new DBOpenHelper(this);
    		db = helper.getReadableDatabase();
    		name = (EditText) findViewById(R.id.name);
    		
        }
        public void find_All(View view){
        	Cursor cursor = db.query("students", new String[]{"_id","_name","_age"}, null, null, null, null, "_id desc");
            long id;
            String name;
            int age;
            
        	for(cursor.moveToFirst(); !cursor.isAfterLast();cursor.moveToNext()){
        	    id = cursor.getLong(cursor.getColumnIndex("_id"));
        	    name = cursor.getString(cursor.getColumnIndex("_name"));
        	    age = cursor.getInt(cursor.getColumnIndex("_age"));
        		System.out.println("id = " + id + " ," + "name = " +name +" ," + "age = " + age);
        		
           }
        	cursor.close();
        }
        public void findName(View view){
        	String findName = name.getText().toString();
        	Cursor cursor = db.query("students", null, "_name=?

    ", new String[]{findName}, null, null, null); if(cursor.moveToFirst()){ long id1; String name1; int age1; id1 = cursor.getLong(cursor.getColumnIndex("_id")); name1 = cursor.getString(cursor.getColumnIndex("_name")); age1 = cursor.getInt(cursor.getColumnIndex("_age")); Toast.makeText(this, "学生记录为id = " + id1 + " ," + "name = " +name1 + " ," + "age = " + age1, Toast.LENGTH_LONG).show(); }else{ Toast.makeText(this, "没有匹配的记录!

    ", Toast.LENGTH_LONG).show(); } } }


    布局设置:

     <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
        xmlns:tools="http://schemas.android.com/tools"
        android:layout_width="fill_parent"
        android:layout_height="fill_parent"
        android:orientation="vertical" >
    
        <Button
            android:id="@+id/find_all"
            android:layout_width="fill_parent"
            android:layout_height="wrap_content"
            android:layout_marginTop="30dp"
            android:onClick="find_All"
            android:text="查询全部数据" />
    
        <LinearLayout
            android:layout_width="fill_parent"
            android:layout_height="fill_parent"
            android:layout_marginTop="30dp"
            android:orientation="horizontal" >
    
        <EditText
            android:id="@+id/name"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:ems="10" >
    
        </EditText>
    
        <Button
            android:id="@+id/find"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_marginLeft="20dp"
            android:onClick="findName"
            android:text="查询" />
      </LinearLayout>
    </LinearLayout>

    要在AndroidMainfest.xml中注冊:
         <provider android:name="com.example.lianxi.StudentProvider"
              android:exported="true"
              android:authorities="test"></provider>


    訪问ContentProvider共享的数据
            ContentResolver:ContentResolver:用于訪问其他应用程序通过ContentProvider共享的数据;
        通过ContextWraper类定义的getContentResolver()方法就可以获取ContentResolver的对象。
    通过使用ContentResolver訪问上一个应用程序内的数据。样例:
            布局不需改动,MainActivity:

    package com.example.lianxi;
    
    import android.app.Activity;
    import android.content.ContentValues;
    import android.content.SharedPreferences;
    import android.content.SharedPreferences.Editor;
    import android.database.Cursor;
    import android.database.sqlite.SQLiteDatabase;
    import android.os.Bundle;
    import android.view.View;
    import android.widget.EditText;
    import android.widget.Toast;
    
    
    public class MainActivity extends Activity {
    	private DBOpenHelper helper;
    	private SQLiteDatabase db;
    	private EditText name;
    	
        @Override
    	protected void onCreate(Bundle savedInstanceState) {
    		super.onCreate(savedInstanceState);
    		setContentView(R.layout.activity_main);
    		
    		helper = new DBOpenHelper(this);
    		db = helper.getReadableDatabase();
    		name = (EditText) findViewById(R.id.name);
    		
        }
        public void find_All(View view){
        	Cursor cursor = db.query("students", new String[]{"_id","_name","_age"}, null, null, null, null, "_id desc");
            long id;
            String name;
            int age;
            
        	for(cursor.moveToFirst(); !cursor.isAfterLast();cursor.moveToNext()){
        	    id = cursor.getLong(cursor.getColumnIndex("_id"));
        	    name = cursor.getString(cursor.getColumnIndex("_name"));
        	    age = cursor.getInt(cursor.getColumnIndex("_age"));
        		System.out.println("id = " + id + " ," + "name = " +name +" ," + "age = " + age);
        		
           }
        	cursor.close();
        }
        public void findName(View view){
        	String findName = name.getText().toString();
        	Cursor cursor = db.query("students", null, "_name=?", new String[]{findName}, null, null, null);
           if(cursor.moveToFirst()){
        	   long id1;
               String name1;
               int age1;
               id1 = cursor.getLong(cursor.getColumnIndex("_id"));
       	    name1 = cursor.getString(cursor.getColumnIndex("_name"));
       	    age1 = cursor.getInt(cursor.getColumnIndex("_age"));
       	    Toast.makeText(this, "学生记录为id = " + id1 + " ," + "name = " +name1 + " ," + "age = " + age1, Toast.LENGTH_LONG).show();
       	    
           }else{
        	   Toast.makeText(this, "没有匹配的记录!

    ", Toast.LENGTH_LONG).show(); } } }


    訪问到的结果为:

     12-30 13:36:02.608: I/System.out(1305): id=1
    12-30 13:36:02.616: I/System.out(1305): name=Mike
    12-30 13:36:02.616: I/System.out(1305): age=28
    12-30 13:36:02.616: I/System.out(1305): id=2
    12-30 13:36:02.616: I/System.out(1305): name=fgusdfg
    12-30 13:36:02.616: I/System.out(1305): age=21
    12-30 13:36:02.616: I/System.out(1305): id=3
    12-30 13:36:02.616: I/System.out(1305): name=huanghdf
    12-30 13:36:02.616: I/System.out(1305): age=23
    12-30 13:36:02.616: I/System.out(1305): id=4
    12-30 13:36:02.616: I/System.out(1305): name=Macal
    12-30 13:36:02.616: I/System.out(1305): age=45
    12-30 13:36:02.616: I/System.out(1305): id=5
    12-30 13:36:02.616: I/System.out(1305): name=jiaokong
    12-30 13:36:02.616: I/System.out(1305): age=34
    12-30 13:36:02.616: I/System.out(1305): id=6
    12-30 13:36:02.620: I/System.out(1305): name=sdfff
    12-30 13:36:02.620: I/System.out(1305): age=56

    SimpleCursorAdapter:
    SimpleCursorAdapter是一种使用Cursor对象作为数据源的Adapter。
    使用SimpleCursorAdapter时,要求Cursor对象中必须存在名为_id的列。
    使用实例,相同訪问的是上面应用的数据:

    MainActivity:

     package com.example.contentresolver;
    
    import android.app.Activity;
    import android.content.ContentResolver;
    import android.database.Cursor;
    import android.net.Uri;
    import android.os.Bundle;
    import android.support.v4.widget.SimpleCursorAdapter;
    import android.view.Menu;
    import android.view.MenuItem;
    import android.widget.ListView;
    
    public class MainActivity extends Activity {
    
    	private ListView listView;
    	private SimpleCursorAdapter adapter;
    
    	@Override
    	protected void onCreate(Bundle savedInstanceState) {
    		super.onCreate(savedInstanceState);
    		setContentView(R.layout.activity_main);
    		ContentResolver cr = getContentResolver();
    		Uri uri = Uri.parse("content://test");
    		Cursor cursor = cr.query(uri, new String[] { "_id", "_name", "_age" },
    				null, null, null);
    
    		listView = (ListView) findViewById(R.id.lv_student);
    		String[] from = { "_id", "_name", "_age" };
    		int[] to = { R.id.item_id, R.id.item_name, R.id.item_age };
    		adapter = new SimpleCursorAdapter(this, R.layout.student_item, cursor,
    				from, to, 0);
    		listView.setAdapter(adapter);
    		
    
    	}
    }

    布局:

    <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:gravity="center_vertical"
         >
         <LinearLayout 
             android:id="@+id/ll_head"
             android:layout_width="match_parent"
             android:layout_height="wrap_content"
             android:orientation="horizontal"
             >
             <TextView 
                 android:id="@+id/tv_id"
                 android:layout_width="match_parent"
                 android:layout_height="wrap_content"
                 android:text="ID"
                 android:gravity="center"
                 android:layout_weight="1"
                 android:padding="3dp"
                 android:layout_margin="1dp"
                 android:background="#aaaaaa"
                 android:textColor="#ffffff"/>
               <TextView 
                 android:id="@+id/tv_name"
                 android:layout_width="match_parent"
                 android:layout_height="wrap_content"
                 android:text="NAME"
                 android:gravity="center"
                 android:layout_weight="1"
                 android:padding="3dp"
                 android:layout_margin="1dp"
                 android:background="#aaaaaa"
                 android:textColor="#ffffff"/>
                 <TextView 
                 android:id="@+id/tv_age"
                 android:layout_width="match_parent"
                 android:layout_height="wrap_content"
                 android:text="AGE"
                 android:gravity="center"
                 android:layout_weight="1"
                 android:padding="3dp"
                 android:layout_margin="1dp"
                 android:background="#aaaaaa"
                 android:textColor="#ffffff"/>
         </LinearLayout>
        <ListView 
            android:id="@+id/lv_student"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:layout_marginTop="30dp"></ListView>
    
    </RelativeLayout>

    item_student:

     <?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:orientation="horizontal" > <TextView android:id="@+id/item_id" android:layout_width="match_parent" android:layout_height="wrap_content" android:text="ID" android:gravity="center" android:layout_weight="1" android:padding="3dp" android:layout_margin="1dp" /> <TextView android:id="@+id/item_name" android:layout_width="match_parent" android:layout_height="wrap_content" android:text="NAME" android:gravity="center" android:layout_weight="1" android:padding="3dp" android:layout_margin="1dp" /> <TextView android:id="@+id/item_age" android:layout_width="match_parent" android:layout_height="wrap_content" android:text="AGE" android:gravity="center" android:layout_weight="1" android:padding="3dp" android:layout_margin="1dp" /> </LinearLayout>


     ContentProvider中的URI,自己定义ContentProvider。实例:

     核心代码:

     StudentProvider:

    package com.example.lianxi;
    
    import android.content.ContentProvider;
    import android.content.ContentUris;
    import android.content.ContentValues;
    import android.content.UriMatcher;
    import android.database.Cursor;
    import android.database.sqlite.SQLiteDatabase;
    import android.net.Uri;
    
    public class StudentProvider extends ContentProvider {
    	/*
    	 * 验证URI 1、是否合法 2、推断操作类型
    	 */
    
    	/*
    	 * 合法的URI content://com.example.lianxi.providers/student 訪问所有的数据
    	 * content://com.example.lianxi.providers/student/5 訪问ID为5的数据
    	 */
    	private DBOpenHelper helper;
    	private static UriMatcher MATCHER;// 用于验证URi的类
    
    	private static String AUTHORITY = "com.example.lianxi.providers";
    	private static String PATH = "student";
    	private static int MATCHER_ALL = 23;
    	private static int MATCHER_ID = 34;
    	static {
    		MATCHER = new UriMatcher(UriMatcher.NO_MATCH);
    		MATCHER.addURI(AUTHORITY, PATH, MATCHER_ALL);
    		MATCHER.addURI(AUTHORITY, PATH + "/#", MATCHER_ID);
    	}
    
    	@Override
    	public int delete(Uri uri, String selection, String[] selectionArgs) {
    		if (MATCHER.match(uri) == MATCHER_ID) {
    			SQLiteDatabase db = helper.getReadableDatabase();
    			long id = ContentUris.parseId(uri);
    			String whereClause;
    			if (selection == null || "".equals(selection)) {
    				whereClause = "_id" + id;
    			} else {
    				whereClause = selection + " and _id=" + id;
    			}
    			int result = db.delete("students", whereClause, selectionArgs);
    			return result;
    		} else {
    			throw new IllegalArgumentException("非法的URI:" + uri.toString());
    		}
    	}
    
    	@Override
    	public String getType(Uri uri) {
    		// TODO Auto-generated method stub
    		return null;
    	}
    
    	@Override
    	public Uri insert(Uri uri, ContentValues values) {
    		// 插入
    		if (MATCHER.match(uri) == MATCHER_ALL) {
    			SQLiteDatabase db = helper.getReadableDatabase();
    			long id = db.insert("students", null, values);
    			return ContentUris.withAppendedId(uri, id);// 返回的为两者合成的
    
    		} else {
    			throw new IllegalArgumentException("非法的URI:" + uri.toString());
    		}
    
    	}
    
    	@Override
    	public boolean onCreate() {
    		// 完毕初始化的操作
    		helper = new DBOpenHelper(getContext());
    
    		return false;
    	}
    
    	@Override
    	public Cursor query(Uri uri, String[] projection, String selection,
    			String[] selectionArgs, String sortOrder) {
    		// 查询
    		if (MATCHER.match(uri) == MATCHER_ALL) {
    			SQLiteDatabase db = helper.getReadableDatabase();
    			Cursor cursor = db.query("students", projection, selection,
    					selectionArgs, null, null, sortOrder);
    			return cursor;
    		} else if (MATCHER.match(uri) == MATCHER_ID) {
    			SQLiteDatabase db = helper.getReadableDatabase();
    			long id = ContentUris.parseId(uri);
    			String whereClause;
    			if (selection == null || "".equals(selection)) {
    				whereClause = "_id=" + id;
    			} else {
    				whereClause = selection + " and _id=" + id;
    			}
    			Cursor cursor = db.query("students", projection, whereClause,
    					selectionArgs, null, null, sortOrder);
    			return cursor;
    		} else {
    			throw new IllegalArgumentException("非法的URI:" + uri.toString());
    		}
    	}
    
    	@Override
    	public int update(Uri uri, ContentValues values, String selection,
    			String[] selectionArgs) {
    		if (MATCHER.match(uri) == MATCHER_ID) {
    			SQLiteDatabase db = helper.getReadableDatabase();
    			long id = ContentUris.parseId(uri);
    			String whereClause;
    			if (selection == null || "".equals(selection)) {
    				whereClause = "_id=" + id;
    			} else {
    				whereClause = selection + " and _id=" + id;
    			}
    			int result = db
    					.update("students", values, whereClause, selectionArgs);
    			return result;
    		} else {
    			throw new IllegalArgumentException("非法的URI:" + uri.toString());
    		}
    
    	}
    
    }

    执行时须要先将上一个应用部署到虚拟机中。然后再将获取数据的应用执行,
    通过一个应用获取还有一个应用中的数据:
            其它代码同上:核心代码:
       Uri uri = Uri.parse("content://com.example.lianxi.providers/student/5");//获取一个数值
    Uri uri = Uri.parse("content://com.example.lianxi.providers/student");//获取全部数值


     ContentObserver监听数据的变化
           使用ContentObserver可监听数据变化,当注冊了ContentObserver的URI相应的数据发生变化时。该类中的onChange()
           方法会被回调。
           调用ContentResolver类定义的registerContentObserver()能够注冊ContentObserver。


           注意:ContentObserver的工作原理并非每分每秒的监听相应的数据,仅仅有ContentProvider的增删改查方法必须通知
           了数据发生变化以后。ContentObserver才干知晓数据的变化。


    实例:

    核心代码:

    StudentProvider:

    @Override
    	public int delete(Uri uri, String selection, String[] selectionArgs) {
    		if (MATCHER.match(uri) == MATCHER_ID) {
    			SQLiteDatabase db = helper.getReadableDatabase();
    			long id = ContentUris.parseId(uri);
    			String whereClause;
    			if (selection == null || "".equals(selection)) {
    				whereClause = "_id=" + id;
    			} else {
    				whereClause = selection + " and _id=" + id;
    			}
    			int result = db.delete("students", whereClause, selectionArgs);
    			this.getContext().getContentResolver().notifyChange(uri, null);
    			return result;
    		} else {
    			throw new IllegalArgumentException("非法的URI:" + uri.toString());
    		}
    	}

    MainActivity:

    package com.example.contentresolver;
    
    import android.app.Activity;
    import android.content.ContentResolver;
    import android.content.ContentUris;
    import android.database.ContentObserver;
    import android.database.Cursor;
    import android.net.Uri;
    import android.os.Bundle;
    import android.os.Handler;
    import android.support.v4.widget.SimpleCursorAdapter;
    import android.view.ContextMenu;
    import android.view.Menu;
    import android.view.MenuItem;
    import android.view.View;
    import android.view.ContextMenu.ContextMenuInfo;
    import android.widget.AdapterView.AdapterContextMenuInfo;
    import android.widget.ListView;
    
    public class MainActivity extends Activity {
    
    	private ListView listView;
    	private SimpleCursorAdapter adapter;
    	private Cursor cursor;
        private Uri uri;
        private ContentResolver cr;
    	@Override
    	protected void onCreate(Bundle savedInstanceState) {
    		super.onCreate(savedInstanceState);
    		setContentView(R.layout.activity_main);
    		cr = getContentResolver();
    		uri = Uri.parse("content://com.example.lianxi.providers/student");//获取一个数值
    //		Uri uri = Uri.parse("content://com.example.lianxi.providers/student");//获取全部数值
    		cursor = cr.query(uri, new String[] { "_id", "_name", "_age" },
    				null, null, null);
            ContentObserver observer = new ContentObserver(new Handler()){
            	@Override
            	public void onChange(boolean selfChange) {
            		// TODO Auto-generated method stub
            		cursor.requery();
            		adapter.notifyDataSetChanged();
            		
            		super.onChange(selfChange);
            	}
            };
            cr.registerContentObserver(uri, true, observer);
    		listView = (ListView) findViewById(R.id.lv_student);
    		String[] from = { "_id", "_name", "_age" };
    		int[] to = { R.id.item_id, R.id.item_name, R.id.item_age };
    		adapter = new SimpleCursorAdapter(this, R.layout.student_item, cursor,
    				from, to, 0);
    		listView.setAdapter(adapter);
    		registerForContextMenu(listView);
    		
    
    	}
    	@Override
    	public void onCreateContextMenu(ContextMenu menu, View v,
    			ContextMenuInfo menuInfo) {
    		// TODO Auto-generated method stub
    		AdapterContextMenuInfo info = (AdapterContextMenuInfo)menuInfo;
    		int position = info.position;
    		cursor.moveToPosition(position);
    		String studentName = cursor.getString(cursor.getColumnIndex("_name"));
    		
    		menu.add(Menu.NONE,1,1,"删除"+ studentName );
    		super.onCreateContextMenu(menu, v, menuInfo);
    	}
    	
    	@Override
    	public boolean onContextItemSelected(MenuItem item) {
    		// TODO Auto-generated method stub
    		AdapterContextMenuInfo info = (AdapterContextMenuInfo) item.getMenuInfo();
    		int position = info.position;
    		cursor.moveToPosition(position);
    		long id = cursor.getLong(cursor.getColumnIndex("_id"));
    		
    		Uri deleteUri = ContentUris.withAppendedId(uri, id);
    		cr.delete(deleteUri,null,null);
    		return super.onContextItemSelected(item);
    	}
    }
    

    今天今天2015年最后一天。

    。。



  • 相关阅读:
    圣诞树
    删除临时表并且插入数据
    sql语句中查询用in的时候,按in的顺序来输出
    xmlhelper and excelhelper
    几个小知识点。
    根据页面上记录数和页面大小获取总页数
    SQL语句的疑问
    katie melua the closest thing to crazy
    something about table
    little things
  • 原文地址:https://www.cnblogs.com/yxysuanfa/p/7039808.html
Copyright © 2020-2023  润新知