I want to build a File Manager.I get list of all files using ContentResolver.For example I get all audio file in this way:
private void getMusic(){
ContentResolver contentResolver=getContentResolver();
Uri songUri= MediaStore.Audio.Media.EXTERNAL_CONTENT_URI;
Cursor songCursor=contentResolver.query(songUri,null,null,null,null);
if(songCursor!=null && songCursor.moveToFirst()){
Log.e(TAG,"if :");
int songTitle=songCursor.getColumnIndex(MediaStore.Audio.Media.TITLE);
int songPath=songCursor.getColumnIndex(MediaStore.Audio.Media.DATA);
do{
String currentTitle=songCursor.getString(songTitle);
Uri currentPath=Uri.parse(songCursor.getString(songPath));
models.add(new model(currentTitle,currentPath));
adapter.notifyDataSetChanged();
}while (songCursor.moveToNext());
}
}
I write this method for deleting file, but didn't work for me.I also get WRITE and READ external permission from user.
private void deleteItem(int position){
File fdelete = new File(models.get(position).getPath().toString());
if (fdelete.exists()) {
boolean flag=fdelete.delete();
if (flag) {
models.remove(models.get(position));
adapter.notifyDataSetChanged();
disableSelectionMode();
Toast.makeText(this,"File successfully deleted.",Toast.LENGTH_SHORT).show();
} else {
disableSelectionMode();
Toast.makeText(this,"File did not deleted!",Toast.LENGTH_SHORT).show();
}
}
}
And this is my model:
public class model {
private int id;
private String title;
private Uri path;
public model(String title, Uri path) {
this.title = title;
this.path = path;
}
public String getTitle() {
return title;
}
public void setTitle(String title) {
this.title = title;
}
public Uri getPath() {
return path;
}
public void setPath(Uri path) {
this.path = path;
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
}
Finally I find the solution.I should deleted file using ContentResolver. I done it this way:
private void deleteItem(model item){
switch (type){
case AUDIOS:{
int b=getContentResolver().delete(
MediaStore.Audio.Media.EXTERNAL_CONTENT_URI,
MediaStore.MediaColumns.DATA + "='" + item.getPath().getPath() + "'", null
);
Log.e(TAG,"b: "+b);
break;
}
case IMAGES:{
int b=getContentResolver().delete(
MediaStore.Images.Media.EXTERNAL_CONTENT_URI,
MediaStore.MediaColumns.DATA + "='" + item.getPath().getPath() + "'", null
);
Log.e(TAG,"b: "+b);
break;
}
case VIDEOS:{
int b=getContentResolver().delete(
MediaStore.Video.Media.EXTERNAL_CONTENT_URI,
MediaStore.MediaColumns.DATA + "='" + item.getPath().getPath() + "'", null
);
Log.e(TAG,"b: "+b);
break;
}
case COMPRESSED:
case APPS:
case DOCUMENTS :{
int bex=getContentResolver().delete(
MediaStore.Files.getContentUri("external"),
MediaStore.MediaColumns.DATA + "='" + item.getPath().getPath() + "'", null
);
int bin=getContentResolver().delete(
MediaStore.Files.getContentUri("internal"),
MediaStore.MediaColumns.DATA + "='" + item.getPath().getPath() + "'", null
);
Log.e(TAG,"bex: "+bex);
Log.e(TAG,"bin: "+bin);
break;
}
}
}
Related
I am new to Android Studio and I am trying to create an Inventory App that allows users to create their own inventory items. I am using SQlite database to do this. I've created my DBHelper class and Item class that stores results.
However, I am unsure how to continue this in my DisplayInventory class (MainActivity) I've written in some FIXME comments to help show where I am talking about.
DisplayInventory class
// TESTING SQLite CODE HERE
public void insertItem(int position) {
//FIXME: This is where I need to ADD items to the database
// inventoryDB.addItem();
mInventoryItemList.add(position, new InventoryItem(R.drawable.ic_delete, "Tap to Edit", "Items: ", (android.widget.Button) Button, (android.widget.Button) Button));
mAdapter.notifyItemInserted(position);
}
public void removeItem(int position) {
// FIXME: This is where I DELETE items from database
// inventoryDB.deleteItem(); <== This method needs to be written in InventoryDBHelper class
mInventoryItemList.remove(position);
mAdapter.notifyItemRemoved(position);
}
public void createExampleList() {
mInventoryItemList = new ArrayList<>();
// get all items from the database
Item[] items = inventoryDB.getAllItems();
// loop through all items to build the array list
for (int i = 0; i < items.length; ++i){
// FIXME: this is where I need to build my ArrayList based on the contents of the DB
// for new users this will be empty. However, as they add items then the database
// will be populated and this will return data the next time.
}
}
//TESTING CODE ENDS HERE
InventoryDBHelper
public class InventoryDBHelper extends SQLiteOpenHelper {
private Context context;
private static final String DATABASE_NAME = "InventoryList.db";
private static final int DATABASE_VERSION = 1;
private static final String TABLE_NAME = "my_inventory";
private static final String COLUMN_ID = "_id";
private static final String COLUMN_TITLE = "item_name";
private static final String COLUMN_OWNER = "item_owner";
private static final String COLUMN_ITEMNUMBER = "number_items";
public InventoryDBHelper(Context context) {
super(context, DATABASE_NAME, null, DATABASE_VERSION);
this.context = context;
}
#Override
public void onCreate(SQLiteDatabase sqLiteDatabase) {
String query = "CREATE TABLE " + TABLE_NAME +
" (" + COLUMN_ID + " INTEGER PRIMARY KEY AUTOINCREMENT," +
COLUMN_TITLE + " TEXT, " +
COLUMN_OWNER + " TEXT, " +
COLUMN_ITEMNUMBER + " INTEGER);";
sqLiteDatabase.execSQL(query);
}
#Override
public void onUpgrade(SQLiteDatabase sqLiteDatabase, int i, int i1) {
sqLiteDatabase.execSQL("DROP TABLE IF EXISTS " + TABLE_NAME);
onCreate(sqLiteDatabase);
}
void addItem(String title, String owner, int numItem) {
SQLiteDatabase db = this.getWritableDatabase();
ContentValues cv = new ContentValues();
cv.put(COLUMN_TITLE, title);
cv.put(COLUMN_OWNER, owner);
cv.put(COLUMN_ITEMNUMBER, numItem);
long result = db.insert(TABLE_NAME, null, cv);
if(result == -1) {
Toast.makeText(context, "FAILED", Toast.LENGTH_SHORT).show();
}
else {
Toast.makeText(context, "Added Successful", Toast.LENGTH_SHORT).show();
}
}
public Item[] getAllItems(){
// list of items to return
Item[] returnItems;
// initialize a readable database connection
SQLiteDatabase db = this.getReadableDatabase();
String query = "SELECT " +
COLUMN_ID + "," +
COLUMN_TITLE + "," +
COLUMN_OWNER + "," +
COLUMN_ITEMNUMBER +
" FROM " + TABLE_NAME + ";";
Cursor cursor = db.rawQuery(query, null);
returnItems = unpackRecordData(cursor);
cursor.close();
return returnItems;
}
private Item[] unpackRecordData(Cursor cursor){
Item[] items = new Item[cursor.getCount()];
int i = 0;
while (cursor.moveToNext()){
Item item = new Item(
// Item.id
cursor.getInt(
cursor.getColumnIndexOrThrow(COLUMN_ID)
),
// Item.title
cursor.getString(
cursor.getColumnIndexOrThrow(COLUMN_TITLE)
),
// Item.owner
cursor.getString(
cursor.getColumnIndexOrThrow(COLUMN_OWNER)
),
// Item.itemNumber
cursor.getInt(
cursor.getColumnIndexOrThrow(COLUMN_ITEMNUMBER)
)
);
// add Item to the list of items
items[i] = item;
}
return items;
}
}
Item Class
public class Item {
// Item Database columns to properties
private int id;
private String title;
private String owner;
private int itemNumber;
// class constructor
public Item(int id, String title, String owner, int itemNumber){
this.id = id;
this.title = title;
this.owner = owner;
this.itemNumber = itemNumber;
}
// getters and setters
public void setId(int id){
this.id = id;
}
public int getId(){
return this.id;
}
public void setTitle(String title){
this.title = title;
}
public String getTitle(){
return this.title;
}
public void setOwner(String owner){
this.owner = owner;
}
public String getOwner(){
return this.owner;
}
public void setItemNumber(int itemNumber){
this.itemNumber = itemNumber;
}
public int getItemNumber(){
return this.itemNumber;
}
}
Here's an example that shows all three types of actions being undertake. It's based upon your code and has some comments to explain suggested changes, additions (commented out) and removal of code.
First InventoryDBHelper
public class InventoryDBHelper extends SQLiteOpenHelper {
private Context context;
private static final String DATABASE_NAME = "InventoryList.db";
private static final int DATABASE_VERSION = 1;
private SQLiteDatabase db; //<<<<<<<< ADDED
/*
CHANGED to public (can be useful)
*/
public static final String TABLE_NAME = "my_inventory";
public static final String COLUMN_ID = "_id";
public static final String COLUMN_TITLE = "item_name";
public static final String COLUMN_OWNER = "item_owner";
public static final String COLUMN_ITEMNUMBER = "number_items";
private static volatile InventoryDBHelper instance;
private InventoryDBHelper(Context context) { //<<<<<<<<<< CHANGED TO PRIVATE
super(context, DATABASE_NAME, null, DATABASE_VERSION);
db = this.getWritableDatabase(); // Instantiates db variable that has full scope
this.context = context;
}
/*
ADDED so a singleton is used
*/
public static InventoryDBHelper getInstance(Context context) {
if (instance == null) {
instance = new InventoryDBHelper(context);
}
return instance;
}
#Override
public void onCreate(SQLiteDatabase sqLiteDatabase) {
String query = "CREATE TABLE " + TABLE_NAME +
" (" + COLUMN_ID + " INTEGER PRIMARY KEY," + //" INTEGER PRIMARY KEY AUTOINCREMENT," <<<<<<<<<< NO NEED FOR AUTOINCREMENT (has overheads)
COLUMN_TITLE + " TEXT, " +
COLUMN_OWNER + " TEXT, " +
COLUMN_ITEMNUMBER + " INTEGER);";
sqLiteDatabase.execSQL(query);
}
#Override
public void onUpgrade(SQLiteDatabase sqLiteDatabase, int i, int i1) {
sqLiteDatabase.execSQL("DROP TABLE IF EXISTS " + TABLE_NAME);
onCreate(sqLiteDatabase);
}
long addItem(String title, String owner, int numItem) { //<<<<<<<<<< CHANGED so result can be returned
// SQLiteDatabase db = this.getWritableDatabase(); //<<<<<<<<<< NOT NEEDED with db as class variable
ContentValues cv = new ContentValues();
cv.put(COLUMN_TITLE, title);
cv.put(COLUMN_OWNER, owner);
cv.put(COLUMN_ITEMNUMBER, numItem);
long result = db.insert(TABLE_NAME, null, cv);
if(result == -1) {
Toast.makeText(context, "FAILED", Toast.LENGTH_SHORT).show();
}
else {
Toast.makeText(context, "Added Successful", Toast.LENGTH_SHORT).show();
}
return result; //<<<<<<<< ADDED might as well return the result
}
/*
ADDED so you can add from a passed item
*/
long addItem(Item item) {
return addItem(item.getTitle(),item.getOwner(),item.getItemNumber());
}
public Item[] getAllItems(){
// list of items to return
Item[] returnItems;
// initialize a readable database connection
//SQLiteDatabase db = this.getReadableDatabase(); //<<<<<<<<<< NOT NEEDED HERE
// PS getReadable gets a writeable database in most situations
/* NOT NEEDED HERE
String query = "SELECT " +
COLUMN_ID + "," +
COLUMN_TITLE + "," +
COLUMN_OWNER + "," +
COLUMN_ITEMNUMBER +
" FROM " + TABLE_NAME + ";";
*/
// ADDED use the convienence query method equivalent to SELECT * FROM my_inventory (SQL is built for you)
Cursor cursor = db.query(TABLE_NAME,null,null,null,null,null,null);
//Cursor cursor = db.rawQuery(query, null);
returnItems = unpackRecordData(cursor);
cursor.close();
return returnItems;
}
/*
ADDED to remove an item from
*/
long removeItem(long itemId) {
return db.delete(TABLE_NAME,COLUMN_ID+"=?",new String[]{String.valueOf(itemId)});
}
/*
ADDED to allow removal of an Item via Item object
*/
long removeItem(Item item) {
return removeItem(item.getId());
}
private Item[] unpackRecordData(Cursor cursor){
Item[] items = new Item[cursor.getCount()];
int i = 0;
while (cursor.moveToNext()){
Item item = new Item(
// Item.id
cursor.getInt(
cursor.getColumnIndexOrThrow(COLUMN_ID)
),
// Item.title
cursor.getString(
cursor.getColumnIndexOrThrow(COLUMN_TITLE)
),
// Item.owner
cursor.getString(
cursor.getColumnIndexOrThrow(COLUMN_OWNER)
),
// Item.itemNumber
cursor.getInt(
cursor.getColumnIndexOrThrow(COLUMN_ITEMNUMBER)
)
);
// add Item to the list of items
items[i++] = item; //ERROR FIXED was i so i was always 0 not 0 1 2 etc
}
return items;
}
}
see AUTOINCREMENT for further reason why not to use AUTOINCREMENT
Item has not been changed (although I would suggest using long instead of int for id)
SQLite rowid (your id columns is an alias of rowid) can be 64-bit signed integer (too large for int).
The examples of Adding, Extracting and Removal of Items from the Database is as per :-
public class MainActivity extends AppCompatActivity {
InventoryDBHelper inventoryDBHelper; //<<<<<<<<< Want to use the Database in this activity
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
inventoryDBHelper = InventoryDBHelper.getInstance(this); // Gets an instance of the Database
//EXAMPLE Examples of Adding Items
inventoryDBHelper.addItem("MyItem","Fred",1);
inventoryDBHelper.addItem(new Item(-1000 /* irrelevant when adding*/,"Another Item","Mary",2));
//EXAMPLE Get a list of all Items
Item[] items = inventoryDBHelper.getAllItems();
//EXAMPLE Remove all Items
for(Item i: items) {
Log.d("INVENTRYINFO","Attempting to remove Item " + i.getTitle());
if (inventoryDBHelper.removeItem(i) > 0) {
Toast.makeText(this,"Item " + i.getTitle() + " deleted",Toast.LENGTH_LONG).show();
} else {
Toast.makeText(this,"Item " + i.getTitle() + " NOT DELETED",Toast.LENGTH_LONG).show();
}
// could use inventoryDBHelper.removeItem(i.getId()); //instead
}
}
}
You just need to adapt this for your needs.
The above is a working example (designed to be run once) it Adds 2 Items, Extracts them as an array of Items and then uses that list to Remove them all.
With a breakpoint at the for each loop that removes the items the following can be seen :-
i.e. the 2 Items have been added and extracted
After the proceeding (after the items have all been removed) then the Log contains :-
D/INVENTRYINFO: Attempting to remove Item MyItem
D/INVENTRYINFO: Attempting to remove Item Another Item
I am facing with a problem which happens only when I add new drawable.
I have a parsed xml to Fragment the icon is set like int.
If I add new drawable then it chooses random drawables to show the icons for the parsed xml.
I have an Adapter for the RecyclerListView.
A Pojo class and DB which extends SQLiteOpenHelper.
If I clear the cache and Storage then it back to normal,
or if I delete the new added drawable it returns back to normally.
Can someone help me to know why it is affecting to change the icons.
I have tried to clean project and rebuild the same.
Invalidate cache and restart but still the same.
Below you can find the code and below the code two pictures of the problem.
public class MyAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> {
private static final int ITEM_TYPE_ONE = 0;
private static final int ITEM_TYPE_TWO = 1;
private final Handler handler = new Handler();
private final ArrayList<Bookmark> arrayList;
private final String BASE_URL = "https://besticon-demo.herokuapp.com/icon?url=";
private final Context context;
public MyAdapter(Context context, ArrayList<Bookmark> arrayList) {
this.context = context;
this.arrayList = arrayList;
}
#NonNull
#Override
public RecyclerView.ViewHolder onCreateViewHolder(#NonNull ViewGroup parent, int viewType) {
View view = null;
if (viewType == ITEM_TYPE_ONE) {
view = LayoutInflater.from(context).inflate(R.layout.grid_item, parent, false);
return new ViewHolder(view);
} else if (viewType == ITEM_TYPE_TWO) {
view = LayoutInflater.from(context).inflate(R.layout.add_bookmark, parent, false);
return new ButtonViewHolder(view);
} else {
return null;
}
}
public void onBindViewHolder(#NonNull RecyclerView.ViewHolder holder, final int position) {
final int itemType = getItemViewType(position);
final Bookmark bookmark = this.arrayList.get(position);
if (itemType == ITEM_TYPE_ONE) {
final ViewHolder viewHolder = (ViewHolder) holder;
RequestOptions requestOptions = new RequestOptions();
BookmarkDB bookmarkDB = new BookmarkDB(context);
String imageUrl = BASE_URL + arrayList.get(position).getSearchUrl() + "&size=32";
int resID = context.getResources().getIdentifier(String.valueOf(arrayList.get(position).getIcon()), "drawable", context.getPackageName());
if (resID == 0) {
Glide.with(context)
.load(imageUrl)
.apply(requestOptions
.placeholder(R.drawable.default_favicon)
.diskCacheStrategy(DiskCacheStrategy.AUTOMATIC)
.fitCenter())
.into(viewHolder.tvIcon);
} else {
viewHolder.tvIcon.setImageResource(resID);
String imageName = context.getResources().getResourceName(resID);
Log.d("getIcons", imageName); // This is the log.
} else if (itemType == ITEM_TYPE_TWO) {
ButtonViewHolder buttonViewHolder = (ButtonViewHolder) holder;
buttonViewHolder.imgButton.setImageResource(arrayList.get(position).getIcon());
}
}
class ViewHolder extends RecyclerView.ViewHolder {
final ImageView tvIcon;
ViewHolder(#NonNull final View itemView) {
super(itemView);
tvIcon = itemView.findViewById(R.id.image_view);
}
}
The Bookmark.db
public class BookmarkDB extends SQLiteOpenHelper {
private static final String DBNAME = "bookmarks.db"; // The name of the database file
private static final int DBVERSION = 1; // The Database version
public static final String TBL_BOOKMARK = "bookmark";
private static final String COL_ID = BaseColumns._ID; // equates to _id
private static final String COl_NAME = "name";
private static final String COl_HIDDEN = "hidden";
private static final String COL_ICON = "icon";
private static final String COL_NATIVEURL = "nativeurl";
private static final String COL_SEARCHURL = "searchurl";
private final SQLiteDatabase mDB;
Context mContext;
public BookmarkDB(Context context) {
super(context, DBNAME, null, DBVERSION);
mDB = this.getWritableDatabase();
}
#Override
public void onCreate(SQLiteDatabase db) {
// The SQL to be used to create the table
String crt_bookmark_tbl_sql = "CREATE TABLE IF NOT EXISTS " + TBL_BOOKMARK + "(" +
COL_ID + " INTEGER PRIMARY KEY AUTOINCREMENT, " +
COl_NAME + " TEXT, " +
COl_HIDDEN + " INTEGER, " +
COL_ICON + " TEXT, " +
COL_NATIVEURL + " TEXT," +
COL_SEARCHURL + " TEXT" +
")";
db.execSQL(crt_bookmark_tbl_sql); // CREATE THE TABLE
}
#Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
db.execSQL("DROP IF TABLE EXISTS " + DBNAME);
onCreate(db);
}
public void updateName(String newName, int id, String oldName) {
SQLiteDatabase db = this.getWritableDatabase();
String query = "UPDATE " + TBL_BOOKMARK + " SET " + COl_NAME +
" = '" + newName + "' WHERE " + COL_ID + " = '" + id + "'" +
" AND " + COl_NAME + " = '" + oldName + "'";
db.execSQL(query);
}
public void addBookmark(long id, String name, boolean hidden, String icon, String nativeurl, String searchurl) {
ContentValues cv = new ContentValues();
cv.put(COl_HIDDEN, hidden);
cv.put(COl_NAME, name);
cv.put(COL_ICON, icon);
cv.put(COL_NATIVEURL, nativeurl);
cv.put(COL_SEARCHURL, searchurl);
mDB.insert(TBL_BOOKMARK, null, cv);
// uses the convenience insert method that builds the SQL
}
public ArrayList<Bookmark> getAllBookmarks() {
ArrayList<Bookmark> rv = new ArrayList<>();
Cursor csr = mDB.query(TBL_BOOKMARK, null, null, null, null, null, null);
while (csr.moveToNext()) {
Bookmark b = new Bookmark();
b.setId(csr.getString(csr.getColumnIndex(COL_ID)));
int Icon = csr.getInt(csr.getColumnIndex(COL_ICON));
String name = csr.getString(csr.getColumnIndex(COl_NAME));
String searchUrl = csr.getString(csr.getColumnIndex(COL_SEARCHURL));
b.setIcon(Icon);
b.setName(name);
b.setSearchUrl(searchUrl);
b.setViewType(csr.getInt(csr.getColumnIndex(COl_NAME)));
b.setNativeUrl(csr.getString(csr.getColumnIndex(COL_NATIVEURL)));
rv.add(b);
}
return rv;
}
}
This is the .XML file.
<?xml version="1.0" encoding="utf-8"?>
<Bookmarks>
<Bookmark name="Bing"
hidden="true"
icon="bing"
id="0"
nativeUrl=""
searchUrl="https://www.bing.com" />
<Bookmark
name="Google"
hidden="true"
icon="google"
id="1"
nativeUrl=""
searchUrl="https://www.google.com" />
<Bookmark
name="Youtube"
hidden="false"
icon="youtube"
id="2"
nativeUrl="youtube://"
searchUrl="https://m.youtube.com" />
<Bookmark
name="Facebook"
hidden="false"
icon="facebook"
id="3"
nativeUrl="facebook://"
searchUrl="https://m.facebook.com" />
<Bookmark
name="Twitter"
hidden="false"
icon="twitter"
id="4"
nativeUrl=""
searchUrl="https://mobile.twitter.com/" />
</Bookmarks>
Fragment of RecyclerView
public class FragmentBookmark extends Fragment {
private final ArrayList<Bookmark> arrayList = new ArrayList<>();
private MyAdapter myAdapter;
private View paramView;
private RecyclerView myRecyclerView;
private BookmarkDB mDB;
private Context mContext;
#Override
public void onAttach(Context context) {
super.onAttach(context);
mContext = context;
mDB = new BookmarkDB(mContext);
mDB.getAllBookmarks();
buildBookmarkArrayListfromDB();
loadBookMarksFromXML();
}
#Nullable
public View onCreateView(LayoutInflater inflater, #Nullable ViewGroup container, #Nullable Bundle savedInstanceState) {
paramView = inflater.inflate(R.layout.bookmark, container, false);
myRecyclerView = paramView.findViewById(R.id.myRecyclerView);
// myRecyclerView.setLayoutManager(new LinearLayoutManager(mContext));
myRecyclerView.setLayoutManager(new GridLayoutManager(mContext, 4));
myRecyclerView.setHasFixedSize(true);
myAdapter = new MyAdapter(mContext, arrayList);
myRecyclerView.setAdapter(myAdapter);
myAdapter.notifyDataSetChanged();
Bookmark bookmark = new Bookmark();
bookmark.setViewType(1);
bookmark.setIcon(R.drawable.add_new_bookmark_icon);
arrayList.add(bookmark);
((MainActivity) getActivity()).setFragmentBookmarkListener(new MainActivity.FragmentBookmarkListener() {
#Override
public void onRefresh() {
assert getFragmentManager() != null;
FragmentTransaction ft = getFragmentManager().beginTransaction();
ft.detach(FragmentBookmark.this).attach(FragmentBookmark.this).commit();
}
});
return paramView;
}
private void loadBookMarksFromXML() {
// MAY WISH TO ONLY DO THIS ONCE as bookmarks would be loaded OTHERWISE DELETE LINE BELOW
if (DatabaseUtils.queryNumEntries(mDB.getWritableDatabase(), BookmarkDB.TBL_BOOKMARK) > 0)
return;
try {
XmlResourceParser xpp = getResources().getXml(R.xml.bookmarks);
while (xpp.getEventType() != XmlPullParser.END_DOCUMENT) {
if (xpp.getEventType() == XmlPullParser.START_TAG) {
if (xpp.getName().equals("Bookmark")) {
Bookmark bookmark = new Bookmark();
bookmark.setName(xpp.getAttributeValue(null, "name"));
bookmark.setSearchUrl(xpp.getAttributeValue(null, "searchUrl"));
bookmark.setNativeUrl(xpp.getAttributeValue(null, "nativeUrl"));
bookmark.setId(xpp.getAttributeValue(null, "id"));
int drawableResourceId = getResources().getIdentifier(xpp.getAttributeValue(null, "icon"), "drawable", mContext.getPackageName());
bookmark.setIcon(drawableResourceId);
bookmark.setViewType(0);
if (bookmark.getId() == null) {
bookmark.setId("1");
}
mDB.addBookmark(
Long.valueOf(bookmark.getId()),
bookmark.getName(),
bookmark.getViewType() > 0,
String.valueOf(bookmark.getIcon()),
bookmark.getNativeUrl(),
bookmark.getSearchUrl()
);
}
}
xpp.next();
}
} catch (XmlPullParserException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
private void buildBookmarkArrayListfromDB() {
arrayList.clear();
arrayList.addAll(mDB.getAllBookmarks());
Bookmark bookmark = new Bookmark();
bookmark.setViewType(1);
bookmark.setIcon(R.drawable.add_new_bookmark_icon);
arrayList.add(bookmark);
}
This is the Pojo.class
public class Bookmark implements Parcelable, Comparable, Comparator<Bookmark> {
public static final Creator<Bookmark> CREATOR = new Creator<Bookmark>() {
#Override
public Bookmark createFromParcel(Parcel in) {
return new Bookmark(in);
}
#Override
public Bookmark[] newArray(int size) {
return new Bookmark[size];
}
};
private String name;
private String id;
private String nativeUrl;
private String searchUrl;
private String hidden;
private long db_id;
private int icon;
private int viewType;
private Bookmark(Parcel in) {
name = in.readString();
id = in.readString();
nativeUrl = in.readString();
searchUrl = in.readString();
db_id = in.readLong();
icon = in.readInt();
viewType = in.readInt();
hidden = in.readString();
}
public Bookmark() {
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getIcon() {
return icon;
}
public void setIcon(int icon) {
this.icon = icon;
}
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
this.db_id = Integer.parseInt(id);
}
public String getNativeUrl() {
return nativeUrl;
}
public void setNativeUrl(String nativeUrl) {
this.nativeUrl = nativeUrl;
}
public String getSearchUrl() {
return searchUrl;
}
public void setSearchUrl(String searchUrl) {
this.searchUrl = searchUrl;
}
public int getViewType() {
return viewType;
}
public void setViewType(int viewType) {
this.viewType = viewType;
}
public String getHidden() {
return hidden;
}
public void setHidden(String hidden) {
this.hidden = hidden;
}
#Override
public String toString() {
return "Bookmark{" +
"name='" + name + '\'' +
", id='" + id + '\'' +
", nativeUrl='" + nativeUrl + '\'' +
", searchUrl='" + searchUrl + '\'' +
", hidden='" + hidden + '\'' +
", db_id=" + db_id +
", icon=" + icon +
", viewType=" + viewType +
'}';
}
#Override
public int compareTo(Object o) {
return 0;
}
#Override
public int describeContents() {
return 0;
}
#Override
public void writeToParcel(Parcel dest, int flags) {
dest.writeString(name);
dest.writeString(id);
dest.writeString(nativeUrl);
dest.writeString(searchUrl);
dest.writeLong(db_id);
dest.writeInt(icon);
dest.writeInt(viewType);
dest.writeString(hidden);
}
#Override
public int compare(Bookmark o1, Bookmark o2) {
return 0;
}
}
This is layout of Fragment.
<?xml version="1.0" encoding="utf-8"?>
<android.support.v4.widget.NestedScrollView xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:overScrollMode="never">
<android.support.v7.widget.RecyclerView
android:id="#+id/myRecyclerView"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:fillViewport="false"
android:orientation="horizontal"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent">
</android.support.v7.widget.RecyclerView>
</android.support.v4.widget.NestedScrollView>
I have created a LogCat to show what it takes this is the result.
Right way
drawable/youtube
drawable/facebook
drawable/twitter
After add drawable or vector asset or image
drawable/wiki
drawable/facebook
drawable/trash
You're calling String.valueOf(bookmark.getIcon()) to store the icon in your database. As the icon is an int representing the resource, this stores the resource id as a string. The issue now is that resource ids are not stable and might change any time you create a new APK. Therefore it works while you don't update the app, but starts failing after.
Instead you should store the name of the res and keep these stable. You're already using the name with your XML data, so I'd assume that's your goal anyhow.
mDB.addBookmark(
Long.valueOf(bookmark.getId()),
bookmark.getName(),
bookmark.getViewType() > 0,
iconName(bookmark.getIcon()),
bookmark.getNativeUrl(),
bookmark.getSearchUrl()
);
String Icon = csr.getString(csr.getColumnIndex(COL_ICON));
b.setIcon(iconRes(Icon));
Now you only need to implement the mapping from name to id.
String iconName(int icon) {
return getResources().getResourceEntryName(icon);
}
int iconRes(String icon) {
return getResources().getIdentifier(icon, "drawable", mContext.getPackageName())
}
Also you need to unset mContext on detach or don't store it and use getContext() or requireContext() instead. Of course you'd have to check for null if you use it in some background operation.
#Override
public void onDetach() {
mContext = null;
super.onDetach();
}
Try to do myAdapter.notifyDataSetChanged(); after your arrayList adding work in the FragmentBookmark:
Bookmark bookmark = new Bookmark();
bookmark.setViewType(1);
bookmark.setIcon(R.drawable.add_new_bookmark_icon);
arrayList.add(bookmark);
myAdapter.notifyDataSetChanged();
BTW:The xml parse work and database operations should generally be handled asynchronously.
Updated:Change your the type icon field in Bookmark from int to String,and modify some code in loadBookMarksFromXML,from
int drawableResourceId =
getResources().getIdentifier(
xpp.getAttributeValue(null, "icon"), "drawable",mContext.getPackageName());
bookmark.setIcon(drawableResourceId);
to
bookmark.setIcon(xpp.getAttributeValue(null, "icon"));
change some code in onBindViewHolder in class MyAdapter,from:
int resID = context.getResources().getIdentifier(String.valueOf(arrayList.get(position).getIcon()), "drawable", context.getPackageName());
to
int resID = context.getResources().getIdentifier(arrayList.get(position).getIcon()), "drawable", context.getPackageName());
You can easily fix other errors caused by changing the icon field's type and run again,let me know the result.Thx.
For storing image to sqlite or any other local database you must store name of variable(i do this when use local database maybe there is better way)
So when you want to store drawable
Use this code
bookmark.setIcon("add_new_bookmark_icon");//don't forget to change icon to String in bookmark
Instead of this
bookmark.setIcon(R.drawable.add_new_bookmark_icon);//you use this in onViewCreate and buildBookmarkArrayListfromDB
Now when you want show drawable from database use this code
int resourceId = getResources().getIdentifier("", "drawable", getPackageName());
Drawable yourImage = ContextCompat.getDrawable(this,resourceId);
imageView.setImageDrawable(yourImage);
Note
You must change all place use setIcon or getIcon and all code you use icon as int like in getAllBookmarks -> csr.getInt(csr.getColumnIndex(COL_ICON) and others
I do this several years ago and i don't check it still works. try it and tell me what happens
As the Resource id will be kept on changing at every install or apk generation, it is wise to store the name of the icon resource and fetch it during display time. To do this you can store a string value of the name of the icon(you can also use the same name as of the bookmark, but make sure the drawable of the same name).
Change icon field to String in Database (Bookmark.db) & Pojo.
Remove this line in your Fragment of RecyclerView
int drawableResourceId = getResources().getIdentifier(xpp.getAttributeValue(null, "icon"), "drawable", mContext.getPackageName());
Change next line
bookmark.setIcon(xpp.getAttributeValue(null, "name"));
In onBindViewHolder in MyAdapter class get icon resource using
int iresourceid = getResources().getIdentifier(arrayList.get(position).getIcon(),"drawable",getPackageName());
Maybe you should move icons from res folder to assets, then load it with Glide.
if (getResources().getAssets().list("").contains("icon.png")) {
Glide.with(fragment)
.load(Uri.parse("file:///android_asset/icon.png"))
.into(imageView);
} else {
// load from web
}
/This is my override function. It works fine when I just retrieve names from the phone book. But the app crashes the moment i try to retrieve a contact number./
#Override
public void onActivityResult(int reqCode, int resultCode, Intent data) {
super.onActivityResult(reqCode, resultCode, data);
switch (reqCode) {
case (1) :
if (resultCode == Activity.RESULT_OK) {
Uri contactData = data.getData();
Cursor c = getContentResolver().query(contactData, null, null, null, null);
if(c.moveToFirst()) {
String contactId = c.getString(c.getColumnIndex(ContactsContract.Contacts._ID));
String hasPhone = c.getString(c.getColumnIndex(ContactsContract.Contacts.HAS_PHONE_NUMBER));
String name = c.getString(c.getColumnIndex(ContactsContract.CommonDataKinds.Phone.DISPLAY_NAME));
if (hasPhone.equalsIgnoreCase("1"))
{
Cursor phones = getContentResolver().query(ContactsContract.CommonDataKinds.Phone.CONTENT_URI,null,
ContactsContract.CommonDataKinds.Phone.CONTACT_ID +" = "+ contactId,null, null);
phones.moveToFirst();
String cNumber = phones.getString(phones.getColumnIndex(ContactsContract.CommonDataKinds.Phone.NUMBER));
Toast.makeText(getApplicationContext(), cNumber, Toast.LENGTH_SHORT).show();
}
}
c.close();
}
break;
}
}
First of all, create POJO class.
public class ContactEntity {
String name;
String number;
String id;
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getNumber() {
return number;
}
public void setNumber(String number) {
this.number = number;
}
}
Now, to retrieve contacts.
ArrayList<ContactEntity> contactList = new ArrayList<>();
contactList = getcontactList();
public ArrayList<ContactEntity> getcontactList() //This Context parameter is nothing but your Activity class's Context
{
ArrayList<ContactEntity> allContacts = new ArrayList<>();
Cursor cursor = getContentResolver().query(ContactsContract.Contacts.CONTENT_URI, null, null, null, null);
Integer contactsCount = cursor.getCount(); // get how many contacts you have in your contacts list
if (contactsCount > 0) {
while (cursor.moveToNext()) {
String id = cursor.getString(cursor.getColumnIndex(ContactsContract.Contacts._ID));
String contactName = cursor.getString(cursor.getColumnIndex(ContactsContract.Contacts.DISPLAY_NAME));
if (Integer.parseInt(cursor.getString(cursor.getColumnIndex(ContactsContract.Contacts.HAS_PHONE_NUMBER))) > 0) {
//the below cursor will give you details for multiple contacts
Cursor pCursor = getContentResolver().query(ContactsContract.CommonDataKinds.Phone.CONTENT_URI, null,
ContactsContract.CommonDataKinds.Phone.CONTACT_ID + " = ?",
new String[]{id}, null);
// continue till this cursor reaches to all phone numbers which are associated with a contact in the contact list
while (pCursor.moveToNext()) {
int phoneType = pCursor.getInt(pCursor.getColumnIndex(ContactsContract.CommonDataKinds.Phone.TYPE));
//String isStarred = pCur.getString(pCur.getColumnIndex(ContactsContract.CommonDataKinds.Phone.STARRED));
String phoneNo = pCursor.getString(pCursor.getColumnIndex(ContactsContract.CommonDataKinds.Phone.NUMBER));
//you will get all phone numbers according to it's type as below switch case.
ContactEntity entity = new ContactEntity();
entity.setName(contactName);
entity.setNumber(phoneNo);
allContacts.add(entity);
//Log.e will print all contacts according to contact types. Here you go.
switch (phoneType) {
case ContactsContract.CommonDataKinds.Phone.TYPE_MOBILE:
Log.e(contactName + ": TYPE_MOBILE", " " + phoneNo);
break;
case ContactsContract.CommonDataKinds.Phone.TYPE_HOME:
Log.e(contactName + ": TYPE_HOME", " " + phoneNo);
break;
case ContactsContract.CommonDataKinds.Phone.TYPE_WORK:
Log.e(contactName + ": TYPE_WORK", " " + phoneNo);
break;
case ContactsContract.CommonDataKinds.Phone.TYPE_WORK_MOBILE:
Log.e(contactName + ": TYPE_WORK_MOBILE", " " + phoneNo);
break;
case ContactsContract.CommonDataKinds.Phone.TYPE_OTHER:
Log.e(contactName + ": TYPE_OTHER", " " + phoneNo);
break;
default:
break;
}
}
pCursor.close();
}
}
cursor.close();
}
return allContacts;
}
I don't know what is your problem, but I have a code for getting phone number you can have a try:
public String getPhone(Context context, String contactID) {
Uri PhoneCONTENT_URI = ContactsContract.CommonDataKinds.Phone.CONTENT_URI;
String Phone_CONTACT_ID = ContactsContract.CommonDataKinds.Phone.CONTACT_ID;
String NUMBER = ContactsContract.CommonDataKinds.Phone.NUMBER;
// Query and loop for every phone number of the contact
Cursor phoneCursor = context.getContentResolver().query(PhoneCONTENT_URI, null, Phone_CONTACT_ID + " = ?", new String[]{contactID}, null);
String phoneNo = "";
if(phoneCursor != null) {
while (phoneCursor.moveToNext()) {
phoneNo = phoneCursor.getString(phoneCursor.getColumnIndex(NUMBER));
}
phoneCursor.close();
}
return phoneNo;
}
I have a ListView which is display several String when i click on a categories it will call and pop out a dialog options menu which has the options of English, Hindi and Cancel. The onClicklistener will be triggered when the user Click one of the category from the Listview such as "Novel", "Book" or "Plays".
What I want to do here is, when the user clicks "Book" and choose language English option, I want to pass category_id and language_id to the next activity.the category_id and language_id are the json object that i got from the server response. So I need to get the category_id selected from listview and pass it to the next activity along with the language_id as seleceted in dialog box.
if this is possible then how? Thanks in advance for your help.
holder.imageView.setImageUrl(Config.TAG_IMAGE_URL+category.getImage(), imageLoader);
holder.textViewName.setText(category.getName());
category_id = category.getId();
language_id = category.getLanguage_id();
holder.imageView.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View arg0) {
handleLanguageDialog();
}
});
}
private AlertDialog handleLanguageDialog() {
AlertDialog.Builder builder = new AlertDialog.Builder(context);
builder.setTitle("Select Language")
.setItems(R.array.lang, new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int which) {
// The 'which' argument contains the index position
// of the selected item
switch(which)
{
case 0:// English
break;
case 1://Bengali
break;
}
}
});
return builder.create().show();
}
categ.java
private String id;
private String name;
private String description;
private String image;
private String parent_id;
private String language_id;
private String created;
private String modified;
#Override
public String toString() {
return "Categ{" +
"id='" + id + '\'' +
", name='" + name + '\'' +
", description='" + description + '\'' +
", image='" + image + '\'' +
", parent_id='" + parent_id + '\'' +
", language_id='" + language_id + '\'' +
", created='" + created + '\'' +
", modified='" + modified + '\'' +
'}';
}
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getDescription() {
return description;
}
public void setDescription(String description) {
this.description = description;
}
public String getImage() {
return image;
}
public void setImage(String image) {
this.image = image;
}
public String getParent_id() {
return parent_id;
}
public void setParent_id(String parent_id) {
this.parent_id = parent_id;
}
public String getLanguage_id() {
return language_id;
}
public void setLanguage_id(String language_id) {
this.language_id = language_id;
}
public String getCreated() {
return created;
}
public void setCreated(String created) {
this.created = created;
}
public String getModified() {
return modified;
}
public void setModified(String modified) {
this.modified = modified;
}
}
In your first activity pass data like this
Intent intent = new Intent(this, NextActivity.class);
intent.putExtra("CATEGORY_ID", category_id);
intent.putExtra("LANGUAGE_ID", language_id);
startActivity(intent);
Now in your next activity recieve data like this
String cat_id = getIntent().getExtras().getString("CATEGORY_ID");
String cat_id = getIntent().getExtras().getString("LANGUAGE_ID");
Pass like this inside your switch case
case 0:
Intent intent = new Intent(YourCurrentActivity.this, Destination.class);
intent.putExtra("category_key", category_id);
intent.putExtra("language_key", language_id);
startActivity(intent);
Intent intent = new Intent(SourceActivity.this,destinationAvtivity.java);
intent.putExtra("category_id",109);
startActivity(theintent);
I am trying to update the record, whenever I am updating a record new id is generated with the updated values. The update should happen to the same id. What can be the reason?
Create table :
public void createTable(SQLiteDatabase db){
String CREATE_EVENTS_TABLE = "CREATE TABLE " + TABLE_EVENTS + "("
+ KEY_ID + " INTEGER PRIMARY KEY,"
+ KEY_TITLE + " TEXT,"
+ KEY_FROM_DATE + " DATE,"
+ KEY_TO_DATE + " DATE,"
+ KEY_DAY_OF_WEEK + " TEXT,"
+ KEY_LOCATION + " TEXT,"
+ KEY_NOTIFICATION_TIME + " DATE" + ")";
db.execSQL(CREATE_EVENTS_TABLE);
}
update function :
public int updateEvent(EventData event) {
SQLiteDatabase db = this.getWritableDatabase();
ContentValues values = new ContentValues();
values.put(KEY_TITLE,event.getTitle());
values.put(KEY_FROM_DATE,event.getFromDate());
values.put(KEY_TO_DATE,event.getToDate());
values.put(KEY_DAY_OF_WEEK,event.getDayOfWeek());
values.put(KEY_LOCATION,event.getLocation());
values.put(KEY_NOTIFICATION_TIME,event.getNotificationTime());
// updating row
return db.update(TABLE, values, KEY_ID + " = ?",
new String[] { String.valueOf(event.getId()) });
}
Calling update function :
db = new EventTableHelper(getApplicationContext());
eventData = new EventData();
db.updateEvent(eventData);
Thank you.
EDIT :
My constructor in EventData is this:
public EventData(String title,String fromDate,String toDate,String dayOfWeek,String location,String notificationTime){
this.title = title;
this.fromDate = fromDate;
this.toDate = toDate;
this.dayOfWeek = dayOfWeek;
this.location = location;
this.notificationTime = notificationTime;
}
and I am adding and updating value using eventData object:
db.addEvent(new EventData(eventTitle, startTime, endTime, dayOfWeek, location,notificationTime));
db.updateEvent(eventData);
The id is getting increased, I am not passing any value to id.
EventData class
public class EventData {
public int id;
public String title;
public String fromDate;
public String toDate;
public String location;
public String dayOfWeek;
public String notificationTime;
public EventData(){}
public EventData(String title,String fromDate,String toDate, String location){
this.title = title;
this.fromDate = fromDate;
this.toDate = toDate;
this.location = location;
}
public EventData(int id,String title,String fromDate,String toDate,String dayOfWeek,String location,String notificationTime){
this.title = title;
this.fromDate = fromDate;
this.toDate = toDate;
this.dayOfWeek = dayOfWeek;
this.location = location;
this.notificationTime = notificationTime;
}
/* public EventData(String title,String fromDate,String toDate,String dayOfWeek,String location,String notificationTime){
this.id = id;
this.title = title;
this.fromDate = fromDate;
this.toDate = toDate;
this.dayOfWeek = dayOfWeek;
this.location = location;
this.notificationTime = notificationTime;
}*/
public void setId(int id) {
this.id = id;
}
public void setTitle(String title) {
this.title = title;
}
public void setFromDate(String fromDate) {
this.fromDate = fromDate;
}
public void setToDate(String toDate) {
this.toDate = toDate;
}
public void setLocation(String location) {
this.location = location;
}
public void setDayOfWeek(String dayofWeek) {
this.dayOfWeek = dayofWeek;
}
public void setNotificationTime(String notificationTime) {
this.notificationTime = notificationTime;
}
public int getId() {
return id;
}
public String getTitle() {
return title;
}
public String getFromDate() {
return fromDate;
}
public String getToDate() {
return toDate;
}
public String getLocation() {
return location;
}
public String getDayOfWeek() {
return dayOfWeek;
}
public String getNotificationTime() {
return notificationTime;
}
}
I am creating events with child view so I want to update the event on which i will click. For that i have used setTag method to pass id of view.
This is my day fragment
dayplanView = (ViewGroup) view.findViewById(R.id.hoursRelativeLayout);
int id = i.getIntExtra("id",0);
mDb = new EventTableHelper(getActivity());
events = mDb.getAllEvents("Mon");
int tag = 0;
for (EventData eventData : events) {
String datefrom = eventData.getFromDate();
if (datefrom != null) {
String[] times = datefrom.substring(11, 16).split(":");
minutesFrom = Integer.parseInt(times[0]) * 60 + Integer.parseInt(times[1]);
}
String dateTo = eventData.getToDate();
String title = eventData.getTitle();
String location = eventData.getLocation();
if (dateTo != null) {
String[] times1 = dateTo.substring(11, 16).split(":");
minutesTo = Integer.parseInt(times1[0]) * 60 + Integer.parseInt(times1[1]);
}
createEvent(inflater, dayplanView, minutesFrom, minutesTo, title, location, tag);
tag++;
}
return view;
}
private void createEvent(LayoutInflater inflater, ViewGroup dayplanView, int fromMinutes, int toMinutes, String title,String location,int tag) {
final View eventView = inflater.inflate(R.layout.event_view, dayplanView, false);
RelativeLayout.LayoutParams layoutParams = (RelativeLayout.LayoutParams) eventView.getLayoutParams();
RelativeLayout container = (RelativeLayout) eventView.findViewById(R.id.container);
TextView tvTitle = (TextView) eventView.findViewById(R.id.textViewTitle);
if (tvTitle.getParent() != null)
((ViewGroup) tvTitle.getParent()).removeView(tvTitle);
if(location.equals(""))
{
tvTitle.setText("Event : " + title);
}
else
{
tvTitle.setText("Event : " + title + " (At : " + location +")");
}
int distance = (toMinutes - fromMinutes);
layoutParams.topMargin = dpToPixels(fromMinutes + 9);
layoutParams.height = dpToPixels(distance);
eventView.setLayoutParams(layoutParams);
dayplanView.addView(eventView);
container.addView(tvTitle);
eventView.setTag(tag);
eventView.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
i = new Intent(getActivity(),AddEventActivity.class);
editMode = true;
i.putExtra("EditMode",editMode);
int tag = 0;
tag =(int)v.getTag();
i.putExtra("tag",tag);
startActivityForResult(i,1);
}
});
}
As we discussed in comments. I think you don't need to be so complex as you are being now,
Just simply do like this,
db.update(TABLE, values, KEY_ID = id, null);
where id means the Integer value OR the value of column KEY_ID that you want to update. Like the value of id will be 5 if you want to update the row with id of 5.