当前位置: 首页 > 知识库问答 >
问题:

尝试编辑/更新sqlite数据库记录时的未知URI

席弘图
2023-03-14

这里是logcat:

06-24 13:33:04.226 23618-23618/?E/Android Runtime︰致命的例外:主要过程:com.example.saleh.findmypassword,PID:23618java.lang.非法争论例外:未知Uri:content://com.example.saleh.findmypassword.provider/PInfos/1com.example.saleh.findmypassword.PInfoProvider.update(PInfoProvider.java:161)atandroid.content.内容提供者$Transport.update(内容rovider.java:287)在android.content.内容esolver.update(内容esolver.java:1316)在com.example.saleh.findmypassword.编辑活动$1.on点击(编辑ctivity.java:62)在android.view.View.perform点击(View.java:4438)在android.view.查看$PerformClick.run(View. java: 18422)在android. os.Handler. handleCallback(Handler. java: 733)在android. os.在android. os.在android. app.ActivityThread. main(ActivityThread. java: 5001)在java. lang.反射。方法。方法调用(方法. java: 515)在com. android. interal. os。ZygoteInit$method odAndArgsCaller. run(ZygoteInit. java: 785)在com. android. interal. os。在dalvik. system上的ZygoteInit. main(ZygoteInit. java: 601)。NativeStart. main(本机方法)

内容提供商类:

    public class PInfoProvider extends ContentProvider {
    private PInfoDatabase mOpenHelper;

    private static String TAG = PInfoProvider.class.getSimpleName();
    private static final UriMatcher sUriMatcher = buildUriMatcher();

    private static final int PINFOS = 100;
    private static final int PINFOS_ID = 101;

    private static UriMatcher buildUriMatcher(){
        final UriMatcher matcher = new UriMatcher(UriMatcher.NO_MATCH);
        final String authority = PInfoContract.CONTENT_AUTHORITY;
        matcher.addURI(authority, "PInfos", PINFOS);
        matcher.addURI(authority, "Pinfos/*", PINFOS_ID);
        return matcher;
    }
    @Override
    public boolean onCreate() {
        mOpenHelper = new PInfoDatabase(getContext());
        return true;
    }

    private void deleteDatabase(){
        mOpenHelper.close();
        PInfoDatabase.deleteDatabase(getContext());
        mOpenHelper = new PInfoDatabase(getContext());
    }
    @Override
    public Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs, String sortOrder) {
        final SQLiteDatabase db = mOpenHelper.getReadableDatabase();
        final int match = sUriMatcher.match(uri);

        SQLiteQueryBuilder queryBuilder = new SQLiteQueryBuilder();
        queryBuilder.setTables(PInfoDatabase.Tables.PINFOS);

        switch(match){
            case PINFOS:
                //do nothing
                break;
            case PINFOS_ID:
                String id = PInfoContract.PInfos.getPInfoId(uri);
                queryBuilder.appendWhere(BaseColumns._ID + "=" + id);
                break;
            default:
                throw new IllegalArgumentException("Unknown Uri: " + uri);
        }

        Cursor cursor = queryBuilder.query(db, projection, selection, selectionArgs, null, null, sortOrder);
        //projection in content provider means the list of columns you want to return.
        return cursor;

    }

    @Override
    public String getType(Uri uri) {
        final int match = sUriMatcher.match(uri);
        switch(match){
            case PINFOS:
                return PInfoContract.PInfos.CONTENT_TYPE;
            case PINFOS_ID:
                return PInfoContract.PInfos.CONTENT_ITEM_TYPE;
            default:
                throw new IllegalArgumentException("Unknown Uri: " + uri);
        }
    }

    @Override
    public Uri insert(Uri uri, ContentValues values) {
        //ContentValues: is a list of content values of our database such as the email and username. Contains the column names and the values we want to associate to it when we're writing to the database/
        Log.v(TAG, "insert(uri=" + uri + ", values =" + values.toString());

        final SQLiteDatabase db = mOpenHelper.getWritableDatabase();
        final int match = sUriMatcher.match(uri);

        switch(match){
            case PINFOS:             //only using the PInfo and not the ID because it's to insert only.
                long recordID = db.insertOrThrow(PInfoDatabase.Tables.PINFOS, null, values); //inserts a row into the database
                return PInfoContract.PInfos.buildPInfoUri(String.valueOf(recordID));
            default:
                throw new IllegalArgumentException("Unknown Uri: " + uri);
        }
    }

    @Override
    public int delete(Uri uri, String selection, String[] selectionArgs) {
        Log.v(TAG, "delete(uri=" + uri);

        if(uri.equals(PInfoContract.URI_TABLE)){
            deleteDatabase();
            return 0;
            //This will be executed if the user didn't input a valid record id.
            //Base content uri doesn't contain an ID nor a path.
        }
        final SQLiteDatabase db = mOpenHelper.getWritableDatabase();
        final int match = sUriMatcher.match(uri);

        String selectionCriteria = selection;

        switch(match){

            /*
            case PInfo:
                If this was called and didn't "break" it would change all the records in the table.
                We will still leave it out because we added the database deletion code above.
                 break;
             */

            case PINFOS_ID:
                String id = PInfoContract.PInfos.getPInfoId(uri);
                selectionCriteria = BaseColumns._ID + "=" + id
                        + (!TextUtils.isEmpty(selection) ? "AND (" + selection + ")" : "");
                return db.delete(PInfoDatabase.Tables.PINFOS, selectionCriteria, selectionArgs);

            default:
                throw new IllegalArgumentException("Unknown Uri: " + uri);
        }

    }

    @Override
    public int update(Uri uri, ContentValues values, String selection, String[] selectionArgs) {
        Log.v(TAG, "update(uri=" + uri + ", values =" + values.toString());

        final SQLiteDatabase db = mOpenHelper.getWritableDatabase();
        final int match = sUriMatcher.match(uri);

        String selectionCriteria = selection;
        //We set selectionCriteria to equal selection in the case PInfo case was chosen. After all,
        //we still need to record the selection.

        switch(match){
            case PINFOS:
                //do nothing
                //If this was called and didn't "break" it would change all the records in the table.
                break;
            case PINFOS_ID:
                String id = PInfoContract.PInfos.getPInfoId(uri);
                selectionCriteria = BaseColumns._ID + "=" + id
                    + (!TextUtils.isEmpty(selection) ? "AND (" + selection + ")" : "");
                break;

            default:
                throw new IllegalArgumentException("Unknown Uri: " + uri);
        }
        return db.update(PInfoDatabase.Tables.PINFOS, values, selectionCriteria, selectionArgs);
    }
}

编辑活动类:

    public class EditActivity extends FragmentActivity {
        private final String LOG_TAG = EditActivity.class.getSimpleName();
        private TextView mWebsiteTextView, mEmailTextView, mUsernameTextView,   mPasswordTextView;
        private Button mButton;
        private ContentResolver mContentResolver;

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.add_edit); //same layout as the AddActivity class.
        getActionBar().setDisplayHomeAsUpEnabled(true); //returns up one level rather than back to the top level

        mWebsiteTextView = (TextView) findViewById(R.id.pinfoWebsite);
        mEmailTextView = (TextView) findViewById(R.id.pinfoEmail);
        mUsernameTextView = (TextView) findViewById(R.id.pinfoUsername);
        mPasswordTextView = (TextView) findViewById((R.id.pinfoPassword));

        mContentResolver = EditActivity.this.getContentResolver();

        Intent intent = getIntent(); //Getting the intent that was passed to this activity from the PInfoCustomAdapter class
        final String _id = intent.getStringExtra(PInfoContract.PInfoColumns.PINFO_ID);
        String website = intent.getStringExtra(PInfoContract.PInfoColumns.PINFO_WEBSITE);
        String email = intent.getStringExtra(PInfoContract.PInfoColumns.PINFO_EMAIL);
        String username= intent.getStringExtra(PInfoContract.PInfoColumns.PINFO_USERNAME);
        String password = intent.getStringExtra(PInfoContract.PInfoColumns.PINFO_PASSWORD);

        //Now to populate what's on screen:
        mWebsiteTextView.setText(website);
        mEmailTextView.setText(email);
        mUsernameTextView.setText(username);
        mPasswordTextView.setText(password);

        mButton = (Button) findViewById(R.id.saveButton);
        mButton.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                ContentValues values = new ContentValues(); //Content Values Class is used to store a set of values that the ContentResolver can process.
                values.put(PInfoContract.PInfoColumns.PINFO_WEBSITE, mWebsiteTextView.getText().toString()); //.put add values ot the set & .toString() to convert it to the right format
                values.put(PInfoContract.PInfoColumns.PINFO_EMAIL, mEmailTextView.getText().toString());
                values.put(PInfoContract.PInfoColumns.PINFO_USERNAME, mUsernameTextView.getText().toString());
                values.put(PInfoContract.PInfoColumns.PINFO_PASSWORD, mPasswordTextView.getText().toString());

                Uri uri = PInfoContract.PInfos.buildPInfoUri(_id); //To know which record we're dealing with
                int recordsUpdated = mContentResolver.update(uri, values, null, null);
                Log.d(LOG_TAG, "Number of records updated =  " + recordsUpdated);
                Intent intent = new Intent(EditActivity.this, MainActivity.class);
                startActivity(intent);
                finish(); //always use this when the activity's process is finished
            }
        });
    }

    @Override
    public boolean onOptionsItemSelected(MenuItem item) {
        switch (item.getItemId()){
            case android.R.id.home:
                NavUtils.navigateUpFromSameTask(this); //Just allows to navigate back to the parent method. So: when someone presses home it will go back to the kain menu
                break;
        }
        return true;
    }
}

创建uri的类:

public class PInfoContract {
        interface PInfoColumns {
            String PINFO_ID = "_id";
            String PINFO_WEBSITE = "PInfo_Website";
            String PINFO_EMAIL = "PInfo_Email";
            String PINFO_USERNAME = "PInfo_Username";
            String PINFO_PASSWORD = "PInfo_Password";
        }

public static final String CONTENT_AUTHORITY = "com.example.saleh.findmypassword.provider";
    public static final Uri BASE_CONTENT_URI = Uri.parse("content://" + CONTENT_AUTHORITY);

    public static final String PATH_PINFOS = "PInfos";
    public static final Uri URI_TABLE = Uri.parse(BASE_CONTENT_URI.toString() + "/" + PATH_PINFOS);

    public static final String[] TOP_LEVEL_PATHS = {
            PATH_PINFOS
    };

    public static class PInfos implements PInfoColumns, BaseColumns {
        public static final Uri CONTENT_URI =
                BASE_CONTENT_URI.buildUpon().appendEncodedPath(PATH_PINFOS).build();
        public static final String CONTENT_TYPE = "vnd.android.cursor.dir/vnd." + CONTENT_AUTHORITY + ".PInfos";
        public static final String CONTENT_ITEM_TYPE = "vnd.android.cursor.item/vnd." + CONTENT_AUTHORITY + ".PInfos";

        public static Uri buildPInfoUri(String pinfoid) {
            return CONTENT_URI.buildUpon().appendEncodedPath(pinfoid).build();
        }

        public static String getPInfoId(Uri uri) {
            return uri.getPathSegments().get(1);
        }

    }


}

舱单:

<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.example.saleh.findmypassword">

    <permission android:name="com.example.saleh.findmypassword.provider.READWRITE" />

    <uses-permission android:name="com.example.saleh.findmypassword.provider.READWRITE" />
    <application
        android:allowBackup="true"
        android:icon="@mipmap/ic_launcher"
        android:label="@string/app_name"
        android:theme="@android:style/Theme.WithActionBar">
        <activity
            android:name=".MainActivity"
            android:label="Personal Info">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />

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

        <activity
            android:name=".AddActivity"
            android:label="@string/add_pinfo_title"
            android:parentActivityName=".MainActivity"
            android:noHistory="true"/>


        <activity
            android:name=".EditActivity"
            android:label="@string/edit_pinfo_title"
            android:parentActivityName="com.example.saleh.findmypassword.MainActivity"
            android:noHistory="true"/>

        <activity
            android:name=".SearchActivity"
            android:label="@string/search_pinfo_title"
            android:parentActivityName=".MainActivity"
            android:noHistory="true"/>

        <provider
            android:name="com.example.saleh.findmypassword.PInfoProvider"
            android:authorities="com.example.saleh.findmypassword.provider"
            android:exported="true"
            android:readPermission="com.example.saleh.findmypassword.provider.READWRITE"
            android:writePermission="com.example.saleh.findmypassword.provider.READWRITE" />
    </application>

</manifest>

共有1个答案

花博厚
2023-03-14

您的UriMatcher正在匹配任何文本“Pinfos/*”,并且它应该匹配任何数字“Pinfos/#”

文件

 类似资料:
  • 我有一个自定义的项目阅读器,它读取数据另一个阅读器是JDBCursorItemReader(它从数据库中的请求表中读取数据),构建一个特定大小的列表并返回一个项目列表。 我在更新请求状态的方法上使用@transactional(propagation=propagation.requires_ne W)。 我对spring批处理表和应用程序特定的表使用单独的数据源和事务管理器。 我正在使用JDBC

  • 问题内容: 这段代码正在更新薪水为13000的所有记录。 相反,我想将薪水为1300的记录更新为值13000。 您能告诉我我在哪里出错吗? 我正在使用隐式游标访问记录.. 对于每个记录,我正在检查该记录的sal值.. 如果特定记录中的薪水值是1500,我想将其更新为15000。 问题答案: 只要您可以使用一条语句进行更新,就应该这样做,而不要使用循环。这样,您将获得非常巨大的性能提升。或者反之,循

  • 问题内容: 我有一个SQL Server 2008数据库和一个asp.net前端。 当用户当前正在编辑记录但不确定哪种是最好的方法时,我想实现一个锁定。 我的想法是为记录创建一列,并在用户拉出该记录时将其设置为true,这意味着所有其他用户都具有只读访问权限,直到第一个用户完成编辑为止。 但是,如果会话超时并且他/她从不保存/更新记录,该记录将保留为,表示其他人无法对其进行编辑,对吗? 如何实现某

  • 网格视图 网格视图是一个类似数据表的视图,将文档和字段显示为行和列。导航栏可让你快速地切换、插入或删除记录。 添加一条记录 请确保你的光标位于表的第一个空白单元格,然后输入所需的数据。如果你要添加新记录到现有的表,只需简单地点击现有的记录并在导航栏点击 或按 CTRL+N 来得到一个空白显示的记录。 请看记录左侧的选择框。它会由指示当前记录的图形符号 变为指示你正在编辑该记录的图形符号 。 若要保

  • 网格视图 网格视图是一个类似数据表的视图,将文档和字段显示为行和列。导航栏可让你快速地切换、插入或删除记录。 添加一条记录 请确保你的光标位于表的第一个空白单元格,然后输入所需的数据。如果你要添加新记录到现有的表,只需简单地点击现有的记录并在导航栏点击 或按 COMMAND-+ 来得到一个空白显示的记录。 请看记录左侧的选择框。它会由指示当前记录的图形符号 变为指示你正在编辑该记录的图形符号 。

  • 网格视图 网格视图是一个类似数据表的视图,将文档和字段显示为行和列。导航栏可让你快速地切换、插入或删除记录。 添加一条记录 请确保你的光标位于表的第一个空白单元格,然后输入所需的数据。如果你要添加新记录到现有的表,只需简单地点击现有的记录并在导航栏点击 或按 CTRL+N 来得到一个空白显示的记录。 请看记录左侧的选择框。它会由指示当前记录的图形符号 变为指示你正在编辑该记录的图形符号 。 若要保