Android: Update a Table Row SQL - android

I have this SQLite containing a number of 'Projects'. Each 'Project' with its attributes from the SQLite Database Table are displayed in an activity. What I wanna do is, when a button inside the activity is clicked, it updates the C_FAVORITE row of that 'Project'.
How am I able to do so? Which arguments do I need to put inside the update method below?
public void makeFavorite() {
Database.Project.C_FAVORITE.update(.......);
}
this is how I display the attributes of the Project on the activity:
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.project);
loader = new ImageLoader(this);
Intent intent = getIntent();
if (intent != null) {
Uri uri = intent.getData();
if (uri != null) {
final Cursor cursor = managedQuery(uri, new String[] {
BaseColumns._ID, Database.Project.C_PROJECTTITLE, Database.Project.C_ORGANIZATIONTITLE,
Database.Project.C_PROJECTDESCRIPTION,Database.Project.C_BIGIMAGE,Database.Project.C_DONATIONAMOUNT,Database.Project.C_ADDRESS,Database.Project.C_WEBSITE,Database.Project.C_SHORTCODE,Database.Project.C_KEYWORD,Database.Project.C_PRICE,Database.Project.C_CAMPAIGNID,Database.Project.C_PAYPALEMAIL,Database.Project.C_ELVAVAILABLE}, null, null, null);
if (cursor == null) {
finish();
} else {
if (cursor.moveToFirst()) {
ImageView img = (ImageView) findViewById(R.id.project_image);
TextView project_title = (TextView)findViewById(R.id.txt_project_title);
project_title.setText(cursor.getString(1));
......

You can try as follows:
public SQLiteDatabase sqd;
//Create connection of database
public void makeFavorite(String fieldname,String c_fav_value) {
ContentValues cv = new ContentValues();
cv.put(fieldname,c_fav_value);
int i= sqd.update(table_name, cv, where, where_clause);
}
If you have no where clause you can pass null there.

One way is to add tags to the button and grab the tags from within the makeFavourite()-method. Exactly how it's done depends entirely on your application structure, of which you don't tell us anything about.

Related

How to click an item of recyclerView and go to another recyclerView that contains the details of the clicked item?

I'm building a music app and I have an "Album" fragment which displays the song's album cover in RecyclerView. What I want is when I click on any of these items(album cover), I should be taken to another activity (albumsDetails.java) that contains the songs of that particular album. And all these songs should be displayed in RecyclerView.
I know how to use intents and I have tried many things but none of them works. I am new to Android Studio.
Album.java
public View onCreateView(LayoutInflater inflater, #Nullable ViewGroup container, #Nullable Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.albums_activity, container, false);
recyclerViewAlbum = view.findViewById(R.id.albums_reyclerView);
recyclerViewAlbum.setHasFixedSize(true);
GridLayoutManager gridLayoutManager = new GridLayoutManager(getContext(),2);
recyclerViewAlbum.setLayoutManager(gridLayoutManager);
albumsAdapter = new AlbumsAdapter( SongList1,getContext(), new AlbumsAdapter.RecyclerItemClickListener() {
#Override
public void onClickListener(SongInfoModel song, int position) {
Intent i = new Intent(getContext(), AlbumDetails.class);
i.putExtra("SongName", song.getSongName());
startActivity(i);
Activity activity = getActivity();
if (activity instanceof MainActivity) {}
}
});
Uri uri = MediaStore.Audio.Media.EXTERNAL_CONTENT_URI;
String selection = MediaStore.Audio.Media.IS_MUSIC + "!=0";
Cursor cursor = getActivity().getContentResolver().query(uri, null, selection, null, null);
if (cursor != null) {
if (cursor.moveToFirst()) {
do {
String name = cursor.getString(cursor.getColumnIndex(MediaStore.Audio.Media.TITLE));
String artist = cursor.getString(cursor.getColumnIndex(MediaStore.Audio.Media.ARTIST));
long duration = cursor.getLong(cursor.getColumnIndex(MediaStore.Audio.Media.DURATION));
String album = cursor.getString(cursor.getColumnIndex(MediaStore.Audio.Media.ALBUM));
String data = cursor.getString(cursor.getColumnIndex(MediaStore.Audio.Media.DATA));
long albumId = cursor.getLong(cursor.getColumnIndex(MediaStore.Audio.Media.ALBUM_ID));
Uri sArtworkUri = Uri.parse("content://media/external/audio/albumart");
Uri albumArtUri = ContentUris.withAppendedId(sArtworkUri, albumId);
SongInfoModel s = new SongInfoModel(name, artist, null, album, null, duration, data,albumArtUri);
SongList1.add(s);
} while (cursor.moveToNext());
}
cursor.close();
Collections.sort(SongList1, new Comparator<SongInfoModel>() {
#Override
public int compare(SongInfoModel lhs, SongInfoModel rhs) {
return lhs.getAlbum().compareTo(rhs.getAlbum());
}
});
}
recyclerViewAlbum.setAdapter(albumsAdapter);
albumsAdapter.notifyDataSetChanged();
return view;
}
}
AlbumsDetails.java
#Override
protected void onCreate(#Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.album_details);
albumsDetails_reyclerView = findViewById(R.id.albumsDetails_reyclerView);
LinearLayoutManager linearLayoutManager = new LinearLayoutManager(getApplicationContext());
albumsDetails_reyclerView.setLayoutManager(linearLayoutManager);
Bundle extras = getIntent().getExtras();
if(extras != null){
}
albumsDetailsAdapter = new AlbumsDetailsAdapter(getApplicationContext(), SongList2, new AlbumsDetailsAdapter.RecyclerItemClickListenerAlbumsDetails() {
#Override
public void onClickListener(SongInfoModel songInfoModelAlbumDetails, int positionAlbumDetails) {
}
}){
};
albumsDetails_reyclerView.setAdapter(albumsDetailsAdapter);
albumsDetailsAdapter.notifyDataSetChanged();
}
}
1)you need call back from adapter to activity.
in which you can pass the model that you want to show in next recycler view.for that simply pass the model through the next recyclerview constructor.
2)in next recycler view adapter you have model simply display the values from that model.
note:-assuming you know how to give call back.
Inside Recycler View Adapter, from ViewHolder class your can cll
View.setOnClickListener();
for that particular item inside recyclerview
You need to get the album id and pass that album id with intent to start activity. And on that activity, use that album id and query the cursor to get the songs related to that album. Hope that answer the question. Below is the code you can use to get allSongsViaAlbum id.
public List<SongModel> getAllSongsViaAlbumId(long albumId) throws Exception {
List<SongModel> songList = null;
if (mIsPermissionGranted) {
ContentResolver contentResolver = mContext.getContentResolver();
Uri uri = MediaStore.Audio.Media.EXTERNAL_CONTENT_URI;
String selection = MediaStore.Audio.Media.ALBUM_ID + "=?";
String [] whereArgs = {String.valueOf(albumId)};
String sortOrder = MediaStore.Audio.Media.TITLE + " ASC";
Cursor cursor = contentResolver.query(uri, null, selection, whereArgs, sortOrder);
if (cursor != null && cursor.moveToFirst()) {
songList = new ArrayList<>();
int totalSongs = cursor.getCount();
LogUtility.debugLog(MediaUtility.class.getSimpleName(), "Total number of audios " + totalSongs);
while (cursor.moveToNext()) {
SongModel currentSong = new SongModel();
currentSong.setAlbum(cursor.getString(cursor.getColumnIndex(MediaStore.Audio.Media.ALBUM)));
currentSong.setAlbumId(cursor.getLong(cursor.getColumnIndex(MediaStore.Audio.Media.ALBUM_ID)));
currentSong.setArtist(cursor.getString(cursor.getColumnIndex(MediaStore.Audio.Media.ARTIST)));
currentSong.setData(cursor.getString(cursor.getColumnIndex(MediaStore.Audio.Media.DATA)));
currentSong.setTitle(cursor.getString(cursor.getColumnIndex(MediaStore.Audio.Media.TITLE)));
currentSong.setAlbumArt(getAlbumArtViaAlbumId(currentSong.getAlbumId()));
songList.add(currentSong);
}
cursor.close();
}
}
return songList;
}
On click event use below code
Intent intent = new Intent(this, yourDesireActivity);
intent.putExtra("album_id", albumId);
startActivity(intent);
And when new activity starts call getAllSongsViaAlbumId() method and pass that which you get from intent from previous activity you can use below code to get the id
long albumId = getIntent().getExtras().getLong("album_id")
Hope that helps you
Firstly you need to have a look how to declare a RecyclerView adapter. This is a very good tutorial : https://antonioleiva.com/recyclerview/
Moreover you need to set tag to each element of your list, Holder.itemView.setTag(HOLDER POSITION); and finally you can declare a click listener where you can retrieve the tag.
public void onClick(View v) {
int tempid = (int) v.getTag();
Intent intent = new Intent(getContext(), destination.class);
intent.putExtra("ID", (int) v.getTag());
startActivity(intent);
On the destination class you can retrieve the id by calling id = getIntent().getExtras().getInt("ID");
Passing RecyclerView CardView Clicked Item Data To Activity
Handle Button click inside a row in RecyclerView
try this . Use onClickListener inside the adapter Class.

Android IllegalStateException: attempt to re-open an already-closed object: SQLiteDatabase [duplicate]

This question already has an answer here:
attempt to re-open an already-closed object: SQLiteDatabase
(1 answer)
Closed 8 years ago.
I know there are several questions like this one, but all of them seem to have a different approach to solve the problem and none have solved mine.
I have my main activity working just fine, loading the db and populating the listview. Then I call a second activity and the problem shows up when I try to load the listview.
I have tried using start/stop managingcursor(cursor) even though it is deprecated, but it didn't fix the problem. Also I tried cloasing the cursor and db in my main activity before firing the next one but that didn't help either.
Both classes extend from ListActivity and follow the same sequence:
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
//Open db in writing mode
MySQLiteHelper.init(this);
MySQLiteHelper tpdbh =
new MySQLiteHelper(this, "DB", null, 1);
SQLiteDatabase db = tpdbh.getWritableDatabase();
checkLocationAndDownloadData(); //this fires a Asynctask that calls method parseNearbyBranches shown bellow
//I load the data to the ListView in the postExecute method of the asynctask by calling:
/*
Cursor cursor = MysSQLiteHelper.getBranchesNames();
adapter = new SimpleCursorAdapter(this,
R.layout.row, cursor, fields, new int[] { R.id.item_text },0);
setListAdapter(adapter);
*/
ListView lv = getListView();
lv.setOnItemClickListener(new AdapterView.OnItemClickListener() {
#Override
public void onItemClick(AdapterView<?> listView, View view,
int position, long id) {
// Get the cursor, positioned to the corresponding row in the result set
Cursor cursor = (Cursor) listView.getItemAtPosition(position);
// Get the state's capital from this row in the database.
String branch_id = cursor.getString(cursor.getColumnIndexOrThrow("branch_id"));
cursor.close();
openNextActivity(Integer.parseInt(branch_id));
}
});
}
//In another file:
private void parseNearbyBranches(JSONObject jo) throws JSONException
{
if ( jo.has(jsonTitle) &&
jo.has("company_id") &&
jo.has("id")
) {
String branch = jo.getString(jsonTitle);
MySQLiteHelper tpdbh = MySQLiteHelper.instance;
SQLiteDatabase db = tpdbh.getWritableDatabase();
db.execSQL("INSERT INTO Branches (branch_id, name, company_id) " +
"VALUES ('" +jo.getInt("id")+"', '" + branch +"', '" +jo.getInt("company_id")+"' )");
db.close(); //no difference is I comment or uncomment this line
}
}
In MySQLiteHelper.java:
public static Cursor getBranchesNames() {
// TODO Auto-generated method stub
String[] columns = new String[] { "_id", "branch_id", "name", "company_id" };
Cursor c = getReadDb().query(branchesTable, columns, null, null, null, null,
null);
return c;
}
My other activity does basically the same:
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_branch_surveys);
//Read branch data from DB
int companyID = -1;
MySQLiteHelper.init(this);
String [] columns = new String [] {"company_id"};
String [] args = {Integer.toString(branchID)};
Cursor c = MySQLiteHelper.getReadDb().query(MySQLiteHelper.branchesTable, columns, "branch_id=?", args, null, null, null); //THIS QUERY WORKS JUST FINE
if (c.moveToFirst())
companyID = Integer.parseInt(c.getString(0));
c.close();
if( companyID != -1)
{
new DownloadTask().execute(Integer.toString(companyID) );
//where the Async task calls something just like NearByBranches shown above(but with different objects of course)
//And the postExecute sets the listView:
/* cursor = MySQLiteHelper.getAll();
SimpleCursorAdapter adapter = new SimpleCursorAdapter(this,
R.layout.row, cursor, fields, new int[] { R.id.item_text },0);
setListAdapter(adapter);
*/
}
}
}
In MySQLiteHelper.java:
public static Cursor getAll() {
// TODO Auto-generated method stub
String[] columns = new String[] { "_id","title", "points" };
//********IT IS IN THIS LINE WHERE I GET THE ERROR:********************
Cursor c = getReadDb().query(theTable, columns, null, null, null, null,
null);
return c;
}
public static SQLiteDatabase getReadDb() {
if (null == db) {
db = instance.getReadableDatabase();
}
return db;
}
I hope you can help me out. Thanks!
I just tried commenting the db.close in the similar method of parseNeabyBranches and the problem was solved. Yet I dont get the same error having db.close() in parseNearbyBranches(), can you explain me why?
In parseNearbyBranches() you create a separate SQLiteDatabase object with:
SQLiteDatabase db = tpdbh.getWritableDatabase();
Since this is a different object than the one returned by getReadDb(), you can (and should) close it. The basic rule is each time you call getWritableDatabase() and getReadableDatable() you must have a matching close() statement.

android calendar event issues with android 2.3

I am presenting user with the add calendar event screen with the below mentioned code.
For example the following will prompt the user if an event should be created with certain details.
Intent intent = new Intent(Intent.ACTION_INSERT);
intent.setData(CalendarContract.Events.CONTENT_URI);
startActivity(intent);
This part is working fine with Android 4.0 and above but not working on android 2.3....?
I want this to work on all android OS between 2.3 till 4.1.
you can use this also if you it to do with some other way :
mCursor = getContentResolver().query(
CalendarContract.Events.CONTENT_URI, COLS, null, null, null);
its a contentProvider for calender .
public class Main extends Activity implements OnClickListener{
private Cursor mCursor = null;
private static final String[] COLS = new String[]
{ CalendarContract.Events.TITLE, CalendarContract.Events.DTSTART};
}
Now we need to override the on create method. Pay special attention to how we populate the database cursor. This is where we need our previously defined COLS constant. You’ll note also that after the database cursor is initialized and the click handler callbacks are set, we go ahead and manually invoke the on click handler. This shortcut allows us to initially fill out our UI without having to repeat code.
Main.java
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
mCursor = getContentResolver().query(
CalendarContract.Events.CONTENT_URI, COLS, null, null, null);
mCursor.moveToFirst();
Button b = (Button)findViewById(R.id.next);
b.setOnClickListener(this);
b = (Button)findViewById(R.id.previous);
b.setOnClickListener(this);
onClick(findViewById(R.id.previous));
}
In our callback, we will manipulate the cursor to the correct entry in the database and update the UI.
#Override
public void onClick(View v) {
TextView tv = (TextView)findViewById(R.id.data);
String title = "N/A";
Long start = 0L;
switch(v.getId()) {
case R.id.next:
if(!mCursor.isLast()) mCursor.moveToNext();
break;
case R.id.previous:
if(!mCursor.isFirst()) mCursor.moveToPrevious();
break;
}
Format df = DateFormat.getDateFormat(this);
Format tf = DateFormat.getTimeFormat(this);
try {
title = mCursor.getString(0);
start = mCursor.getLong(1);
} catch (Exception e) {
//ignore
}
tv.setText(title+" on "+df.format(start)+" at "+tf.format(start));
}

IntentService and CursorLoader Sychronisation issue

I am building an app that follows the IOSched way of retrieving data, with the exception of the fact that I thought I would use CursorLoader rather than ContentObserver:
I have also been referring to Reto's android-protips-location which does use CursorLoader and the logic flow is quite similar to IOSched, thus:
initLoader → startService (serviceIntent) → handleIntent → insert into DB → notifyChange → onLoadFinished → update UI
What I am expecting to see happen is CursorLoader return a Cursor once an insert has been performed on the database.
Currently, the fragment onActivityCreated calls initLoader and runs query on the ContentProvider this returns the Cursor for that point in time, with current data.
However, it appears that onLoadFinished is not being triggered when I perform a refresh. Logs show that delete and insert on the ContentProvider are performed, yet viewing the log shows that notifyChange is dispatched on insert.
// in my Fragment:
#Override
public void onActivityCreated(Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
getLoaderManager().initLoader(0, null, this);
refreshWelcome();
}
public void refreshWelcome() {
Intent i = new Intent(getActivity(), SyncService.class);
i.setAction(SyncService.GET_WELCOME);
getActivity().startService(i);
}
public Loader<Cursor> onCreateLoader(int id, Bundle args) {
Uri queryUri = AppContract.Welcome.CONTENT_URI;
String[] projection = new String[] { Welcome.WELCOME_FIRST_NAME };
String where = null;
String[] whereArgs = null;
String sortOrder = null;
// create new cursor loader
CursorLoader loader = new CursorLoader(getActivity(), queryUri, projection, where, whereArgs, sortOrder);
return loader;
}
//in AppProvider (which extends ContentProvider)
#Override
public Uri insert(Uri uri, ContentValues values) {
final SQLiteDatabase db = mOpenHelper.getWritableDatabase();
final int match = sUriMatcher.match(uri);
switch (match) {
case WELCOME: {
long rowId = db.insertOrThrow(Tables.WELCOME, null, values);
if (rowId > 0) {
getContext().getContentResolver().notifyChange(uri, null);
return uri;
}
}
}
return null;
}
As far I know, you receive the cursor in onLoadFinished; onCreateLoader returns a Loader< Cursor>.
I do it this way, setting the notification Uri for the cursor just after received it. It works fine for me.
#Override
public void onLoadFinished(Loader<Cursor>loader, Cursor data) {
Log.v(DEBUG_TAG, "onLoadFinished");
data.setNotificationUri(getActivity().getContentResolver(),yourURI);
((SimpleCursorAdapter) getListAdapter()).swapCursor(data);
if (data.getCount() == 0) {
Toast.makeText(getActivity(), "no elements",Toast.LENGTH_SHORT).show();
return;
}
<}

Media Query Cursor keeps returning null on emulator and device....but why?

I am using the following code to get a list of songs on my device. Eventually I'd like to do more with them but to just get started I want to find audio/music in an Android device.
I have used this code to query the media store and I keep getting a null cursor... I've checked out these stack overflow answers but their either not relevant or I don't understand them enough to implement them...
Would appreciate any help! Thanks in advance
public class AudioFinalActivity extends Activity {
private TextView tv;
private String res;
/** Called when the activity is first created. */
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
// link text view obj
tv = (TextView) findViewById(R.id.tv);
res = "";
String[] proj = { MediaStore.Audio.Media._ID,
MediaStore.Audio.Media.DATA,
MediaStore.Audio.Media.DISPLAY_NAME,
MediaStore.Audio.Artists.ARTIST };
// managed query doesn't need startManagingCursor called on the
Cursor c = managedQuery(MediaStore.Audio.Media.EXTERNAL_CONTENT_URI,
proj, null, null, null);
// ContentResolver contentResolver = getContentResolver();
// String[] columns = { MediaColumns.TITLE, AudioColumns.DURATION,
// MediaColumns.DATA
// // add more columns if you want to fetch more data
// };
//
// Cursor c = contentResolver.query(
// MediaStore.Audio.Media.EXTERNAL_CONTENT_URI, columns, null,
// null, null);
if (c != null) {
Log.d("AFA", "Cursor returned NULL");
} else if (c.getCount() < 1) {
Log.d("AFA", "Cursor query is empty.. :( ...");
} else {
// do stuff with our content...
while (c.moveToNext()) {
//String title = c.getString(c
.getColumnIndex(MediaColumns.TITLE));
//Long duration = c.getLong(c
.getColumnIndex(AudioColumns.DURATION));
//String data = c.getString(c
.getColumnIndex(MediaColumns.DATA));
//res += title + "\n";
res += c.getString(c.getColumnIndex(MediaStore.Audio.Media.DISPLAY_NAME)) + "\n";
tv.setText(res);
}
}
}
}
I the stock music player can play my phones audio just fine..
EDIT:
I just removed my checking for the cursor being empty and for the cursor being null and I seem to get a result.. strange why the cursor is null yet the while(c.MoveToNext())... returns values... hmmm
your checking is if (c != null) {}, but I suppose it is if (c == null) {} (if you are checking the cursor being null)

Categories

Resources