keeping a variable value across all android activities - android

I have a database with one row of data that will be used across a number of activities. I need to be able to keep the row id available in all activites so I can read and write data across different activites with my DB adapter. I have successfully used putExtra (Overthelimit.java) via an intent to pass a row id to the next activity. mRowId variable is then given the row id using getExtra (Profile.java). The problem I now have is making mRowId available to other activities i.e. MyUsual and DrinksList so I can update data as I go.
You can see I have tried putExtras, putSerializable but can't get it to work. I think I am missing some understanding.
So for my profile menu option in the activity below I can send the value of the cursor row id to Profile class:
public class Overthelimit extends ListActivity {
private OverLimitDbAdapter dbHelper;
private Cursor cursor;
/** Called when the activity is first created. */
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
this.getListView();
dbHelper = new OverLimitDbAdapter(this);
dbHelper.open();
fillData();
registerForContextMenu(getListView());
}
#Override
protected void onActivityResult(int requestCode, int resultCode,
Intent intent) {
super.onActivityResult(requestCode, resultCode, intent);
fillData();
}
private void fillData() {
cursor = dbHelper.fetchAllUserDrinks();
startManagingCursor(cursor);
//cursor.getCount();
String[] from = new String[] { OverLimitDbAdapter.KEY_USERNAME };
int[] to = new int[] { R.id.label };
// Now create an array adapter and set it to display using our row
SimpleCursorAdapter notes = new SimpleCursorAdapter(this,
R.layout.user_row, cursor, from, to);
setListAdapter(notes);
}
#Override
protected void onDestroy() {
super.onDestroy();
if (dbHelper != null) {
dbHelper.close();
}
}
#Override
public boolean onCreateOptionsMenu(Menu menu) {
MenuInflater inflater = getMenuInflater();
inflater.inflate(R.menu.main_menu, menu);
return true;
}
#Override
public boolean onOptionsItemSelected(MenuItem item) {
// Handle item selection
switch (item.getItemId()) {
case R.id.profile:
Intent myIntent1 = new Intent(this, Profile.class);
if(cursor.getCount() != 0) {
//Toast.makeText(getApplicationContext(), "no profile",Toast.LENGTH_SHORT).show();
myIntent1.putExtra(OverLimitDbAdapter.KEY_ROWID, cursor.getString(cursor.getColumnIndexOrThrow(OverLimitDbAdapter.KEY_ROWID)));
}
startActivityForResult(myIntent1, 0);
return true;
case R.id.myusual:
Intent myIntent2 = new Intent(this, MyUsual.class);
startActivityForResult(myIntent2, 0);
return true;
case R.id.trackme:
Intent myIntent3 = new Intent(this, TrackMe.class);
startActivityForResult(myIntent3, 0);
return true;
case R.id.moreinfo:
Intent myIntent4 = new Intent(this, MoreInfo.class);
startActivityForResult(myIntent4, 0);
return true;
}
return super.onOptionsItemSelected(item);
}
}
Then make it available as mRowId in my Profile activity below:
mRowId = (bundle == null) ? null :
(Long) bundle.getSerializable(OverLimitDbAdapter.KEY_ROWID);
if (mRowId == null) {
Bundle extras = getIntent().getExtras();
mRowId = extras != null ? Long.parseLong(extras.getString(OverLimitDbAdapter.KEY_ROWID))
: null;
}
I then need to make this mRowId available to another activity called DrinkList from MyUsual. so I have MyUsual below with a drink1 button onClickListener to try and send the row id to DrinksList:
public class MyUsual extends Activity {
private Long mRowId;
private OverLimitDbAdapter mDbHelper;
private Cursor cursor;
private TextView mDrink1Label;
private TextView mDrink1Units;
/** Called when the activity is first created. */
#Override
public void onCreate(final Bundle bundle) {
super.onCreate(bundle);
mDbHelper = new OverLimitDbAdapter(this);
mDbHelper.open();
setContentView(R.layout.my_usual);
mDrink1Label = (TextView) findViewById(R.id.drink1Label);
mDrink1Units = (TextView) findViewById(R.id.drink1Units);
Button drink1 = (Button) findViewById(R.id.drink1Button);
// get intent data i.e. which drink button pressed and mRowId
mRowId = (bundle == null) ? null :
(Long) bundle.getSerializable(OverLimitDbAdapter.KEY_ROWID);
if (mRowId == null) {
Bundle extras = getIntent().getExtras();
mRowId = extras != null ? Long.parseLong(extras.getString(OverLimitDbAdapter.KEY_ROWID))
: null;
}
//populateFields();
drink1.setOnClickListener(new View.OnClickListener() {
public void onClick(View view) {
setResult(RESULT_OK);
//finish();
Intent myIntent1 = new Intent(view.getContext(), DrinksList.class);
myIntent1.putExtra("drinkButton", "drink1");
if(cursor.getCount() != 0) {
myIntent1.putExtra(OverLimitDbAdapter.KEY_ROWID, cursor.getString(cursor.getColumnIndexOrThrow(OverLimitDbAdapter.KEY_ROWID)));
}
startActivityForResult(myIntent1, 0);
}
});
}
protected void onSaveInstanceState(Bundle outState) {
super.onSaveInstanceState(outState);
//saveState();
outState.putSerializable(OverLimitDbAdapter.KEY_ROWID, mRowId);
}
}
From DrinksList I select a drink and I need to use the mRowId write the data to the database via the onListItemclick:
public class DrinksList extends ListActivity {
private ProgressDialog m_ProgressDialog = null;
private ArrayList<CreateDrinkOption> m_drinks = null;
private DrinkAdapter m_adapter;
private Runnable viewDrinks;
private String drinkButton;
private Long mRowId;
private OverLimitDbAdapter mDbHelper;
private String databaseRow;
private Cursor cursor;
/** Called when the activity is first created. */
#Override
public void onCreate(Bundle bundle) {
super.onCreate(bundle);
setContentView(R.layout.drinks_list);
mDbHelper = new OverLimitDbAdapter(this);
mDbHelper.open();
m_drinks = new ArrayList<CreateDrinkOption>();
this.m_adapter = new DrinkAdapter(this, R.layout.drink_row, m_drinks);
setListAdapter(this.m_adapter);
viewDrinks = new Runnable(){
#Override
public void run() {
getDrinks();
}
};
Thread thread = new Thread(null, viewDrinks, "MagentoBackground");
thread.start();
m_ProgressDialog = ProgressDialog.show(DrinksList.this,
"Please wait...", "Retrieving data ...", true);
// get intent data i.e. which drink button pressed and mRowId
mRowId = (bundle == null) ? null :
(Long) bundle.getSerializable(OverLimitDbAdapter.KEY_ROWID);
if (mRowId == null) {
Bundle extras = getIntent().getExtras();
drinkButton = extras.getString(drinkButton);
mRowId = extras != null ? Long.parseLong(extras.getString(OverLimitDbAdapter.KEY_ROWID))
: null;
}
}
protected void onSaveInstanceState(Bundle outState) {
super.onSaveInstanceState(outState);
//saveState();
outState.putSerializable(OverLimitDbAdapter.KEY_ROWID, mRowId);
}
private Runnable returnRes = new Runnable() {
#Override
public void run() {
if(m_drinks != null && m_drinks.size() > 0){
m_adapter.notifyDataSetChanged();
for(int i=0;i<m_drinks.size();i++)
m_adapter.add(m_drinks.get(i));
}
m_ProgressDialog.dismiss();
m_adapter.notifyDataSetChanged();
}
};
#Override
protected void onListItemClick(ListView l, View v, int position, long id)
{
try
{
super.onListItemClick(l, v, position, id);
CreateDrinkOption bkg = (CreateDrinkOption)l.getItemAtPosition(position);
String drink1type = bkg.getDrinkType().toString();
float drink1units = (bkg.getPercentageByVolume() * bkg.getVolume());
//Toast.makeText(this, mRowId.toString(), Toast.LENGTH_LONG).show();
mDbHelper.updateDrink(mRowId, drink1type, drink1units);
finish();
}
catch(Exception ex)
{
Toast.makeText(this, "error", Toast.LENGTH_LONG).show();
}
}
private void getDrinks(){
try{
m_drinks = new ArrayList<CreateDrinkOption>();
CreateDrinkOption o1 = new CreateDrinkOption();
o1.setDrinkType("Beer - 1 pint");
o1.setPercentageByVolume((float) 4.5);
o1.setVolume((float) 0.5);
m_drinks.add(o1);
CreateDrinkOption o2 = new CreateDrinkOption();
o2.setDrinkType("Wine - small glass");
o2.setPercentageByVolume((float) 12);
o2.setVolume((float) 0.125);
m_drinks.add(o2);
CreateDrinkOption o3 = new CreateDrinkOption();
o3.setDrinkType("Spirit - single");
o3.setPercentageByVolume((float) 40);
o3.setVolume((float) 0.25);
m_drinks.add(o3);
CreateDrinkOption o4 = new CreateDrinkOption();
o4.setDrinkType("Alcopop - bottle");
o4.setPercentageByVolume((float) 5);
o4.setVolume((float) 0.275);
m_drinks.add(o4);
Thread.sleep(1000);
Log.i("ARRAY", ""+ m_drinks.size());
} catch (Exception e) {
Log.e("BACKGROUND_PROC", e.getMessage());
}
runOnUiThread(returnRes);
}
private class DrinkAdapter extends ArrayAdapter<CreateDrinkOption> {
private ArrayList<CreateDrinkOption> items;
public DrinkAdapter(Context context, int textViewResourceId, ArrayList<CreateDrinkOption> items) {
super(context, textViewResourceId, items);
this.items = items;
}
#Override
public View getView(int position, View convertView, ViewGroup parent) {
View v = convertView;
if (v == null) {
LayoutInflater vi = (LayoutInflater)getSystemService(Context.LAYOUT_INFLATER_SERVICE);
v = vi.inflate(R.layout.drink_row, null);
}
CreateDrinkOption o = items.get(position);
if (o != null) {
TextView tt = (TextView) v.findViewById(R.id.drinkdetail);
TextView bt = (TextView) v.findViewById(R.id.drinkunits);
if (tt != null) {
tt.setText("Type: "+o.getDrinkType());
}
if(bt != null){
bt.setText("Units: "+ String.valueOf(o.getPercentageByVolume() * o.getVolume()));
}
}
return v;
}
}
}
Sorry for the long post, but all I need to do is make this value for mRowId available to all activites so I can read/write data at any point. The data also needs to be there if the app is paused or interupted by say an incoming call, so I use onSaveInstanceState.
ok, thanks. So reply to great answers and I have done this, but it crashes trying to get the data. I have this as my Application class:
public class OverthelimitApplication extends Application {
private Long rowId;
public Long getRowId() {
return rowId;
}
public void setRowId(Long value) {
rowId = value;
}
}
then set value with this:
OverthelimitApplication app1 = (OverthelimitApplication)getApplicationContext();
app1.setRowId((long) cursor.getColumnIndexOrThrow(OverLimitDbAdapter.KEY_ROWID));
then try to get value with this and it crashes:
mRowId = ((OverthelimitApplication) getApplicationContext()).getRowId();
I have fixed it! using this the set and get:
app1.setRowId(Long.parseLong(cursor.getString(cursor.getColumnIndexOrThrow(OverLimitDbAdapter.KEY_ROWID))));
mRowId = (long)((OverthelimitApplication)getApplicationContext()).getRowId();
I still had to specify long when setting and getting. Thanks for all your input.

Another way is to create a application class which is available for all activities.
To do that, you have to extend you Manifest with
<application
..
android:name=".MyApplication" >
and create a new Class
public class MyApplication extends Application {
public int rowId = 0;
}
inside the activities, you can access the rowId by
int mRowId = ((MyApplication) getApplicationContext()).rowId;

There are two options that I think are fit for your purpose:
SharedPreferences: the added benefit is that your variables will kept and available next time you start the application. You can store primitive types easily in shared preferences, like your rowId.
Application: you can subclass the application class, something like MyApplication extends Application, declare in your manifest that you're using this class instead of the default application, and access it using getApplication from all your activities. The added benefit is you can store anything, even a complex data structure in the application, you define the member and access methods in your MyApplication class. For example you could store the whole row of data in your application, not just the rowId)
Personally, I use SharedPreferences to remember settings that I want to be saved for the user, and not having to set them again each time the application is started is nice. And I use application for all the temporary data that I want to live across all activities as long as the application is open.

I'll describe 2 ways.
1) Use a static variable in any one of the Activities. This is the quick, dirty and lazy way. You've been warned.
2) Create your Application class.
Create a Simple class MyApplication that extends Application
In the Android Manifest, there should be a field for Application, make sure you choose your Class.
Typical example.
public class MyApp extends Application
{
private Object myGloballyAccessibleObject; //make getter and setter
private static MyApp singleInstance = null;
public static MyApp getInstance()
{
return singleInstance;
}
#Override
public void onCreate() {
super.onCreate();
singleInstance = this;
}
}
In your activities,
Call this
MyApp myApp = MyApp.getInstance();
myApp.getMyAwesomeObject(); //Booyaah!

You can use the ApplicationContext too. In your Manifest, you should have something like this :
<application
...
android:name="xx.xx.MyApp"
...>
Now, you can access to the Application from any Activity thanks to :
MyApp application = (MyApp)this.getApplicationContext();
You can put your attributes in this class, it'll be accessible anywhere in your app. MyApp must extends Application. See Manifest and
Application

Here you want to get mRowId values from all activity and it is primitive types, So
Either use Shared Preferences for store data or make your member field as a static globally, Then you can use this data in your whole application life cycle..
EDIT: Also you can use Application class as a singleton for your application and create field mRowId in this class and also make getter setter method for this field..

Related

Innerclass AsyncTask Static or by WeakReference?

I have a question regarding this simple frequently occurring situation in android .
I have an activity that will invoke the async task and async task will draw values from SQLite database and update on the UI. I used Async task to make the UI reponsive and fast.
This is the code I have been working on.
SqlHandler sqlHandler;
#BindView(R.id.list) ListView listView;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity1);
ButterKnife.bind(this);
sqlHandler = new SqlHandler(this);
new DisplayAll(this).execute();
listView.setOnItemClickListener((AdapterView<?> parent, View view,
int position, long id) -> {
Intent i = new Intent(getApplicationContext(), Activity2.class);
String text = textView.getText().toString();
startActivity(i);
});
}
private class DisplayAll extends AsyncTask<Void, Void, Void> {
int null_val;
final ArrayList<listRow=> myList = new ArrayList<>();
private WeakReference<Activity> mActivity;
public DisplayAll(Activity activity) {
mActivity = new WeakReference<>(activity);
}
#Override
protected Void doInBackground(Void... params) {
myList.clear();
String query = " ...";
Cursor c1 =sqlHandler.selectQuery(query);
if (c1 != null && c1.getCount() != 0) {
if (c1.moveToFirst()) {
do {
.....
} while (c1.moveToNext());
}
}
try {
null_val = Objects.requireNonNull(c1).getCount();
c1.close();
}
catch (NullPointerException e)
{
Log.e("NPE", "" + e);
}
return null;
}
#Override
protected void onPostExecute(Void param) {
// get a reference to the activity if it is still there
Activity activity = mActivity.get();
if (activity == null || activity.isFinishing()) return;
ProgressBar prgBar=findViewById(R.id.prgbar);
listAdapter Adapter;
prgBar.setVisibility(View.GONE);
Adapter = new listAdapter(getApplicationContext(), myList);
listView.setAdapter(Adapter);
}
}
I had checked this question also.I have added the weak reference to my class now. But still Android Studio warns me about the memory leak.
I tried to change it to static, but changing the sqlhandler as static also causes memory leak. To change the async task to a top-level class is not good for me. I have many async tasks in different activities.
So anyone have any idea how to tackle this?

putExtra doesn't seem to be working at all. Using ListView to get a string and using listView to display a string

I am programming a messaging app and I want to add users in a group. However, when a list of users pops up and I select one from the list, it doesn't pass the string (the username) to the other activity. All I get is an empty list.
Here is my code:
First Activity = Sending data (usernames from list) through putExtra()
public class ListUsersActivity extends Activity {
private String currentUserId;
private ArrayAdapter<String> namesArrayAdapter;
private ArrayList<String> names;
private ListView usersListView;
private Button logoutButton;
private ProgressDialog progressDialog;
private BroadcastReceiver receiver = null;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_list_users);
Parse.initialize(this, "embpZ0spRUv5XwDgI23innll1sgHg0KZNiKzg6kl", "LPsU4UffPeqFXkQB1GfLCIJ4kvg20llPgbOnLise");
currentUserId = ParseUser.getCurrentUser().getObjectId();
names = new ArrayList<>();
ParseQuery<ParseUser> query = ParseUser.getQuery();
query.whereNotEqualTo("objectId", currentUserId);
query.findInBackground(new FindCallback<ParseUser>() {
public void done(List<ParseUser> userList, com.parse.ParseException e) {
if (e == null) {
for (int i=0; i<userList.size(); i++) {
names.add(userList.get(i).getUsername().toString());
}
usersListView = (ListView)findViewById(R.id.usersListView);
namesArrayAdapter =
new ArrayAdapter<String>(getApplicationContext(),
R.layout.user_list_item, names);
usersListView.setAdapter(namesArrayAdapter);
usersListView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
#Override
public void onItemClick(AdapterView<?> a, View v, int i, long l) {
Intent goBackToAddPoolIntent = new Intent(ListUsersActivity.this, addNewPoolActivity.class);
addNewPoolActivity checker = new addNewPoolActivity();
checker.checkIfUserIsSelected(usersListView.getItemAtPosition(i).toString());
goBackToAddPoolIntent.putExtra("username", usersListView.getItemAtPosition(i).toString());
startActivity(goBackToAddPoolIntent);
}
});
} else {
Toast.makeText(getApplicationContext(),
"Error loading user list",
Toast.LENGTH_LONG).show();
}
}
});
}
Second Activity = Receiving data from putExtra()
public class addNewPoolActivity extends Activity {
private static ArrayList<String> addedUsers;
private ArrayAdapter <String> addedUserAdapter;
private boolean userIsSelected;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_add_new_pool);
Button addMembers = (Button) findViewById(R.id.bAddMembers);
addedUsers = new ArrayList<>();
//addedUsers.add("Group Members");
addMembers.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
Intent showUsersToSelect = new Intent(addNewPoolActivity.this, ListUsersActivity.class);
startActivity(showUsersToSelect);
}
});
ListView addedUsersList = (ListView) findViewById(R.id.addedUsersListView);
addedUserAdapter = new ArrayAdapter<>(this, R.layout.user_list_item, addedUsers);
addedUsersList.setAdapter(addedUserAdapter);
if(userIsSelected){
Bundle extras = getIntent().getExtras();
addedUsers.add(extras.getString("username"));
}
}
public void checkIfUserIsSelected(String user){
if (user!=null){
userIsSelected = true;
}else{
userIsSelected = false;
}
}
Since the default value for a boolean is false, the code is never called because
if(userIsSelected){
will always evaluate to false since you have declared the varaible as
private boolean userIsSelected;
and the first snippet here is in onCreate() so it will only run the first time the Activity is created.
Maybe you are wanting to call checkIfUserIsSelected(someUser) before that code but without more context of what you hope to accomplish, it's hard to say.
Possibly, you want to use startActivityForResult() in some way?
In addition to #codeMagic 's answer (Since your boolean value is false, it won't call the statement that you are adding the new data). It's also because of you parse the Data "username" after you setAdapter of your ListView. So basically you are setting the data, and then trying to add the new data you parsed to the list. Either you need to do it before setting your data set to your adapter, or call addedUsersAdapter.notifyDataSetChanged() to refresh your listView's data set.
addedUserAdapter = new ArrayAdapter<>(this, R.layout.user_list_item, addedUsers);
addedUsersList.setAdapter(addedUserAdapter);
Bundle extras = getIntent().getExtras();
// Check if the username has been sent to this Activity.
if(extras != null && extras.containsKey("username")){
addedUsers.add(extras.getString("username"));
// Refresh Your Data Set
addedUserAdapter.notifyDataSetChanged();
}

Passing Object with multiple parts from one activity to another

Hi I have a Requirement like Person Details for that i have multiple details like personal,educational,job like In first activity am enter personal details and then educational and then job like that one after another for that how can i maintain all details in single object and pass through app please help me.
Be aware that you need to bundle an object in an Intent, that object must implement the Parcelable interface. Here's a common implementation taken from the Parcelable documentation...
public class MyParcelable implements Parcelable {
private int mData;
public int describeContents() {
return 0;
}
public void writeToParcel(Parcel out, int flags) {
out.writeInt(mData);
}
public static final Parcelable.Creator<MyParcelable> CREATOR
= new Parcelable.Creator<MyParcelable>() {
public MyParcelable createFromParcel(Parcel in) {
return new MyParcelable(in);
}
public MyParcelable[] newArray(int size) {
return new MyParcelable[size];
}
};
private MyParcelable(Parcel in) {
mData = in.readInt();
}
}
Once you've done that, simply pass the object around in an Intent...
Intent i = new Intent(getApplicationContext(), ACTIVITY_TO_START.class);
i.putExtra("extra_key", new MyParcelable());
startActivity(i);
to retrieve the object for the starting activity...
Bundle extras = getIntent().getExtras();
if(extras != null && extras.containsKey("extra_key"))
{
MyParcelable p = (MyParecelable)extras.getParcelable("extra_key");
}
Simple solution: Use intents for this
Personal.class
public class Personal extends Activity {
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.personal);
Intent i = new Intent(getApplicationContext(), Educational.class);
i.putExtra("personal_details",<-get data from object->);
startActivity(i);
}
}
Educational.class
public class Personal extends Activity {
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.personal);
String personal_details;
Bundle extras = getIntent().getExtras();
if (extras != null) {
personal_details= extras.getString("personal_details");
}
Intent i = new Intent(getApplicationContext(), educational.class);
i.putExtra("personal_details",personal_details);
i.putExtra("educational_details",<-get data from object->);
startActivity(i);
}
}
Job.class
public class Personal extends Activity {
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.personal);
String personal_details,educational_details;
Bundle extras = getIntent().getExtras();
if (extras != null) {
personal_details= extras.getString("personal_details");
educational_details= extras.getString("educational_details");
}
Intent i = new Intent(getApplicationContext(), FinalResult.class);
i.putExtra("personal_details",personal_details);
i.putExtra("educational_details",educational_details);
i.putExtra("job_details",<-get data from object->);
startActivity(i);
}
}
FinalResult.class
public class Personal extends Activity {
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.personal);
String personal_details,educational_details,job_details;
Bundle extras = getIntent().getExtras();
if (extras != null) {
personal_details= extras.getString("personal_details");
educational_details= extras.getString("educational_details");
job_details= extras.getString("job_details");
}
}
}
{EDIT-1}
have a look at one of my answers in different storage options in
android - Click Here
You can achieve it using application variable or shared
preferences but i would not recommend it. !
Try storing it in POJO(Plain old Java class)
{EDIT-2}
Hmm if i understand correctly your question:: You are connected to internet(Wifi,Wired,... etc) basically you are trying to show a dialog when there is no network connectivity ! .... You can take the help of Broadcast receivers ...
Try this:: Set the broadcast receiver to fire the intent when there is no net connectivity ....
Write the code to catch that intent and pop the dialog .... In this dialog give the user option to reconnect the connectivity !

NullPointerException on calling a public method from another activity

I have an Activity SaveData.class with a public method addEvent() use to add some information in a DataBase table as follows:
public class SaveData extends Activity implements OnClickListener {
public SoftCopyDatabase dB ;
public static String FILE_NAME;
String _subject, _topic,_lecturenumber,_date;
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.save);
View add = findViewById(R.id.saveSave);
add.setOnClickListener(this);
View home = findViewById(R.id.saveBack);
home.setOnClickListener(this);
}public void onStart() {
super.onStart();
dB = new SoftCopyDatabase(this);
}
public void onStop() {
super.onStop();
if (dB.getReadableDatabase().isOpen()) {
//dB.close();
}
}
public void onDestroy() {
super.onDestroy();
if (dB.getReadableDatabase().isOpen()) {
dB.close();
}
}
public void onClick(View v) {
switch (v.getId()) {
case R.id.saveBack:
Intent i = new Intent(this, OpenScreen.class);
startActivity(i);
break;
case R.id.saveSave:
EditText subject = (EditText) findViewById(R.id.subjectid);
EditText topic = (EditText) findViewById(R.id.topicid);
EditText lecturenumber = (EditText) findViewById(R.id.lecturenumberid);
EditText date = (EditText) findViewById(R.id.dateid);
_subject = ((TextView) subject).getText().toString();
_topic = ((TextView) topic).getText().toString();
_lecturenumber = ((TextView) lecturenumber).getText()
.toString();
_date = ((TextView) date).getText().toString();
FILE_NAME = _subject + _topic + _lecturenumber;
//addEvent();
Intent j = new Intent(this, LectureNoting.class);
startActivity(j);
break;
}
}
public void addEvent() {
ContentValues values = new ContentValues();
values.put(SUBJECT, _subject);
values.put(TOPIC, _topic);
values.put(LECTURENUMBER, _lecturenumber);
values.put(DATE, _date);
values.put(_DATA, FILE_NAME + ".png");
dB.getWritableDatabase().insertOrThrow(TABLE_NAME, null, values);
}
}
Another activity LectureNoting.class is used to save Drawings on the disk and updates the entry in Database Table as follows:
public class LectureNoting extends Activity implements View.OnTouchListener{
private SaveData sD=new SaveData();
private File directory = new File("/sdcard/SoftCopy");
//...remaining code
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.drawing_activity);
}
//...remaining code
public void onClick(View view){
switch (view.getId()){
case R.id.saveBtn:
addEvent();
final Activity currentActivity = this;
Handler saveHandler = new Handler(){
#Override
public void handleMessage(Message msg) {
Toast.makeText(currentActivity, "Lecture Saved", Toast.LENGTH_SHORT).show();
}
} ;
new ExportBitmapToFile(this,saveHandler, softCopyInterface.getBitmap()).execute();
break;
//...remaining code
}
private class ExportBitmapToFile extends AsyncTask<Intent,Void,Boolean> {
private Context mContext;
private Handler mHandler;
private Bitmap nBitmap;
public ExportBitmapToFile(Context context,Handler handler,Bitmap bitmap) {
mContext = context;
nBitmap = bitmap;
mHandler = handler;
}
#Override
protected Boolean doInBackground(Intent... arg0) {
try {
if (!directory.exists()) {
directory.mkdirs();
}
final FileOutputStream out = new FileOutputStream(new File(directory + "/"+SaveData.FILE_NAME+".png"));
nBitmap.compress(Bitmap.CompressFormat.PNG, 90, out);
out.flush();
out.close();
return true;
}
catch (FileNotFoundException e)
{
e.printStackTrace();
}
catch (IOException e)
{
e.printStackTrace();
}
return false;
}
#Override
protected void onPostExecute(Boolean bool) {
super.onPostExecute(bool);
if ( bool ){
mHandler.sendEmptyMessage(1);
}
}
}
}
And I am receiving following error:
Unable to start activity componentInfo(com.ned.LectureNoting):NullPointerException
At the addEvent(), used in the onClick method of LectureNoting.
Kindly tell me where I am going wrong. One point I would like to mention is if addEvent() is called from the same activity in which it was defined, this error does not appear.
Couple of things:
Logcat should be giving more information about the error. You may have to scroll down a bit to see the source of the problem in your code, but there should be more info.
you shouldnt be defining public methods inside of classes that extend Activity to be used by other classes. If you want to expose some database method to multiple activities, then create a separate class for that and then call that method inside of your activity. You said LectureNoting extends Activity. You sure about this? You must have it extending SaveData if you are just calling addEvent() like that.
Either way, DON'T CALL METHODS FROM ONE ACTIVITY INSIDE OF ANOTHER. If you want to expose a method to multiple activities, create it in it's own class with a sensible name related to the group of functions that you expose.

How to implement text to speech in non-activity class

I want to implement text to speech in non-activity class, I want when user click on custom ListView to listen the word who is written.
The code is next:
public class BankAdapter extends BaseAdapter {
List<BankItem> items;
LayoutInflater inflater;
//class who implements TextToSpeech
**TextToSpeach ttl1;**
OnClickListener l;
static class BankItemHolder {
TextView wordView;
TextView descriptionView;
}
Activity myMainActivity;
public BankAdapter(Activity mainActivity) {
// TODO Auto-generated constructor stub
super();
this.myMainActivity=mainActivity;
}
public BankAdapter(Context ctx, List<BankItem> items) {
this.items = items;
inflater =(LayoutInflater)ctx.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
}
.
.
.
.
.
public View getView(final int position, View convertView, ViewGroup parent) {
final BankItemHolder bih;
if (convertView == null) {
RelativeLayout rl = (RelativeLayout) inflater.inflate(R.layout.v_bank_item, null);
convertView = rl;
bih = new BankItemHolder();
bih.wordView = (TextView) rl.findViewById(R.id.txtWord);
bih.descriptionView = (TextView) rl.findViewById(R.id.txtDescription);
convertView.setTag(bih);
} else {
bih = (BankItemHolder) convertView.getTag();
}
bih.wordView.setText(items.get(position).getWord());
bih.descriptionView.setText(items.get(position).getDescriprion());
l=new OnClickListener() {
public void onClick(View v) {
// TODO Auto-generated method stub
String w1 = items.get(position).getWord();
int i1 = w1.indexOf(" ");
String w2=w1.substring(0, i1);
**ttl1.speakWords(w2);**
}
};;;
convertView.setOnClickListener(l);
return convertView;
.
.
.
.
}
}
Now the class who implements TextToSpeech
public class TextToSpeach extends Activity implements OnInitListener {
private int MY_DATA_CHECK_CODE = 0;
private TextToSpeech tts;
/**
* Called when the activity is first created.
*/
#Override
public void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
// setContentView(R.layout.main);
// Fire off an intent to check if a TTS engine is installed
Intent checkIntent = new Intent();
checkIntent.setAction(TextToSpeech.Engine.ACTION_CHECK_TTS_DATA);
startActivityForResult(checkIntent, MY_DATA_CHECK_CODE);
}
public void speakWords(String word) {
tts.speak(word, TextToSpeech.QUEUE_ADD, null);
}
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
if (requestCode == MY_DATA_CHECK_CODE) {
if (resultCode == TextToSpeech.Engine.CHECK_VOICE_DATA_PASS) {
// success, create the TTS instance
tts = new TextToSpeech(this, this);
}
else {
// missing data, install it
Intent installIntent = new Intent();
installIntent.setAction(TextToSpeech.Engine.ACTION_INSTALL_TTS_DATA);
startActivity(installIntent);
}
}
}
public void onInit(int status) {
if (status == TextToSpeech.SUCCESS) {
Toast.makeText(TextToSpeach.this, "Text-To-Speech engine is initialized", Toast.LENGTH_LONG).show();
}
else if (status == TextToSpeech.ERROR) {
Toast.makeText(TextToSpeach.this, "Error occurred while initializing Text-To-Speech engine",
Toast.LENGTH_LONG).show();
}
}
/**
* Be kind, once you've finished with the TTS engine, shut it down so other
* applications can use it without us interfering with it :)
*/
#Override
public void onDestroy()
{
// Don't forget to shutdown!
if (tts != null)
{
tts.stop();
tts.shutdown();
}
super.onDestroy();
}
}
This question is symptomatic when you want to use Android framework outside of a android context..
From my little experience and lecture,
Here my own best practice in this question context.
FIRST:
Custom Service, Activity, Broadcastreceiver, ContentProvider are android context and/or are provided with android context.
This context is very important to get access to android services.
TTS is not in exception : it needs to be intantiated with a context and a listener to notify when it is ready (not ready at contruction time)
So you may do TextToSpeech actions in non-GUI component like a service for instance.
SECOND:
Avoid to design your code with a mix of App Logic and GUI in same code
THIRD:
if logic need to act on android framework it's a good way to provide context only when needed at runtime (as a parameter for instance)
as example : context can be a service or activity instance.
FOURTH:
Avoid as much as possible to keep reference to a context.
because android framework,for memory allocation strategy, may destroy /reconstruct context at it's own discretion.
hope that help

Categories

Resources