Is it possible to get device aspect ratio before launching any activity?
I am trying to setup the width based on whether my device is identified as 'long' or 'not_long'. This should be available long before the activity is launched but I am not sure where I can get this variable. Activity is NOT available at the time this method is executed. Also in order to avoid memory leaks I do not want to pass activity into the class that contains the following method.
Here is the failing call method:
public int getDefaultWidth() {
Configuration myConfig = new Configuration();
myConfig.setToDefaults();
myConfig = getResources().getConfiguration();
switch (myConfig.screenLayout & Configuration.SCREENLAYOUT_LONG_MASK) {
case Configuration.SCREENLAYOUT_LONG_NO: {
return this._defaultWidth;
}
case Configuration.SCREENLAYOUT_LONG_YES: {
return this._defaultWidthLong;
}
case Configuration.SCREENLAYOUT_LONG_UNDEFINED: {
return this._defaultWidth;
}
}
return this._defaultWidth;
}
Your app's Application context is created before any activities. An Application has a valid context, so you could use that to fetch whatever you need, set a static or member variable, and then reference that in your first activity.
An Application context can be handled by adding a new class that extends Application and making a small change in AndroidManifest.xml
Manifest:
<application android:enabled="true"...
android:name=".Foo">
...
</application>
Add the new class to your project that extends Application:
public class Foo extends Application {
private int mWidth;
#Override
public void onCreate() {
super.onCreate();
// do stuff to set mWidth using the Application context like:
// mWidth = getResources().getConfiguration().blahblahblah
}
public int getWidth() {
return mWidth;
}
From your activity, simply do this to get width:
int width = ((Foo)getApplication()).getWidth();
Where is this is executing? I don't see how you could be executing code and not have something instantiated that inherits from Context. Service inherits from Context and a BroadcastReceiver's onReceive is given a Context.
Also, instead of passing a Context in, you could just pass in a Configuration object from where ever this method is being called.
When you call this method from an activity. you can pass "this" as a parameter for getDefaultWidth() method. Then you can use it as a context.
public int getDefaultWidth(Context context) { ... }
and in the activitym call it like
int width = getDefaultWidth(this)
Related
I currently have the current aspect
#Aspect
public class ActivityShowingAspect {
private static final String POINTCUT_METHOD =
"execution(#nz.co.kevinsahandsomedevil.android.myaccount.aspect.ActivityMustBeShowing * *(..))";
#Pointcut(POINTCUT_METHOD)
public void methodAnnotatedWithActivityShowing() {
}
#Around("methodAnnotatedWithActivityShowing()")
public Object weaveJoinPoint(ProceedingJoinPoint joinPoint) throws Throwable {
Activity activity = // code to retrieve the calling activity, joinPoint.getTarget() or whatever
Object result = null;
if(!activity.isFinishing()) {
result = joinPoint.proceed();
} else {
result = // do something else
}
return result;
}
}
I'd like to know how to determine the calling Activity from within the Aspect.
Okay so it depends on where the method with your annotation is.
If the annotated method is declared within an Activity implementation, then you can indeed call joinpoint.getTarget()and cast the result.
Also you might want to update your pointcut to make sure that the method indeed is on an activity :
execution(#nz.co.vodafone.android.myaccount.aspect.ActivityMustBeShowing * *(..)) && within(android.app.Activity+)
If that's not the case then you might need to add an advice before any activity's onResume() to remember what the current activity is.
Here is my scenario.
I have an android activity in which I want to abstract my I/O dependencies. The dependencies are represented by this interface (edited for brevity and simplicity):
public interface ITimeDataServer {
TimeRecord[] get(int userID);
void save(TimeRecord record);
}
What I want is for my activity to be able to call these interface methods, and leave the implementation to be supplied by the calling code. (Pretty standard, I think).
ITimeDataServer myServer;
int myUserID;
void loadRecords() {
TimeRecord[] records = myServer.get(myUserID);
// etc...
}
My difficulty is, how can I ensure that myServer gets set?
This seems like a common problem, but I can't find a clean solution.
My first thought would be that myServer would be passed in through the constructor, but Android activities aren't really instantiated with constructors.
I've come up with several solutions, but they're all icky in some way:
Icky Solution 1
Create a static method to launch the activity class which takes an ITimeDataServer parameter and stores it in a static variable from which the activity can access it:
private static ITimeDataSource theDataSource;
public static void launch(Activity currentActivity, ITimeDataSource dataSource) {
theDataSource = dataSource;
Intent intent = new Intent(currentActivity, MainActivity.class);
currentActivity.startActivity(intent);
}
This is icky because (a) the data source is static and not actually associated with the instance, and (b) a consumer could initiate the activity by the standard activity API rather than this static method, which will cause NullPointerException.
Icky Solution 2
I can create a Provider class which provides a singleton instance of ITimeDataSource, which needs to be initialized by the calling library before use:
public class TimeDataSourceProvider {
private static ITimeDataSource myDataSource = null;
public void initialize(ITimeDataSource dataSource) {
myDataSource = dataSource;
}
public ITimeDataSource get() {
if (myDataSource == null)
throw new NullPointerException("TimeDataSourceProvider.initialize() must be called before .get() can be used.");
else
return myDataSource;
}
}
This seems a little less icky, but it's still a little icky because the activity's dependency is not obvious, and since there may be many paths to launch it, it's highly possible that some of them would forget to call TimeDataSourceProvider.initialize().
Icky solution 3
As a variation on #2, create a static IODependencyProvider class which must be initialized with ALL dependencies on app startup.
public class IODependencyProvider {
static ITimeDataSource myTimeData;
static IScheduleDataSource myScheduleData; // etc
public static void initialize(ITimeDataSource timeData, IScheduleDataSource scheduleData /* etc */) {
myTimeData = timeData;
myScheduleData = scheduleData;
//etc
}
public static ITimeDataSource getTimeData() {
if (myTimeData == null)
throw new NullPointerException("IODependencyProvider.initialize() must be called before the getX() methods can be used.");
else
return myTimeData;
}
// getScheduleData(), etc
}
This seems superior to #1 and #2 since a failure to initialize would be much harder to sneak by, but it also creates interdependencies among the data types that otherwise need not exist.
...and other icky variations on that theme.
The common themes that make these solutions crappy:
the need to use static fields to pass non-serializable information to an activity
the lack of ability to enforce initialization of those static fields (and subsequent haphazardness)
inability to clearly identify an activity's dependencies (due to reliance on statics)
What's a nooby Android developer to do?
As long as these dependencies implement Parcelable correctly, you should be able to add them to your intent, then unparcel them as ITimeDataServer and get the correct class.
I found a nice solution here, in the least-loved answer.
I define the library activity as abstract and with no default constructor, but a constructor that takes an interface, like so:
public abstract class TimeActivity extends AppCompatActivity {
private ITimeDataSource myTimeDataSource;
public TimeActivity(#NonNull ITimeDataSource dataSource) {
myTimeDataSource = dataSource;
}
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_time);
// do stuff with myTimeDataSource!
}
}
Then, the calling code can create a concrete subclass with its chosen implementation that does have a parameterless constructor. No static members, easy-peasy!
This allows you to abstract and inject all sorts of crazy behaviours! Woooo!
(Note that the concrete subclass activity needs to be manually added to AndroidManifest.xml, like all activities, or the app will crash when it tries to launch.)
I want to pass a value from activity A to activity B without actually starting the activity B (therefore this rules out the use of Intents and putExtra). The activity B may or may not be started but when it does it needs to display the value passed to it by activity A.
I searched high and low but couldn't find any relevant solution to this seemingly simple question. Any help will be appreciated!
You can't find a solution, because it's something that goes against any logic.
Activity B can't do anything if not started and visible. Activity B might even already be destroyed by the system without you knowing.
You can use a lot of things to set some variables, which your Activity B can read such as in your Application, somewhere in your XML or simply any random class.
Still, you can not actually DO anything with any of these options, until you start Activity B and when you can, it will just effectively be the same as giving the extra data in the Intent.
Use global class like :
public class AppConfig {
Context context;
public AppConfig(Context mxt) {
context = mxt;
}
public static String filepath = null;
Then, in activity A before onCreate() :
AppConfig config;
Context context;
and in onCreate() method put this :
context = getApplicationContext();
config = new AppConfig(context);
And, in second Activity B before onCreate() :
AppConfig config;
Context context;
And, in onCreate() method put this :
context = getApplicationContext();
config = new AppConfig(context);
And set the value where you want. Hope this will help you.
You can use shared Preferences. Using this one Activity can set Value into it, and other activity can read from it.
So you need to keep a value for an activity . If it starts it means you have to use those values, otherwise you will discard those values. For this you can use a separate class with a variable of datatype that you want and you can create getter setter for that and you can use it.
Make use of the classes
public class GetSet {
public GetSet() {
super();
}
private static boolean passwordSet = false;
public static boolean isPasswordSet() {
return passwordSet;
}
public static void setPasswordSet(boolean passwordSet) {
GetSet.passwordSet = passwordSet;
}
}
You can access ths using GetSet.setPasswordSet(false);
and Boolean flag = GetSet.isPasswordSet();
Set the value as Global:
public class Global {
public static int mValue;
public static int getValue() {
return mValue;
}
public static void setValue(int mValue) {
Global.mValue = mValue;
}
}
I was looking for answers to that but I couldn't find it. So I found a way to do that.
First Activity
Intent intent = new Intent(this, SecondActivity.class);
intent.putExtra("Flag" , true);
startActivity(intent);
Second Activity
boolean flag;
flag = getIntent().getBooleanExtra("Flag" ,false);
if(flag == true)
{
this.finish();
}
So now you may send any data you want it will open the Second Activity and then immediately close it after you wouldn't even realize it. You may use Shared prefences to save your data for after usage.
I often find myself needing to access methods that require referencing some activity. For example, to use getWindowManager, I need to access some Activity. But often my code for using these methods is in some other class that has no reference to an activity. Up until now, I've either stored a reference to the main activity or passed the context of some activity to the class. Is there some better way to do this?
If you already have a valid context, just use this:
Activity activity = (Activity) context;
Passing context is better way for refrence Activity.
You can pass Context to another class.
IN Activity ::
AnotherClass Obj = new AnotherClass(this);
IN Another Class
class AnotherClass{
public AnotherClass(Context Context){
}
}
You can implement the necessary methods in your activity and implement a Handler. Then, simply pass a handler instance to your classes, where you can obtain a message for handler and send it to target.
You can make you application instance a singleton, and use it when you need a Context
An example is in this question:
Android Application as Singleton
This way, when you need a Context, you can get it with
Context context = MyApplication.getInstance()
This might not be the cleanest solution, but it has worked well for me so far
I found a way to get the Activity to a non-activity class that I have not seen discussed in forums. This was after numerous failed attempts at using getApplicationContext() and of passing the context in as a parameter to constructors, none of which gave Activity. I saw that my adapters were casting the incoming context to Activity so I made the same cast to my non-activity class constructors:
public class HandleDropdown extends Application{
...
public Activity activity;
...
public HandleDropdown() {
super();
}
public HandleDropdown(Activity context) {
this.activity = context;
this.context = context;
}
public void DropList(View v,Activity context) {
this.activity = context;
this.context = context;
...
}
After doing this cast conversion of Context to Activity I could use this.activity wherever I needed an Activity context.
I'm new to android so my suggestion may look guffy but what if you'll just create a reference to your activity as private property and assign that in OnCreate method? You can even create your CustomActivity with OnCreate like that and derive all your activities from your CustomActivity, not the generic Activity provided by android.
class blah extends Activity{
private Activity activityReference;
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
activityReference = this;
}
}
after that you could use that the way you want, i.e. in
Intent i = new Intent(activityReference, SomeOtherActivity.class)
etc
There are many ways for Activities communication.
you can use:
the startActivityForResult method
a system of broadcast message and receiver (you can broadcast an event from the actual activity, and register a receiver in the target activity. Remember that the target activity must be previously initialized and non finished)
as you say, store a reference of the target activity wherever you need.
We built a framework for this. We have a BaseActivity class that inherits from Activity and it overrides all the lifecycle methods and has some static (class) variables that keep track of the activity stack. If anything wants to know what the current activity is, it just calls a static method in BaseActivity that returns the activity on top of our privately-managed stack.
It is kinda hacky, but it works. I'm not sure I would recommend it though.
Handle the Intent in the class you want to do these methods, and send your information to it in a Bundle like so:
Intent i = new Intent("android.intent.action.MAIN");
i.setComponent(new ComponentName("com.my.pkg","com.my.pkg.myActivity"));
Bundle data = new Bundle();
i.putExtras(data);
startActivityForResult(i);
Then use an OnActivityResultListener to grab the new data.
I solved this by making a singleton class has an instance of the class below as a member.
public class InterActivityReferrer <T> {
HashMap<Integer, T> map;
ArrayList<Integer> reserve;
public InterActivityReferrer() {
map = new HashMap<>();
reserve = new ArrayList<>();
}
public synchronized int attach(T obj) {
int id;
if (reserve.isEmpty()) {
id = reserve.size();
}
else {
id = reserve.remove(reserve.size() - 1);
}
map.put(id, obj);
return id;
}
public synchronized T get(int id) {
return map.get(id);
}
public synchronized T detach(int id) {
T obj = map.remove(id);
if (obj != null) reserve.add(id);
return obj;
}
}
This class can get a T object and return a unique integer assigned to the object by attach(). Assigned integers will not collide with each other unless HashMap fails. Each assigned integer will be freed when its corresponding object is detached by detach(). Freed integers will be reused when a new object is attached.
And from a singleton class:
public class SomeSingleton {
...
private InterActivityReferrer<Activity> referrer = new InterActivityReferrer<>();
...
public InterActivityReferrer<Activity> getReferrer() {return referrer;}
}
And from an activity that needs to be referred:
...
int activityID = SomeSingleton.getInstance().getReferrer().attach(this);
...
Now with this, a unique integer corresponding to this activity instance is returned. And an integer can be delivered into another starting activity by using Intent and putExtra().
...
Intent i = new Intent(this, AnotherActivity.class);
i.putExtra("thisActivityID", activityID);
startActivityForResult(i, SOME_INTEGER);
...
And from the another activity:
...
id refereeID = getIntent().getIntExtra("thisActivityID", -1);
Activity referredActivity = SomeSingleton.getInstance().getReferrer().get(refereeID);
...
And finally the activity can be referred. And InterActivityReferrer can be used for any other class.
I hope this helps.
public static Activity getLaunchActivity()
{
final Class<?> activityThreadClass = Class.forName("android.app.ActivityThread");
final Method methodApp = activityThreadClass.getMethod("currentApplication");
App = (Application) methodApp.invoke(null, (Object[]) null);
Intent launcherIntent = App.getPackageManager().getLaunchIntentForPackage(App.getPackageName());
launchActivityInfo = launcherIntent.resolveActivityInfo(App.getPackageManager(), 0);
Class<?> clazz;
try
{
clazz = Class.forName(launchActivityInfo.name);
if(clazz != null)
return Activity.class.cast(clazz.newInstance());
}
catch (Exception e)
{}
return null;
}
Just a guess since I haven't done this but it might work.
1) Get your applicationContext by making your Android Application class a Singleton.
2) Get your ActivityManager class from the context.
3) Get a list of RunningTaskInfos using getRunningTasks() on the ActivityManager.
4) Get the first RunningTaskInfo element from the list which should be the most recent task launched.
5) Call topActivity on that RunningTaskInfo which should return you the top activity on the activity stack for that task.
Now, this seems like a LOT more work than any of the other methods mentioned here, but you can probably encapsulate this in a static class and just call it whenever. It seems like it might be the only way to get the top activity on the stack without adding references to the activities.
In an Android app, is there anything wrong with the following approach:
public class MyApp extends android.app.Application {
private static MyApp instance;
public MyApp() {
instance = this;
}
public static Context getContext() {
return instance;
}
}
and pass it everywhere (e.g. SQLiteOpenHelper) where context is required (and not leaking of course)?
There are a couple of potential problems with this approach, though in a lot of circumstances (such as your example) it will work well.
In particular you should be careful when dealing with anything that deals with the GUI that requires a Context. For example, if you pass the application Context into the LayoutInflater you will get an Exception. Generally speaking, your approach is excellent: it's good practice to use an Activity's Context within that Activity, and the Application Context when passing a context beyond the scope of an Activity to avoid memory leaks.
Also, as an alternative to your pattern you can use the shortcut of calling getApplicationContext() on a Context object (such as an Activity) to get the Application Context.
In my experience this approach shouldn't be necessary. If you need the context for anything you can usually get it via a call to View.getContext() and using the Context obtained there you can call Context.getApplicationContext() to get the Application context. If you are trying to get the Application context this from an Activity you can always call Activity.getApplication() which should be able to be passed as the Context needed for a call to SQLiteOpenHelper().
Overall there doesn't seem to be a problem with your approach for this situation, but when dealing with Context just make sure you are not leaking memory anywhere as described on the official Google Android Developers blog.
Some people have asked: how can the singleton return a null pointer?
I'm answering that question. (I cannot answer in a comment because I need to post code.)
It may return null in between two events: (1) the class is loaded, and (2) the object of this class is created. Here's an example:
class X {
static X xinstance;
static Y yinstance = Y.yinstance;
X() {xinstance=this;}
}
class Y {
static X xinstance = X.xinstance;
static Y yinstance;
Y() {yinstance=this;}
}
public class A {
public static void main(String[] p) {
X x = new X();
Y y = new Y();
System.out.println("x:"+X.xinstance+" y:"+Y.yinstance);
System.out.println("x:"+Y.xinstance+" y:"+X.yinstance);
}
}
Let's run the code:
$ javac A.java
$ java A
x:X#a63599 y:Y#9036e
x:null y:null
The second line shows that Y.xinstance and X.yinstance are null; they are null because the variables X.xinstance ans Y.yinstance were read when they were null.
Can this be fixed? Yes,
class X {
static Y y = Y.getInstance();
static X theinstance;
static X getInstance() {if(theinstance==null) {theinstance = new X();} return theinstance;}
}
class Y {
static X x = X.getInstance();
static Y theinstance;
static Y getInstance() {if(theinstance==null) {theinstance = new Y();} return theinstance;}
}
public class A {
public static void main(String[] p) {
System.out.println("x:"+X.getInstance()+" y:"+Y.getInstance());
System.out.println("x:"+Y.x+" y:"+X.y);
}
}
and this code shows no anomaly:
$ javac A.java
$ java A
x:X#1c059f6 y:Y#152506e
x:X#1c059f6 y:Y#152506e
BUT this is not an option for the Android Application object: the programmer does not control the time when it is created.
Once again: the difference between the first example and the second one is that the second example creates an instance if the static pointer is null. But a programmer cannot create the Android application object before the system decides to do it.
UPDATE
One more puzzling example where initialized static fields happen to be null.
Main.java:
enum MyEnum {
FIRST,SECOND;
private static String prefix="<", suffix=">";
String myName;
MyEnum() {
myName = makeMyName();
}
String makeMyName() {
return prefix + name() + suffix;
}
String getMyName() {
return myName;
}
}
public class Main {
public static void main(String args[]) {
System.out.println("first: "+MyEnum.FIRST+" second: "+MyEnum.SECOND);
System.out.println("first: "+MyEnum.FIRST.makeMyName()+" second: "+MyEnum.SECOND.makeMyName());
System.out.println("first: "+MyEnum.FIRST.getMyName()+" second: "+MyEnum.SECOND.getMyName());
}
}
And you get:
$ javac Main.java
$ java Main
first: FIRST second: SECOND
first: <FIRST> second: <SECOND>
first: nullFIRSTnull second: nullSECONDnull
Note that you cannot move the static variable declaration one line upper, the code will not compile.
Application Class:
import android.app.Application;
import android.content.Context;
public class MyApplication extends Application {
private static Context mContext;
public void onCreate() {
super.onCreate();
mContext = getApplicationContext();
}
public static Context getAppContext() {
return mContext;
}
}
Declare the Application in the AndroidManifest:
<application android:name=".MyApplication"
...
/>
Usage:
MyApplication.getAppContext()
You are trying to create a wrapper to get Application Context and there is a possibility that it might return "null" pointer.
As per my understanding, I guess its better approach to call- any of the 2
Context.getApplicationContext() or Activity.getApplication().
It is a good approach. I use it myself as well. I would only suggest to override onCreate to set the singleton instead of using a constructor.
And since you mentioned SQLiteOpenHelper: In onCreate () you can open the database as well.
Personally I think the documentation got it wrong in saying that There is normally no need to subclass Application. I think the opposite is true: You should always subclass Application.
I would use Application Context to get a System Service in the constructor. This eases testing & benefits from composition
public class MyActivity extends Activity {
private final NotificationManager notificationManager;
public MyActivity() {
this(MyApp.getContext().getSystemService(NOTIFICATION_SERVICE));
}
public MyActivity(NotificationManager notificationManager) {
this.notificationManager = notificationManager;
}
// onCreate etc
}
Test class would then use the overloaded constructor.
Android would use the default constructor.
I like it, but I would suggest a singleton instead:
package com.mobidrone;
import android.app.Application;
import android.content.Context;
public class ApplicationContext extends Application
{
private static ApplicationContext instance = null;
private ApplicationContext()
{
instance = this;
}
public static Context getInstance()
{
if (null == instance)
{
instance = new ApplicationContext();
}
return instance;
}
}
I'm using the same approach, I suggest to write the singleton a little better:
public static MyApp getInstance() {
if (instance == null) {
synchronized (MyApp.class) {
if (instance == null) {
instance = new MyApp ();
}
}
}
return instance;
}
but I'm not using everywhere, I use getContext() and getApplicationContext() where I can do it!
I know the original question was posted 13 years ago, and this is the Kotlin version of getting context everywhere.
class MyApplication : Application() {
companion object {
#JvmStatic
private var instance: MyApplication? = null
#JvmStatic
public final fun getContext(): Context? {
return instance
}
}
override fun onCreate() {
instance = this
super.onCreate()
}
}