Я новичок в Android и у меня есть ошибка в моем проекте, я буду благодарен, если какой-либо орган поможет.
У моего приложения есть база данных, которую я сделал с помощью SQLite. я сохраняю изображения в формате BLOB и использую SimpleCurserAdapter для загрузки моих данных, но адаптер не может загрузить изображения и вызывает эту ошибку:
Процесс: com.example.radman.cars, PID: 9861 android. database.sqlite.SQLiteException: неизвестная ошибка (код 0): невозможно преобразовать BLOB в строку в android.database.CursorWindow.nativeGetString (собственный метод) в android.database.CursorWindow.getString (CursorWindow.java:438) в android.database.AbstractWindowedCursor.getString (AbstractWindowedCursor.java:51) в android.widget.SimpleCursorAdapter.bindView (SimpleCursorAdapter.java:150) в android.widget.CursorAdapter.getView (CursorAdapter). widget.AbsListView.obtainView (AbsListView.java:2363) в android.widget.ListView.makeAndAddView (ListView.java:1970) в android.widget.ListView.fillDown (ListView.java:704) в android.widget.ListView.fillromTop(ListView.java:765) в android.widget.ListView.layoutChildren (ListView.java:1744) в android.widget.AbsListView.onLayout (AbsListView.java:2162) в android.view.View.layout (View.java:17637) в android.view.ViewGroup.layout (ViewGroup.java:5575) в android.support.constraint.ConstraintLayout.onLayout (ConstraintLayout.java: 1197) на android.view.View.layout (View.java:17637) на android.view.ViewGroup.layout (ViewGroup.java:5575) на android.widget.FrameLayout.layoutChildren (FrameLayout.java:323)на android.widget.FrameLayout.onLayout (FrameLayout.java:261) на android.view.View.layout (View.java:17637) на android.view.ViewGroup.layout (ViewGroup.java:5575) на com.android. internal.widget.ActionBarOverlayLayout.onLayout (ActionBarOverlayLayout.java:493) в android.view.View.layout (View.java:17637) в android.view.ViewGroup.layout (ViewGroup.java:5575) в android.widget.FrameLayout.layoutChildren (FrameLayout.java:323)на android.widget.FrameLayout.onLayout (FrameLayout.java:261) на com.android.internal.policy.DecorView.onLayout (DecorView.java:726) на android.view.View.layout (View.java:17637) наandroid.view.ViewGroup.layout (ViewGroup.java:5575) в android.view.ViewRootImpl.performLayout (ViewRootImpl.java:2346) в android.view.ViewRootImpl.performTraversals (ViewRootImpl.java:2068l) в android.view.oot.view. .doTraversal (ViewRootImpl.java:1254) в android.view.ViewRootImpl $ TraversalRunnable.run (ViewRootImpl.java:6337) в android.view.Choreographer $ CallbackRecord.run (Choreographer.java:874. and and at. doCallbacks (Choreographer.java:686) в android.view.Choreographer.doFrame (Choreographer.java:621) в android.view.Choreographer $ FrameDisplayEventReceiver.run (Choreographer.java:860) в android.os.Chler.java: 751) на android.os.Handler.dispatchMessage (Handler.java:95) на android.os.Looper.loop (Looper.java:154) на android.app.ActivityThread.main (ActivityThread.java: 6119) на java.lang.reflect.Method.invoke (собственный метод) на com.android.internal.os.ZygoteInit $ MethodAndArgsCaller.run (ZygoteInit.java:886) на com.android.internal.os.ZygoteInit.main(ZygoteInit.java:776) 10-04 20: 24: 09.517 9861-9870 / com.example.radman.cars W / art: приостановка всех потоков заняла: 17.145мс
Я думаю, что ошибкапотому что адаптер не может прочитать двоичное значение, хотя я не уверен.
здесь мои коды:
Мой класс помощника:
public class Connector extends SQLiteOpenHelper {
private static final int DB_VERSION = 1; // Db version
private static final String DB_NAME = "Cars"; // name of the TABLE
private String name;
private String model;
private String color;
private int year;
private int photoR;
//CTOR coz the super class doesn't have any default CTOR
Connector(Context context, int year, int res, String color, String model, String name) {
super(context, DB_NAME, null, DB_VERSION);
this.name = name;
this.model = model;
this.color = color;
this.year = year;
this.photoR = res;
}
public SQLiteDatabase geter() {
return this.getWritableDatabase();
}
// an overrided FUN (if DB doesn't exist create one )
@Override
public void onCreate(SQLiteDatabase db) {
updateDB(db, 0, DB_VERSION);
}
// an overrided FUN (if DB exists update it )
@Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
updateDB(db, 0, DB_VERSION);
}
// a created FUN to check either DB exists or not
// IF yes just update it
// ELSE create
// * although the update feature will come in future *
public void updateDB(SQLiteDatabase db, int oldVersion, int newVersion) {
db.execSQL("CREATE TABLE CARS (_id INTEGER PRIMARY KEY AUTOINCREMENT, "
+ "NAME TEXT, "
+ "MODEL TEXT, "
+ "COLOR TEXT, "
+ "IMAGE_RESOURCE_ID BLOB NOT NULL, "
+ "YEAR INTEGER);");
//insertOBJ(db, this.name, this.model, this.color, this.photoR, this.year);
insertOBJ(db, name, model, color, R.drawable.performance, year);
}
// a created FUN to add the OBJ (Car) to the DB
public static void insertOBJ(SQLiteDatabase db, String name, String model,
String color, int photoId, int productionyear) {
ContentValues car = new ContentValues();
car.put("NAME", name);
car.put("MODEL", model);
car.put("COLOR", color);
car.put("IMAGE_RESOURCE_ID", photoId);
car.put("YEAR", productionyear);
db.insert("CARS", null, car);
}
}
мой домашний код, который предназначен для домашней активности, и он должен загружать и показывать записи из базы данных:
package com.example.radman.cars;
import android.app.Activity;
import android.app.AlertDialog;
import android.app.ListActivity;
import android.content.ContentValues;
import android.content.DialogInterface;
import android.content.Intent;
import android.database.Cursor;
import android.database.SQLException;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteOpenHelper;
import android.graphics.BitmapFactory;
import android.os.Bundle;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.widget.AdapterView;
import android.widget.CursorAdapter;
import android.widget.ImageView;
import android.widget.ListView;
import android.widget.SimpleAdapter;
import android.widget.SimpleCursorAdapter;
import android.widget.Toast;
import javax.crypto.interfaces.PBEKey;
public class Home extends ListActivity {
private SQLiteDatabase db;
private Cursor data;
@Override
protected void onCreate(Bundle savedInstanceState) {
setTheme(R.style.Home);
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_home);
orders();
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
getMenuInflater().inflate(R.menu.menu_main, menu);
return super.onCreateOptionsMenu(menu);
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()) {
case R.id.add: {
Intent intent = new Intent(this, Add.class);
startActivity(intent);
}
}
return super.onOptionsItemSelected(item);
}
@Override
protected void onResume() {
orders();
super.onResume();
}
private void orders() {
// this.deleteDatabase("Cars");
ListView list = getListView();
try {
SQLiteOpenHelper helper = new Connector(this, 0, 0, null, null, null);
db = helper.getReadableDatabase();
data = db.query("CARS", null, null, null, null, null, null);
SimpleCursorAdapter adapter = new SimpleCursorAdapter(this,
R.layout.format
, data, new String[]{"NAME", "YEAR", "MODEL", "IMAGE_RESOURCE_ID"},
new int[]{R.id.nameText, R.id.yearTEXT, R.id.modelTXT, R.id.PICIMG});
list.setAdapter(adapter);
} catch (SQLException e) {
String a = e.getMessage();
Toast.makeText(this, e.getMessage(), Toast.LENGTH_SHORT).show();
}
list.setOnItemClickListener(new AdapterView.OnItemClickListener() {
@Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
}
});
list.setOnItemLongClickListener(new AdapterView.OnItemLongClickListener() {
@Override
public boolean onItemLongClick(AdapterView<?> parent, View view, int position, final long id) {
new AlertDialog.Builder(Home.this).setCancelable(true).setMessage("Do you want to delete or edit ?")
.setNegativeButton("Delete", new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
new AlertDialog.Builder(Home.this).setTitle("Delete ?").setMessage("Are you sure you want to delete it?")
.setPositiveButton("Yes", new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
delete((int) id);
}
}).setNegativeButton("No", new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
}
}).setCancelable(false).show();
}
}).setPositiveButton("Edit", new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
edit((int) id);
}
}).setTitle("Ready for order").show();
return true;
}
});
}
public void delete(int id) {
try {
Connector c = new Connector(this, 0, 0, null, null, null);
SQLiteDatabase db = c.getWritableDatabase();
db.delete("CARS", "_id=?", new String[]{Integer.toString(id)});
Toast.makeText(this, "Deleted successfully !", Toast.LENGTH_SHORT).show();
orders();
} catch (SQLException e) {
Toast.makeText(this, "Failed to delete ! please try later", Toast.LENGTH_SHORT).show();
}
}
public void edit(int id) {
Bundle b = new Bundle();
b.putInt("id", id);
Intent intent = new Intent(this, Edit.class);
intent.putExtra("id", b);
startActivity(intent);
}
}
мой домашний макет:
<?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:theme="@style/Theme.AppCompat.DayNight.NoActionBar">
<ListView
android:id="@android:id/list"
android:layout_width="344dp"
android:layout_height="495dp"
android:layout_marginBottom="8dp"
android:layout_marginLeft="8dp"
android:layout_marginRight="8dp"
android:layout_marginTop="8dp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintHorizontal_bias="0.0"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintVertical_bias="0.984" />
</android.support.constraint.ConstraintLayout>
как я сохранил свои записи:
package com.example.radman.cars;
import android.content.ContentValues;
import android.content.Intent;
import android.database.SQLException;
import android.database.sqlite.SQLiteDatabase;
import android.graphics.drawable.BitmapDrawable;
import android.media.Image;
import android.media.MediaPlayer;
import android.provider.ContactsContract;
import android.provider.MediaStore;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.View;
import android.widget.ArrayAdapter;
import android.widget.ImageView;
import android.widget.Spinner;
import android.widget.TextView;
import android.widget.Toast;
import android.graphics.Bitmap;
import java.io.ByteArrayOutputStream;
import java.util.ArrayList;
import java.util.Objects;
public class Add extends AppCompatActivity {
// private static final int CAMERA_REQUEST = 1888;
// private ImageView imageView;
// private static final int MY_CAMERA_PERMISSION_CODE = 100;
static final int REQUEST_IMAGE_CAPTURE = 1;
public static final int PICK_IMAGE = 1;
@Override
protected void onCreate(Bundle savedInstanceState) {
// getActionBar().setDisplayHomeAsUpEnabled(true);
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_add);
// getActionBar().setDisplayHomeAsUpEnabled(true);
MediaPlayer player = new MediaPlayer();
player.start();
ArrayList<String> items = new ArrayList<>();
for (int i = 1960; i < 2020; i++) {
items.add(Integer.toString(i));
}
Spinner s = (Spinner) findViewById(R.id.spnYear);
ArrayAdapter<String> adapter = new ArrayAdapter<String>(this,
android.R.layout.simple_spinner_item, items);
adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
s.setAdapter(adapter);
}
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
if (requestCode == REQUEST_IMAGE_CAPTURE && resultCode == RESULT_OK) {
Bundle extras = data.getExtras();
Bitmap imageBitmap = (Bitmap) extras.get("data");
ImageView imageView = (ImageView) findViewById(R.id.photoImage);
imageView.setImageBitmap(imageBitmap);
} else if (requestCode == PICK_IMAGE) {
Bundle extras = data.getExtras();
Bitmap imageBitmap = (Bitmap) extras.get("data");
ImageView imageView = (ImageView) findViewById(R.id.photoImage);
imageView.setImageBitmap(imageBitmap);
}
}
private void dispatchTakePictureIntent() {
Intent takePictureIntent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
if (takePictureIntent.resolveActivity(getPackageManager()) != null) {
startActivityForResult(takePictureIntent, REQUEST_IMAGE_CAPTURE);
}
}
public void btnAdd(View view) {
try {
TextView[] texts = new TextView[2];
texts[0] = (TextView) findViewById(R.id.nameText);
texts[1] = (TextView) findViewById(R.id.mdlText);
Spinner a = (Spinner) findViewById(R.id.spnYear);
String year = a.getSelectedItem().toString();
a = (Spinner) findViewById(R.id.spnColor);
String color = a.getSelectedItem().toString();
ImageView image = (ImageView)findViewById(R.id.photoImage);
BitmapDrawable drawable = (BitmapDrawable) image.getDrawable();
Bitmap bitmap = drawable.getBitmap();
ByteArrayOutputStream out = new ByteArrayOutputStream();
bitmap.compress(Bitmap.CompressFormat.PNG, 100, out);
byte[] buffer=out.toByteArray();
Connector connection = new Connector(this, 0, 0, null, null, null);
SQLiteDatabase db = connection.getWritableDatabase();
ContentValues car = new ContentValues();
String n = texts[0].getText().toString();
car.put("NAME", n);
car.put("MODEL", texts[1].getText().toString());
car.put("COLOR", color);
car.put("IMAGE_RESOURCE_ID",buffer /*R.id.photoImage*/);
car.put("YEAR", Integer.parseInt(year));
db.insert("CARS", null, car);
Toast.makeText(this, "Saved Successfully !", Toast.LENGTH_SHORT).show();
} catch (SQLException e) {
Toast.makeText(this, "Database unable !", Toast.LENGTH_SHORT).show();
}
Intent intent = new Intent(this, Home.class);
startActivity(intent);
finish();
}
public void btnTake(View view) {
dispatchTakePictureIntent();
}
public void btnGal(View view) {
Intent intent = new Intent();
intent.setType("image/*");
intent.setAction(Intent.ACTION_GET_CONTENT);
startActivityForResult(Intent.createChooser(intent, "Select Picture"), PICK_IMAGE);
}
}
и мой макет, который используется в качестве макета для просмотра списка:
<?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="100dp">
<TextView
android:id="@+id/modelTXT"
android:layout_width="189dp"
android:layout_height="32dp"
android:layout_marginBottom="8dp"
android:layout_marginLeft="8dp"
android:layout_marginRight="67dp"
android:layout_marginTop="8dp"
android:text="MODEL"
android:textAlignment="inherit"
android:textColor="@android:color/black"
android:textSize="18sp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintHorizontal_bias="0.0"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintVertical_bias="1.0" />
<TextView
android:id="@+id/yearTEXT"
android:layout_width="60dp"
android:layout_height="33dp"
android:layout_marginBottom="8dp"
android:layout_marginLeft="8dp"
android:layout_marginRight="8dp"
android:layout_marginTop="8dp"
android:text="2020"
android:textAlignment="center"
android:textColor="@android:color/black"
android:textSize="20sp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintVertical_bias="0.0" />
<TextView
android:id="@+id/nameText"
android:layout_width="132dp"
android:layout_height="34dp"
android:layout_marginBottom="8dp"
android:layout_marginLeft="8dp"
android:layout_marginRight="8dp"
android:layout_marginTop="8dp"
android:text="NAME"
android:textAlignment="inherit"
android:textColor="@android:color/black"
android:textSize="18sp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintHorizontal_bias="0.0"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintVertical_bias="0.0" />
<ImageView
android:id="@+id/PICIMG"
android:layout_width="134dp"
android:layout_height="95dp"
android:layout_marginBottom="8dp"
android:layout_marginTop="8dp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintHorizontal_bias="0.976"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintVertical_bias="0.454"
app:srcCompat="@color/white" />
</android.support.constraint.ConstraintLayout>
Я будубудь очень благодарен, если кто-нибудь поможет.
в продвинутом спасибо.