检索 blob 时 SQLite 数据库中的异常

时间:2021-04-02 10:40:21

标签: android sqlite blob

我创建了一个表订单,以显示购物车项目。当我单击产品详细信息活动中的添加到购物车按钮时,应用程序崩溃并转到上一页。但是,我可以在列表视图中看到购物车项目。

OrderProvider 类:

public class OrderProvider extends ContentProvider {

    // this constant is needed in order to define the path of our modification in the table
    public static final int ORDER=100;

    public DBHelper mhelper;
    public static UriMatcher sUriMatcher = new UriMatcher(UriMatcher.NO_MATCH);

    static {
        sUriMatcher.addURI(OrderContract.CONTENT_AUTHORITY,OrderContract.PATH,ORDER);
    }


    @Override
    public boolean onCreate() {

        mhelper = new DBHelper(getContext());

        return true;
    }


    @Override
    public Cursor query( Uri uri,  String[] projection,  String selection,  String[] selectionArgs, String sortOrder) {


        SQLiteDatabase database = mhelper.getReadableDatabase();
        Cursor cursor;
        int match = sUriMatcher.match(uri);
        switch (match){
            case ORDER:
                cursor = database.query(OrderContract.OrderEntry.TABLE_NAME, projection, selection, selectionArgs, null,null, sortOrder);
                break;

            default:
                throw new IllegalArgumentException("CANT QUERY");
        }

        cursor.setNotificationUri(getContext().getContentResolver(),uri);
        return cursor;

    }


    @Override
    public String getType(Uri uri) {
        return null;
    }


    @Override
    public Uri insert(Uri uri, ContentValues values) {
        int match = sUriMatcher.match(uri);
        switch (match) {
            case ORDER:
                return insertCart(uri, values);

            default:
                throw new IllegalArgumentException("Cant insert data");
        }

    }

    private Uri insertCart(Uri uri, ContentValues values) {

        String name = values.getAsString(OrderContract.OrderEntry.COLUMN_NAME);
        if(name == null){
            throw new IllegalArgumentException("Name is Required");
        }

        String quantity = values.getAsString(OrderContract.OrderEntry.COLUMN_QUANTITY);
        if(quantity == null){
            throw new IllegalArgumentException("Quantity is Required");
        }

        String price = values.getAsString(OrderContract.OrderEntry.COLUMN_PRICE);
        if(price == null){
            throw new IllegalArgumentException("Price is Required");
        }

        byte[] image = values.getAsByteArray(OrderContract.OrderEntry.COLUMN_IMAGE);
        if(image == null){
            throw new IllegalArgumentException("Image is Required"); //shows this error in logcat  
        }

        //insert values into order

        SQLiteDatabase database = mhelper.getWritableDatabase();
        long id = database.insert(OrderContract.OrderEntry.TABLE_NAME, null, values);

        if(id == 0){
            return null;
        }
        getContext().getContentResolver().notifyChange(uri,null);
        return ContentUris.withAppendedId(uri,id);


    }

    @Override
    public int delete(Uri uri, String selection, String[] selectionArgs) {
        //delete data once order is made

        int rowsDeleted;
        SQLiteDatabase database = mhelper.getWritableDatabase();
        int match = sUriMatcher.match(uri);
        switch (match) {
            case ORDER:
                rowsDeleted = database.delete(OrderContract.OrderEntry.TABLE_NAME, selection, selectionArgs);
                break;

            default:
                throw new IllegalArgumentException("Cannot delete");
        }

        if (rowsDeleted!=0) {
            getContext().getContentResolver().notifyChange(uri, null);
        }

        return rowsDeleted;
    }

    @Override
    public int update(Uri uri, ContentValues values, String selection, String[] selectionArgs) {
        return 0;
    }
}

OrderContract.class:

public class OrderContract {

    public OrderContract() {
    }

    //content authority requires package name
    public static final String CONTENT_AUTHORITY = "com.example.myapp";
    public static final Uri BASE_URI = Uri.parse(("content://" +CONTENT_AUTHORITY));
    //same as table name
    public static final String PATH = "orders" ;


    public static abstract class OrderEntry implements BaseColumns{

        public static final Uri CONTENT_URI = Uri.withAppendedPath(BASE_URI,PATH);

        public static final String TABLE_NAME = "orders" ;
        public static final String _ID = BaseColumns._ID ;
        public static final String COLUMN_NAME = "name" ;
        public static final String COLUMN_QUANTITY = "quantity" ;
        public static final String COLUMN_PRICE = "price" ;
        public static final String COLUMN_IMAGE = "image" ;

    }

}

ProductDetails.class:

public class Sofa1 extends AppCompatActivity implements LoaderManager.LoaderCallbacks<Cursor> {


    ImageButton plusquantity,minusquantity;
    ImageView productimage;
    TextView quantitynumber,sofaname,sofaprice,sofadesc,totalamount;
    Button addtocart;
    int quantity;
    int totalprice=0;
    public Uri mcurrentcarturi;
    boolean hasallrequiredvalues = false;
    DBHelper DB;


    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_sofa1);

        if (getSupportActionBar() != null) {
            getSupportActionBar().hide();
        }




        sofaname=(TextView)findViewById(R.id.sofaname);
        sofaprice=(TextView)findViewById(R.id.sofaprice);
        sofadesc=(TextView)findViewById(R.id.sofadesc);
        plusquantity = findViewById(R.id.addquantity);
        minusquantity  = findViewById(R.id.subquantity);
        quantitynumber = findViewById(R.id.quantity);
        addtocart = (Button) findViewById(R.id.addtocart);
        productimage = (ImageView)findViewById(R.id.productimage);



        DB = new DBHelper(Sofa1.this);
        //product - 1
        byte[] bytesImage = DB.getProductImage("SELECT F_Image FROM Furniture WHERE F_Type = 'Sofa';");
        if (bytesImage != null) {

            Bitmap bitmap = convertByteArraytoImage(bytesImage);
            productimage.setImageBitmap(bitmap);

        }
        String Name = DB.getProductNamePrice("SELECT F_Name FROM Furniture WHERE F_Type = 'Sofa';");
        String Price = DB.getProductNamePrice("SELECT F_Price FROM Furniture WHERE F_Type = 'Sofa';");
        String Desc = DB.getProductNamePrice("SELECT F_Description FROM Furniture WHERE F_Type = 'Sofa';");
        sofaname.setText(Name);
        sofaprice.setText(Price);
        sofadesc.setText(Desc);

        plusquantity.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                if(quantity<5){
                    //sofaprice
                    int baseprice= Integer.parseInt(sofaprice.getText().toString());
                    quantity++;
                    displayquantity();
                    totalprice = baseprice * quantity;
                    String setnewprice = (String.valueOf(totalprice));
                    sofaprice.setText(setnewprice);
                }
            }
        });

        minusquantity.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {

                int baseprice=0;
                String Price = DB.getProductNamePrice("SELECT F_Price FROM Furniture WHERE F_Type = 'Sofa';");
                baseprice = Integer.parseInt(Price);
                    if(quantity>1) {
                        quantity--;
                        displayquantity();
                        totalprice = baseprice * quantity;
                        String setnewprice = (String.valueOf(totalprice));
                        sofaprice.setText(setnewprice);
                    }


            }
        });

        addtocart.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                Toast.makeText(Sofa1.this, "Product Added to cart", Toast.LENGTH_SHORT).show();

                SaveCart();
                totalamount = (TextView) findViewById(R.id.total);



            }
        });





    }

    private void SaveCart() {

        String name = sofaname.getText().toString();
        String price = sofaprice.getText().toString();
        String quantity = quantitynumber.getText().toString();
        byte[] bytesImage = convertImageViewToByteArray(productimage);

        ContentValues values = new ContentValues();
        values.put(OrderContract.OrderEntry.COLUMN_NAME,name);
        values.put(OrderContract.OrderEntry.COLUMN_PRICE,price);
        values.put(OrderContract.OrderEntry.COLUMN_QUANTITY,quantity);
        values.put(OrderContract.OrderEntry.COLUMN_IMAGE,bytesImage);

        if(mcurrentcarturi == null){
            Uri newUri = getContentResolver().insert(OrderContract.OrderEntry.CONTENT_URI, values);

            if(newUri == null){
                Toast.makeText(this, "Failed to add to cart", Toast.LENGTH_SHORT).show();
            }else{
                Toast.makeText(this, "Product added to cart", Toast.LENGTH_SHORT).show();
            }

        }

        hasallrequiredvalues = true;

    }

    private void displayquantity() {
        quantitynumber.setText(String.valueOf(quantity));
    }



    @Override
    public @NotNull Loader<Cursor> onCreateLoader(int id, Bundle args) {

        String[] projection = {OrderContract.OrderEntry._ID,
                OrderContract.OrderEntry.COLUMN_NAME,
                OrderContract.OrderEntry.COLUMN_PRICE,
                OrderContract.OrderEntry.COLUMN_QUANTITY,
                OrderContract.OrderEntry.COLUMN_IMAGE};

        return new CursorLoader(this, mcurrentcarturi, projection, null, null, null);
    }

    @Override
    public void onLoadFinished(@NotNull Loader<Cursor> loader, Cursor cursor) {

        if(cursor==null || cursor.getCount() < 1){
            return;
        }

        if(cursor.moveToFirst()){

            int name = cursor.getColumnIndex(OrderContract.OrderEntry.COLUMN_NAME);
            int price = cursor.getColumnIndex(OrderContract.OrderEntry.COLUMN_PRICE);
            int quantity = cursor.getColumnIndex(OrderContract.OrderEntry.COLUMN_QUANTITY);

            String nameofsofa = cursor.getString(name);
            String priceofsofa = cursor.getString(price);
            String quantityofsofa = cursor.getString(quantity);
            byte[] bytesImage = cursor.getBlob(cursor.getColumnIndex(OrderContract.OrderEntry.COLUMN_IMAGE));

            if (bytesImage != null) {

                Bitmap bitmap = convertByteArraytoImage(bytesImage);
                productimage.setImageBitmap(bitmap);

            }
            sofaname.setText(nameofsofa);
            sofaprice.setText(priceofsofa);
            quantitynumber.setText(quantityofsofa);

        }

    }

    @Override
    public void onLoaderReset(@NotNull Loader<Cursor> loader) {

        sofaname.setText("");
        sofaprice.setText("");
        quantitynumber.setText("");
        byte[] bytesImage = DB.getProductImage("SELECT F_Image FROM Furniture WHERE F_Type = 'Sofa';");
        if (bytesImage != null) {

            Bitmap bitmap = convertByteArraytoImage(bytesImage);
            productimage.setImageBitmap(bitmap);

        }


    }

    private Bitmap convertByteArraytoImage (byte[] bytes){
        return BitmapFactory.decodeByteArray(bytes, 0, bytes.length);
    }

    private byte[] convertImageViewToByteArray(ImageView imageView){

        Bitmap bitmap = ((BitmapDrawable) imageView.getDrawable()).getBitmap();
        ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
        bitmap.compress(Bitmap.CompressFormat.JPEG,80,byteArrayOutputStream);
        return byteArrayOutputStream.toByteArray();

    }
}

这是我的日志:

E/AndroidRuntime: FATAL EXCEPTION: main
    Process: com.example.myapp, PID: 12426
    java.lang.IllegalArgumentException: Image is Required
        at com.example.myapp.OrderProvider.insertCart(OrderProvider.java:96)
        at com.example.myapp.OrderProvider.insert(OrderProvider.java:69)
        at android.content.ContentProvider$Transport.insert(ContentProvider.java:313)
        at android.content.ContentResolver.insert(ContentResolver.java:1845)
        at com.example.myapp.Sofa1.SaveCart(Sofa1.java:165)
        at com.example.myapp.Sofa1.access$100(Sofa1.java:42)
        at com.example.myapp.Sofa1$3.onClick(Sofa1.java:138)
        at android.view.View.performClick(View.java:7257)
        at com.google.android.material.button.MaterialButton.performClick(MaterialButton.java:992)
        at android.view.View.performClickInternal(View.java:7213)
        at android.view.View.access$3800(View.java:828)
        at android.view.View$PerformClick.run(View.java:27921)
        at android.os.Handler.handleCallback(Handler.java:883)
        at android.os.Handler.dispatchMessage(Handler.java:100)
        at android.os.Looper.loop(Looper.java:237)
        at android.app.ActivityThread.main(ActivityThread.java:7830)
        at java.lang.reflect.Method.invoke(Native Method)
        at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:492)
        at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1040)
I/Process: Sending signal. PID: 12426 SIG: 9
Disconnected from the target VM, address: 'localhost:50639', transport: 'socket'

2 个答案:

答案 0 :(得分:0)

convertImageViewToByteArray 方法的 ProductDetails 类中,行 bitmap.compress(Bitmap.CompressFormat.JPEG,80,byteArrayOutputStream); 假定转换。但是,如果您查看 bitmap.compress 压缩是不确定的,因此应该检查返回的值并在压缩不起作用时采取适当的措施。

  • 根据退货 boolean true 如果成功压缩到指定的流。

也许使用:-

private byte[] convertImageViewToByteArray(ImageView imageView){

    Bitmap bitmap = ((BitmapDrawable) imageView.getDrawable()).getBitmap();
    ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
    if (!bitmap.compress(Bitmap.CompressFormat.JPEG,80,byteArrayOutputStream) return new byte[]{};
    return byteArrayOutputStream.toByteArray();
}

但是,是否可以接受存储空字节数组需要考虑并可能适当处理。因此,此修复程序可能会解决该问题,但可能只会延迟处理图像(如果有)未压缩的潜在问题。

此外,存储大图像可能是不可能的,随后检索起来非常困难或效率低下。总的来说,任何接近 250kb 的图像。通常建议不要将图像存储在数据库中,而是将图像存储为文件并存储文件的路径。

答案 1 :(得分:0)

嘿兄弟对不起,我认为你必须以错误的方式将数据添加到 SQLite

简单用例 - https://www.javatpoint.com/android-sqlite-tutorial

要将图像存储在 SQLite 数据库中,您必须使用 URI 您可以轻松地重试和存储而不会出现任何问题或崩溃...不要使用 blob 方法兄弟...我个人不推荐它使用blob

解决方案:

在 uri 中存储为 SQLite 中的字符串,如果您想显示图像并将字符串转换为 URI。

Uri 到 String 和 Reverse Machinasim - Converting of Uri to String

相关问题