Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 9 years ago.
Improve this question
I have an application consisting of two buttons and a text view.
btnInsert : when the user clicks this, an insert statement will be performed
btnShow : a select statement will be executed and the result is displayed in the TextView.
The problem is the following. I am using AsyncTask to perform write / read operations. I created two separate AsyncTasks, one for reading, one for writing. The insert (Write Async works properly, and I am sure that the values are getting inserted because if I run the same insert statement twice I get a PRIMARY KEY violation error:
07-19 11:46:48.080: E/AndroidRuntime(21486): FATAL EXCEPTION: main
07-19 11:46:48.080: E/AndroidRuntime(21486): android.database.sqlite.SQLiteConstraintException: PRIMARY KEY must be unique (code 19)
This is where the problem arises. Everything is performed properly, apparently, when I run the Select Statement ( by clicking the button), however instead of the value, I get com.example.testdb.MainActivity$Select#4203e900.
Does anyone know what the problem is? It is very annoying, I do not know what I am doing wrong. Please have a look at my code:
public class MainActivity extends Activity
{
static DatabaseImplementation db;
static SQLiteDatabase dbWrite;
static SQLiteDatabase dbRead;
static String insert = "INSERT INTO tbl_Test VALUES(7, 'Test');";
static String select = "SELECT test FROM tbl_Test WHERE _id = 1;";
Button btnInsert;
Button btnShow;
static TextView txtView;
//static String name = "";
#Override
public void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
db = new DatabaseImplementation(this);
dbWrite = db.getWritableDatabase();
dbRead = db.getReadableDatabase();
txtView = (TextView)findViewById(R.id.txtView);
btnInsert = (Button)findViewById(R.id.btnInsert);
btnInsert.setOnClickListener(new View.OnClickListener()
{
#Override
public void onClick(View v)
{
new Insert().execute();
}
});
btnShow = (Button)findViewById(R.id.btnShow);
btnShow.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v)
{
AsyncTask<String, Void, String> n = new Select().execute();
txtView.setText(n.toString());
}
});
}
#Override
public boolean onCreateOptionsMenu(Menu menu)
{
getMenuInflater().inflate(R.menu.main, menu);
return true;
}
//INSERT ASYNC
private class Insert extends AsyncTask<String, Void, String>
{
#Override
protected String doInBackground(String... params)
{
//Connect to Database First.
try
{
//String insert = executeInsert();
//onPostExecute(insert);
}
catch (Exception e)
{
e.printStackTrace();
}
return null;
}
#Override
protected void onPostExecute(String result)
{
//Connect to Database First.
dbWrite.execSQL(insert);
}
}
//SELECT ASYNC
private class Select extends AsyncTask<String, Void, String>
{
#Override
protected String doInBackground(String... params)
{
try
{
dbWrite = db.getWritableDatabase();
Cursor c = dbWrite.rawQuery(select, null);
String name = "";
c.moveToFirst();
name = c.getString(0);
return name;
}
catch (Exception e)
{
e.printStackTrace();
}
return null;
}
#Override
protected void onPostExecute(String result)
{
}
}
}
I would really appreciate if someone could help me.
That has nothing to do with the database but just with this two lines:
AsyncTask<String, Void, String> n = new Select().execute();
txtView.setText(n.toString());
Variable n is of tyoe AsyncTask, and applying toString() on it therefore gives you just the name of the class like you described (com.example.testdb.MainActivity$Select#4203e900).
What you got to do is, to change the onPostExecute() method of your Select class to this:
#Override
protected void onPostExecute(String result)
{
txtView.setText(result);
}
and remove the line txtView.setText(n.toString()); from your onClick handler.
Related
I would like to build an app and in the app i want to pull a specific text from a website. So lets say that we want to retrieve and store the words "Connect with friends and the world around you on Facebook" from facebook.com. which is easy to get if i want to get the whole text from a specific website. Now lets say that we would like to get the word connect only or friends only from the website and store it into a string and print it.
what im doing is a currency app and getting the number http://www.hawlergov.org/en/currency.php and retrieving 128,800.
the number then prints out on the textView
I Answered my own question by splitting the string like this!
public class MainActivity extends AppCompatActivity {
TextView text;
TextView text2;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
text = (TextView) findViewById(R.id.textView9);
text2 = (TextView) findViewById(R.id.textView8);
Button btn1 = (Button) findViewById(R.id.btn1);
btn1.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
new doit().execute();
}
});
}
public class doit extends AsyncTask<Void, Void, Void> {
String words;
String currentString;
String date;
#Override
protected Void doInBackground(Void... params) {
try {
Document doc = Jsoup.connect("http://www.hawlergov.org/en/currency.php").get();
words = doc.text();
currentString = words;
} catch (Exception e) {
e.printStackTrace();
}
String first = words;
String roar = first.substring(718, 730);
words=roar;
return null;
}
#Override
protected void onPostExecute(Void aVoid) {
super.onPostExecute(aVoid);
String currentDate = new SimpleDateFormat("MM-dd-yyyy", Locale.getDefault()).format(new Date());
text2.setText(currentDate);
text.setText(words);
}
}
here is the example
I'm new to android and working on a basic screen to use a web-service with android application.
I am posting values using AsyncTask and fetching the result from the webservice. It works fine until displaying the returned value. While displaying the Toast Message on click, I get old value of TextView resultReturned
public class TestPost extends Activity{
private TextView result = null;
#Override
protected void onCreate(Bundle savedInstanceState) {
// TODO Auto-generated method stub
super.onCreate(savedInstanceState);
setContentView(R.layout.my_screen);
result = (TextView)findViewById(R.id.resultReturned);
Button submit = (Button)findViewById(R.id.btnSubmit);
submit.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
String[] strPost = new String[]{"value1", "value2"};
SendAsyncRequest asyncSend = new SendAsyncRequest();
asyncSend.execute(strPost);
// ResultView retains old value and gets correct value on second click
String returned = result.getText().toString();
Toast.makeText(getApplicationContext(), returned, Toast.LENGTH_LONG).show();
}
});
}
public class SendAsyncRequest extends AsyncTask<String, Void, String>{
private String fetchedData = "";
#Override
protected String doInBackground(String... params ) {
// perform async task
return fetchedData;
}
#Override
protected void onPostExecute(String result) {
setReturedValue(result);
}
}
private void setReturedValue(String data){
result.setText(data);
}
So, how do I get the updated text value of the TextView?
AsyncTask takes time to get response from request, Show toast message in postExecute() method, like this, and remove from onclick.
#Override
protected void onPostExecute(String result) {
Toast.makeText(getApplicationContext(), result, Toast.LENGTH_LONG).show();
}
Try this
submit.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
String[] strPost = new String[]{"value1", "value2"};
SendAsyncRequest asyncSend = new SendAsyncRequest();
asyncSend.execute(strPost);
// ResultView retains old value and gets correct value on second click
String jsonResult;
try {
jsonResult=asyncSend.get();
} catch (InterruptedException | ExecutionException e) {
e.printStackTrace();
}
Toast.makeText(getApplicationContext(), jsonResult, Toast.LENGTH_LONG).show();
}
});
And return your Json String in doInBackground().
In my Project android i have a big data that i want insert to database.
I am using AsyncTask for inserting big data to database. for average 5 min needed to inserting.
But when my phone screen is off two bug exist.
1- for complete inserting the Screen must be On.
2- if one or many time Screen will be off then database not good inserted.
Question
1- where i am wrong.
2- Other way to inserting big data to database
part of My code
public class MainActivity extends Activity {
DatabaseHandler db;
MobileInformation mobile;
private SetDataBaseTask setDataBaseTask;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
db = new DatabaseHandler(this);
mobile = new MobileInformation();
preferences = PreferenceManager.getDefaultSharedPreferences(this);
String state = preferences.getString("IsSetDataBase","");
if ( !state.equals("yes"))
{
setDataBaseTask=new setDataBaseTask();
setDataBaseTask.execute();
}
}
public void firstDatabaseInitialize()
{
for (int i = 0;i < samsung0.brandStringList.length ; i++ )
{
mobile.Clean();
mobile.Alert_types = samsung0.Alert_typesStringList[i];
mobile.brand = samsung0.brandStringList[i];
//and something other
db.insertMobileInfo(mobile);
}
//and many for for inserting
}
#Override
protected void onStop() {
// TODO Auto-generated method stub
super.onStop();
if (Loading==true)
{
stopLoadingAndDownloading();
if (setDataBaseTask != null && setDataBaseTask.getStatus() != AsyncTask.Status.FINISHED)
setDataBaseTask.cancel(true);
}
db.close();
}
private class SetDataBaseTask extends AsyncTask<Void, Void, String> {
#Override
protected void onPreExecute() {
showLoading();
}
#Override
protected String doInBackground(Void... esult) {
String msg="";
db.open();
db.clearTable("indexing");
db.clearTable("mobile");
firstDatabaseInitialize();
db.close();
return msg;
}
#Override
protected void onPostExecute(String result) {
stopLoadingAndDownloading();
preferences = PreferenceManager.getDefaultSharedPreferences(MainActivity.this);
SharedPreferences.Editor editor = preferences.edit();
editor.putString("IsSetDataBase","yes");
editor.commit();
}
}
}
In my Project android i have a big data that i want insert to database.
Then you could use an IntentService and when the insert is complete send a broadcast and the activity can register on that broadcast action (unregister is necessary as well) so it can display some UI updates.
I am using AsyncTask for inserting big data to database. for average 5 min needed to inserting.
I don't think it's a good idea, because on orientation changes you're screwed! Also, you will leak the parent activity for the duration of insertion. So moving the insertion to an IntentService will decouple the insertion from UI.
I am pretty much new in Java (& android), hence I can't solve it with my limited knowledge despite searching extensively.
In the code below, I want to get a JASONArray from a weblink through AsyncTask. After that I want to populate my database from the array data.
To do that I created the RemoteConnectivity class where I can populate an ArrayList importdata with all the data from JASONArray. But the problem is, I cannot access my database class mylibmandbhandler from inside RemoteConnectivity class (I guess because that is not extended to Activity). And in ImportExport class, if I write the code to insert into database just after calling RemoteConnectivity().execute() [as in code below], it starts inserting before execution ends (very obvious because it is property of AsyncTask).
Now, can anybody please guide me through this? Or any link please to understand the whole process (I am lost in at least 50 pages I read about it :( ).
P.S. mylibmandbhandler is a Class I created (not activity) in my package src folder for my database operations.
public class ImportExport extends Activity {
public void webimport(View v){
new RemoteConnectivity().execute(); // START OF ASYNCTASK
//INSERT importdata INTO DATABASE AFTER EXECUTE
mylibmandbhandler db = new mylibmandbhandler(this);
for (String[] s : importdata){
db.addRecord(new mylibman(s));
}
}
final ArrayList<String[]> importdata = new ArrayList<String[]>();
private class RemoteConnectivity extends AsyncTask<Void, Void, Void>
{
#Override
protected Void doInBackground(Void... arg0) {
..................
..................
importdata.add(dataline); // POPULATE ARRAYLIST IMPORTDATA
return null;
}
#Override
protected void onPostExecute(Void result1)
{
// WHAT TO WRITE HERE
}
}
}
You should insert the data in the onPostExecute as follows:
public class ImportExport extends Activity {
public void webimport(View v){
new RemoteConnectivity().execute(); // START OF ASYNCTASK
}
final ArrayList<String[]> importdata = new ArrayList<String[]>();
private class RemoteConnectivity extends AsyncTask<Void, Void, Void>
{
#Override
protected Void doInBackground(Void... arg0) {
..................
..................
importdata.add(dataline); // POPULATE ARRAYLIST IMPORTDATA
return null;
}
#Override
protected void onPostExecute(Void result1)
{
//INSERT importdata INTO DATABASE AFTER EXECUTE FINISH (POST EXECUTE)
mylibmandbhandler db = new mylibmandbhandler(ImportExport.this);
for (String[] s : importdata){
db.addRecord(new mylibman(s));
}
}
}
}
The reason is because, onPostExecute is the method (callback) which is executed after the data has been done downloading in the doInBackground method.
Alternatively: You can also put the insert statements inside the doInBackground if you want the inserting to be done by background thread. This may be helpful, if inserting into the database is time consuming. In such a case the UI thread won't block. '
public class ImportExport extends Activity {
public void webimport(View v){
new RemoteConnectivity().execute(); // START OF ASYNCTASK
}
final ArrayList<String[]> importdata = new ArrayList<String[]>();
private class RemoteConnectivity extends AsyncTask<Void, Void, Void>
{
#Override
protected Void doInBackground(Void... arg0) {
..................
..................
importdata.add(dataline); // POPULATE ARRAYLIST IMPORTDATA
//INSERT importdata INTO DATABASE. NOW DONE IN THE BACKGROUND THREAD (Alternate method)
mylibmandbhandler db = new mylibmandbhandler(ImportExport.this);
for (String[] s : importdata){
db.addRecord(new mylibman(s));
}
return null;
}
#Override
protected void onPostExecute(Void result1)
{
}
}
}
Update: The important this to highlight in my answer is that I used new mylibmandbhandler(ImportExport.this); instead of new mylibmandbhandler(this); as this refers to AsyncTask which is not what the constructor supports.
You need to use method onPostExecute to insert data to datatable. Like this:
private class RemoteConnectivity extends AsyncTask<Void, Void, Void>
{
#Override
protected Void doInBackground(Void... arg0) {
..................
..................
importdata.add(dataline); // POPULATE ARRAYLIST IMPORTDATA
return null;
}
#Override
protected void onPostExecute(Void result1)
{
//INSERT importdata INTO DATABASE AFTER EXECUTE FINISH (POST EXECUTE)
mylibmandbhandler db = new mylibmandbhandler(ImportExport.this);
for (String[] s : importdata){
db.addRecord(new mylibman(s));
}
}
}
I am getting from time to time testing my app error:
03-04 20:57:01.929: E/TestApp(13673): android.view.ViewRoot$CalledFromWrongThreadException: Only the original thread that created a view hierarchy can touch its views.
From questions like this: Whats this exception?, and my own experience (I got this same error from time to time as in mentioned question) I would like to ask you guys what I can do to get rid of it?
As far as I know, I can do some stuff on AsyncTask connected to View, so I don't know why I am getting this info.
This is my code:
private MyDBAdapter mySQLiteAdapter;
private ListView wordList;
private AsyncDBDownload asycn;
private ProgressDialog dbUpdate;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.smart_guide_ocr);
asycn = new AsyncDBDownload();
wordList = (ListView) findViewById(R.id.wordsList);
//...
}
#Override
protected void onResume() {
super.onResume();
asycn.execute(null);
}
private class AsyncDBDownload extends AsyncTask<String, Integer, String> {
#Override
protected String doInBackground(String... params) {
try {
refreshList();//upload of contetn and set of adapter
} catch (Exception ex) {
Log.e(TAG, ex.toString());
}
return null;
}
#Override
protected void onPostExecute(String result) {
dbUpdate.dismiss();
}
#Override
protected void onPreExecute() {
dbUpdate = ProgressDialog.show(TestAppActivity.this, "Wait",
"DB download");
}
}
private void refreshList() {
mySQLiteAdapter = new MyDBAdapter(TestAppActivity.this);
mySQLiteAdapter.open();
String[] columns = { MyDBAdapter.KEY_TRANSLATED, MyDBAdapter.KEY_WORD, MyDBAdapter.KEY_LANG,
MyDBAdapter.KEY_ID };
Cursor contentRead = mySQLiteAdapter.getAllEntries(false, columns,
null, null, null, null, MyDBAdapter.KEY_ID, null);
startManagingCursor(contentRead);
Log.d(TAG, Integer.toString(contentRead.getCount()));
RowItem adapterCursor = new RowItem(this, R.layout.save_word_row,
contentRead, columns, new int[] { R.id.translatedWord, R.id.orgWord, R.id.langInfo }, 0);
wordList.setAdapter(adapterCursor);
mySQLiteAdapter.close();
}
You must not call wordList.setAdapter(adapterCursor); from within refresList method. That's a way of "changing a view from a non-UI thread".
So, instead, save the adapterCursor instance and use it from within the onPostExecute method.
You can not manipulate your Views within a background task. Do all the loading you need in your AsyncTask, pass it back into the activity in onPostExecute and set your adapter then. Doing any form of UI manipulation in a background task or service will throw this error.