I'm new to Android programming and while I have successfully logged the output of a listener for a state change in the Telephony API, I'm having trouble accessing the value and writing it to a database. I can write to the log from within the inner class but can't save to DB as I can't access the helper from within the inner class. I'm also having trouble calling getSignalStrengths() method. these are all learning exercises and any advice would be much appreciated.
public class MyPhoneStateListener extends PhoneStateListener {
String sSstr = "initial value";
public String getSignalStrengths(){
return sSstr;
}
public void onSignalStrengthsChanged(SignalStrength signalStrength) {
super.onSignalStrengthsChanged(signalStrength);
sSstr = signalStrength.toString();
Log.v("Test", sSstr);
}
}
You can access your database inside the MyPhoneStateListener in a couple of way
Create a MyPhoneStateListener constructor with a Context parameter and use this context to instantiate your database class.
Just instantiate your database class using
MyDatabase db = new MyDatabase(MainActivity.this)
Related
Hi I am kind of new to android, still learning. And my problem is that, for example I have a method which was created in the MainActivity and I need to call it from another class.
Is it a good practice to get the instance of the MainActivity so that I may be able to call the method in the MainActivity from another class?
This is an example:
public class MainActivity extends AppCompatActivity {
private static MainActivity inst;
public static MainActivity instances()
{
return inst;
}
#Override
public void onStart() {
super.onStart();
inst = this;
}
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
}
public void showToast (String text){
Toast.makeText(inst, text, Toast.LENGTH_SHORT).show();
}
Then this is the other class:
public class broadcastReceiver extends BroadcastReceiver {
public void onReceive(Context context, Intent intent) {
MainActivity instance = new MainActivity();
instance.showToast(AnyText);
}
}
I saw this type of coding while looking at tutorials and wondered if it's a good practice or maybe there might be a better way? Since I get the warning of Do not place Android Context Classes in static classes
Thanks in advance for any insight or help! :D
I guess You want to make A singleton of Activity Class
but as Mention in All Pattern Design
using Singleton
If and Only If its only way to Make A Global Variable
Singleton is based on Lazing Initialing and Load On Memory
so I guess If you cant to Interact With Activiy You can Use
BroadCast Or Intents
You can call method from another class like this:
MainActivity instance = new MainActivity();
String data = instance.data();
and create data method in that class:
public String data() {
return mangaId;
}
Is it a good practice to get the instance of the MainActivity so that
I may be able to call the method in the MainActivity from another
class?
You totally can do this but you don't need to make it static and use a constructor. Just create a new instance like follows and you'll access the public methods
MainActivity mainActivity = new MainActivity();
mainActivity.showToast(text);
About the warning
It suggests avoiding having context fields defined as static. The warning itself explains why: It's a memory leak. If you make it static it will be accessible anywhere in your app and some methods can hold the reference to this context for a really long time and it won't be garbage collected. It will lead to a outofmemory exception and the app could crash. But here you're trying to invoke showToast() from broadcastreceiver so you can just get rid of static references. And it you need them in the future you safe ways to inject context
You cannot create instances of an Activity using the new operator.
You have to use an Intent to let an Activity to be created.
So you cannot get a reference to an instance of your activity.
The only methods you can use of your activity class are static ones.
I want to check if a SQLite Database is open, and if it is, I would like to access that Database within a service class.
I am worried, and have seen, that multiple open calls to the database clash, and throw exceptions. Because I do query the database within both my Activity and Service classes, I am attempting to implement the solution Commonsware recommended here: When to close db connection on android? Every time after your operation finished or after your app exit. However I do not want to close then open the Database within the Service class if the Activity might need it. From this answer Why use SQLiteOpenHelper over SQLiteDatabase?, it looks like it might make sense to implement a SQLiteOpenHelper to solve the issue of making multiple calls.
Thank you so much for all your help!!
This man Kevin is a legend: http://touchlabblog.tumblr.com/post/24474750219/single-sqlite-connection. Thank you so much.
On that link he shares his ridiculously simple solution:
public class DatabaseHelper extends OrmLiteSqliteOpenHelper {
private static DatabaseHelper instance;
public static synchronized DatabaseHelper getHelper(Context context)
{
if (instance == null)
instance = new DatabaseHelper(context);
return instance;
}
//Other stuff...
}
Then in my SQLite class I changed my code to look like this:
public BlacklistWordDataSource(Context context) {
dbHelper = MySQLiteHelper.getHelper(context);
}
at onCreat in the activity put datasource.open();
then do what ever you want
and at the end of actevity put this to close :
/** Call after close activity */
#Override
protected void onStop() {
super.onStop();
//Close dataSource
datasource.close();
}
I have a static function that gets called whenever my background service gets a new location. In this function I want to take to coordinates passed in and save them in my database. Can I pass 'null' as the context to create an instance of the database helper or is there a better way to do this. Thanks.
public static void locationHasChanged() {
final wd_DatabaseHelper helper = new wd_DatabaseHelper(null, "myDB.db", null, 1);
}
Probably not. Usually your Database helper extends SQLiteOpenHelper and the context will be used to call the openOrCreateDatabase() or the getDatabasePath(). I can't say for sure without seeing the code of wd_DatabaseHelper but having a null context is never a good idea. See for your self ... Source of SQLiteOpenHelper
since an android Service is a context you can pass "this of the service" into your method
public class MyLocationHelper {
public static void locationHasChanged(Context context) {
final wd_DatabaseHelper helper = new wd_DatabaseHelper(context, "myDB.db", null, 1);
....
}
}
public class MyService extends Service {
private void onLocationHasChanged()
{
MyLocationHelper.locationHasChanged(this);
}
}
I'm having some trouble understanding the search dialog in the Android SDK.
The "main activity" of my application provides a button. If the user clicks this button the search dialog is called. The search itself is then done in an async task as it might need some time. So far so good.
The main activity also creates a database adapter object which is used to initialize the database, perform queries, etc. But how can I use this adapter object in the searchable activity?
MAIN activity
// Init database
DatabaseAdapter dba = new DatabaseAdapter();
dba.init();
// open search dialog
if (buttonClick) onSearchRequest();
Searchable activity
Get intent and receive query from search dialog -> OK
How can I use the database adapter again to perform a query?
Do I have to create a new object? Can I pass it somehow from the min activity to the searchable activity, [...]?
Thanks,
Robert
You can create adapter in Application class, and retreieve it in all your activities. That's what I do for my projects.
public class ApplicationClass extends Application {
Adapter adapter.
#Override
public void onCreate(){
adapter=new Adapter();
super.onCreate();
}
public Adapter getAdapter(){
return adapter;
}
}
Then call from Activity:
Adapter adapter=(ApplicationClass)getApplication().getAdapter();
Something like that. ApplicationClass is for your app name. Could be MyAppNameApplication You should create it in your package and then declare in AndroidManifest.xml
An option would be to use a singleton and provide access to the DatabaseAdapter via a static method. Ex:
private static DatabaseAdapter sWritableAdapter = null;
private static DatabaseAdapter sReadableAdapter = null;
public static DatabaseAdapter openForReading(Context ctx) {
if(sReadableAdapter == null)
sReadableAdapter = new DatabaseAdapter(new DatabaseHelper(ctx).getReadableDatabase());
return sReadableAdapter;
}
or for write access:
public static DatabaseAdapter openForWriting(Context ctx) {
if(sWritableAdapter == null)
sWritableAdapter = new DatabaseAdapter(new DatabaseHelper(ctx).getWritableDatabase());
return sWritableAdapter;
}
So in your searchable activity you would write for instance:
DatabaseAdapter adapter = DatabaseAdapter.openForReading(ctx);
adapter.searchSomething();
Marco
You should rather implement an ContentProvider
http://developer.android.com/guide/topics/providers/content-providers.html
They are singletons, and accessible from (almost) everywhere in your application.
I want to use a singleton pattern to hold a database and some other data/methods for my Android application.
I realize there are many reasons against singletons, but for this case I'd like to use it.
I've sub-classed UIApplication and made a data class within it called MyAppData.
MyAppData needs to have access to the SQLite database.
When I create the databse, I need to pass a context. I could pass the application context, but it will not directly relate to MyAppData.
I don't know if this wlll cause problems with my code.
So my thought is to have MyAppdata extend android.content.ContextWrapper. I don't think I should extend Activity because it's really not an activity, its a data class with methods to access the database.
I'm wondering if I extend ContextWrapper will there be something deep in the code I'm missing that will cause big problems down the road (memory leaks, etc).
This may not be the ideal approach to this (and I've considered other options), but my goal is to:
Have a singleton class in UIApplication that can encapsulate the database and be retrieved easily from any activity in my app.
Thanks in advance for your suggestions/warnings/advice.
Subclass android.database.sqlite.SQLiteOpenHelper and android.app.Application (with the latter being properly declared in AndroidManifest.xml).
Now,
public class MyApplication extends Application {
private static SQLiteOpenHelper openHelper;
#Override
public void onCreate() {
super.onCreate();
openHelper = new DbManager(this);
//
}
public static SQLiteDatabase getDB() {
return openHelper.getWritableDatabase();
}
}
Then have helper DAO classes that will perform instertions/updates/etc.
That's what I'm using in all of my apps.
I've used this approach:
Create a class responsible for managing the db, let's call it DBUtil. This class will extend android.database.sqlite.SQLiteOpenHelper. You can pass a reference to the application context to the constructor of this class. This class will contain methods for creating the db, adding, removing and retrieving items.
Create another class, let's call it AppCore, create a static instance of the DBUtil and a static init() method that accepts an ApplicationContext object
public class AppCore
{
public static var dbUtil:DBUtil;
public static void init( ApplicationContext context )
{
dbUtil = new DBUtil( context );
}
}
Then in the onCreate() method of our your application's main Activity, initialize the AppCore class.
#Override
protected void onCreate(Bundle savedInstanceState)
{
AppCore.init( getApplicationContext() );
}
So, it's not really a Singleton. Instead, the DBUtil instance is maintained as a static property, yet still accessible throughout your application, such as this:
AppCore.dbUtil.createNewRecord( params );
Also, I found this tutorial to be very helpful when getting started with this topic: http://developer.android.com/guide/tutorials/notepad/index.html