getContentResolver in Separate Class - java

I need a class to get the artists, albums and tracks on the device, which I will then use JNI to call upon.
At the moment, in its barebones, the following causes a crash.
public class AndroidMediaLibray extends Activity {
public void getArtists() {
getContentResolver();
}
}
How do I get this to not crash?

The problem you have, is that you need to call getContentResolver() on a Context. If you call it in an Activity, you automatically call it on the Context of the Activity. But you (probably) never really start AndroidMediaLibrary. Please refer to the documentation of activities. If you want to have the DB call in an extra class, you may have a look at the following code. I have created a class with static methods. I just need to pass the context of my given Activity to that class. In your case that class might look like this:
public class AndroidMediaLibrary {
public static List<String> getArtists(Context context){
ArrayList<String> retVal = new ArrayList<String>();
ContentResolver resolver = context.getContentResolver();
// some more stuff here..
return retVal;
}
}
You may call that function from your MainActivity with:
List<String> myValues = DBUtils.someFunction(MainActivity.this);

Related

"Cannot resolve method getResources" when trying to execute getResources in non-activity method using method widely advocated here

I have been trying to use getResources in a non-activity class. I found some advice on how to do so here. To use one of the suggested ways, by Lilzilala, (there are multiple, but mostly suggest the same thing), I have created a special class, used this to specify the resources as "res", and then instantiated this class using "new" in a line which invokes "getResources".
However, I'm getting a "cannot resolve method getResources" error on "getResources". I'm a bit of a noob, but don't know why this is happening. From what I can tell, this error happens when there simply isn't a resource with that name available. Which makes me think maybe Resources doesn't contain getResources() by default?
class executeTrimmer<Resdefine> {
public class ResDefine {
private Resources res;
public ResDefine(Resources res)
{
this.res = res;
}}
Bitmap img1 = BitmapFactory.decodeResource(new ResDefine(getResources()),
R.drawable.bmpname);
}
EDIT - following suggestions that I add context, I have tried this:
class executeTrimmer<Resdefine> {
private static Context context;
public executeTrimmer(Context context){
this.context = context;
}
public class ResDefine {
private Resources res;
public ResDefine(Resources res)
{
this.res = res;
}}
Bitmap img1 = BitmapFactory.decodeResource(new ResDefine(executeTrimmer.context.getResources),
R.drawable.bmpname);
But this still brings up error "cannot resolve symbol getResources". I've tried multiple different ways to pass context to it, and consistently faced the same error.
As you can see in the official documentation, "getResources" is Context's method, therefore you can't call it out from nowhere, neither statically. This method requires a context instance.
In your case you must at least pass a context to your class to be able to invoke it as next:
context.getResources()
I think you got confused from seen it being directly called inside Activities without a prefixed context, but as all Activities are actually a context, this is why there is no prefix.
To clarify. When called inside an activity, this:
getResources()
is the same as this:
this.getResources()
where the prefix "this." refers to the activity, which in turn is a context by itself.
On the other hand your code should be like next, without the ResDefine class. And notice that the decodeResource call is required to be inside a method and not at class level scope (this is not allowed in Java). And in fact you don't even need to use a context, so pass instead the Resources instance from the caller's class which is supposed to hold the context:
public class executeTrimmer {
private final Resources res;
public executeTrimmer(final Resources res) {
this.res= res;
}
public void loadBitmap()
Bitmap img1 = BitmapFactory.decodeResource(this.res, R.drawable.bmpname);
........
}
}
And for the caller, next a very naive example, so may get an idea:
public class MainActivity extends Activity {
#Override
protected void onCreate(#Nullable final Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
new executeTrimmer(this.getResources()).loadBitmap();
}
}

Wrong 1st argument type. Found: 'com.example.sunshine.FetchData', required: 'android.content.Context'

I guess this question is more about understanding context and how to use it properly.
After having googled and "stackoverflowed" a lot I could not find the answer.
Problem:
when using DateUtils.formatDateTime I cannot use "this" as a context. The error message is as described in the title.
Application Info:
This is a simple weather app retrieving weather information via JSON and displaying it on the screen.
Activities:
- MainActivity.java
- FetchData.java
MainActivity: displaying the info
FetchData: getting JSON info from the API, formatting it and sending it back to MainActivity
I am using DateUtils.formatDateTime in the FetchData.java activity and using "this" as a context does not work.
As from my understanding Context provided the "environment" (?) of where the method is being called.
Why is the "environment" of FetchData not valid?
What content should be provided instead?
Help is much appreciated.
Thank you :)
Code:
private ArrayList<String> getWeatherDataFromJson(String forecastJsontStr) throws JSONException {
ArrayList<String> dailyWeatherInfo = new ArrayList<>();
int dataCount;
DateUtils tempDate = new DateUtils();
JSONObject weatherData = new JSONObject(forecastJsontStr);
JSONArray threeHourWeatherData = weatherData.getJSONArray(JSON_LIST);
dataCount = weatherData.getInt("cnt");
JSONObject tempJSONWeatherData;
for (int i = 0; i < dataCount; i++) {
tempJSONWeatherData = threeHourWeatherData.getJSONObject(i);
tempDate.formatDateTime(this,tempJSONWeatherData.getLong("dt"),
DateUtils.FORMAT_SHOW_DATE | DateUtils.FORMAT_SHOW_WEEKDAY |
DateUtils.FORMAT_ABBREV_ALL);
[more code here]
return dailyWeatherInfo;
}
Edit: I just realized I left out an important detail, namely this activity extends AsyncTask. After some further research apparently you provide the context bei adding WeakReference and then adding context in the constructor.
I added the following code:
private WeakReference<Context> contextWeakReference;
public FetchData (Content context) {
contextWeakReference = new WeakReference<>();
}
tempDate.formatDateTime(contextWeakReference.get(),tempJSONWeatherData.getLong("dt"),
DateUtils.FORMAT_SHOW_DATE | DateUtils.FORMAT_SHOW_WEEKDAY |
DateUtils.FORMAT_ABBREV_ALL);
This made the error disappear but I still don't understand why "this" doesn't work.
I am using DateUtils.formatDateTime in the FetchData.java activity and
using "this" as a context does not work. As from my understanding
Context provided the "environment" (?) of where the method is being
called.
You're incorrect, Context is Android context which is (from documentation):
Interface to global information about an application environment. This
is an abstract class whose implementation is provided by the Android
system. It allows access to application-specific resources and
classes, as well as up-calls for application-level operations such as
launching activities, broadcasting and receiving intents, etc.
DateUtils.formatDateTime() needs Context as one of its parameter. So, you need to pass a context.
Android Activity is sub class of Context, so you can use this (which refer to itself) as the context like the following:
public class MyActivity extends Activity {
...
protected void doSomething() {
// this refer to the MyActivity instance which is a Context.
DateUtils.formatDateTime(this, ...);
}
...
}
You need to pass the Context for every class that is not a Context subclass.
You can't use this in AsyncTask because it's not a Context subclass. So, you need to pass the Context using WeakReference to avoid Context leaking, like the following:
private class AsyncTaskRunner extends AsyncTask<String, String, String> {
private WeakReference<Context> contextWeakReference;
public FetchData (Content context) {
contextWeakReference = new WeakReference<>();
}
private void doSomething() {
// We have the context from the WeakReference
Context context = contextWeakReference.get();
DateUtils.formatDateTime(context, ...);
}
}
Last, you don't need to create a DateUtils object when calling DateUtils.formatDateTime(), so this isn't necessary:
DateUtils tempDate = new DateUtils();
tempDate.formatDateTime(...);
You can directly call it because it's a static method:
DateUtils.formatDateTime(...);
tempDate.formatDateTime(this,tempJSONWeatherData.getLong("dt"), instead of this you can pass context of application, this refers on class FetchData

How to call a method contained in an Android activity?

I have an Activity-class with a method called getPacketNames() that returned the names of some installed packages.
private ArrayList<CharSequence> getPackageNames(){
ArrayList<CharSequence> packageNames = new ArrayList<>();
List<PackageInfo> packagesInfos = getPackageManager().getInstalledPackages(0);
for(PackageInfo packageInfo: packagesInfos){
if(!isSystemApp(packageInfo)){
packageNames.add(packageInfo.packageName);
}
}
return packageNames;
}
I want to make it easy for someone else to call this method from another class. However, in order to do so, they would have to create an instance of the activity. This seems cumbersome, and not correct.
Is thee any way I can create this method outside of an Activity? When I create a separate class and copy-paste the method it does not work, because getPackageManager().getInstalledPackages(0) seems to need to be in an activity.
You should't attempt to do that. Instead create a UtilityClass and make your getPackageNames() as static method.
public final class MyUtils {
public static ArrayList<CharSequence> getPackageNames(final Context context){
ArrayList<CharSequence> packageNames = new ArrayList<>();
List<PackageInfo> packagesInfos = context.getPackageManager().getInstalledPackages(0);
for(PackageInfo packageInfo: packagesInfos){
if(!isSystemApp(packageInfo)){
packageNames.add(packageInfo.packageName);
}
}
return packageNames;
}
private static boolean isSystemApp(...){
...
}
}
Then from the Activity, you can access it as follows:
MyUtils.getPackageNames(this);
Sagar's answer is correct and you should follow that. If you are going to create a util class don't forget to add a private constructor, so that your util class will not be instantiated.
For a "hacky" and bad solution, you can always define your method as public static in your activity class and call it from elsewhere with YourActivity.methodname. But this approach will fail especially if you experiment with Don't Keep Activities option.

Can't call a method from outside of a java class

I have a method name checkForUpdate() in UpdateActivity.java. It looks like this:
#NonNull
#SuppressWarnings("deprecation")
protected String checkForUpdate(int curVersionCode) {
HttpClient httpclient = new DefaultHttpClient();
...
}
I am trying to call it from anotherActivity. So I'm trying to use code like this:
private void callFromAnotherActivity() {
UpdateActivity updateApp = new UpdateActivity();
String result = updateApp.checkForUpdate(...);
}
so when I type updateApp. then a list of the methods of UpdateActivity.java appears but there is no checkForUpdate() method. Why?
so when I type updateApp. then a list of the methods of UpdateActivity.java appears but there is no checkForUpdate() method. Why?
This is because your method is not public and probably you haven't import the UpdateActivity.
Please be noted that you can't create an Activity by calling the following:
UpdateActivity updateApp = new UpdateActivity();
You need to use something like this:
// context is your activity context.
Intent updateApp = new Intent(context, UpdateActivity.class);
context.startActivity(updateApp);
My suggestion:
You need to move the checkForUpdate method from UpdateActivity and make it as an util. So, other activity using the method won't be dependent and coupled with UpdateActivity. Localize the method to an utility class something like this:
public class UpdateUtil {
...
#NonNull
#SuppressWarnings("deprecation")
public static String checkForUpdate(int curVersionCode) {
HttpClient httpclient = new DefaultHttpClient();
...
}
}
and then use the method with:
UpdateUtil.checkForUpdate(1);
If you can't move the code (e.g, you don't have ownership of the code), you can do these things:
Make the checkForUpdate as static method
Use EventBus to tell the UpdateActivity to do the update.
You should not create an instance of the activity class. It is wrong. Activity has ui and lifecycle and activity is started by startActivity(intent)
Check here : call a method in another Activity

Call a class with AsyncTaks from a static class

I am trying to initialize a class that calls another class that uses AsyncTask. I am using GetDataFromDB gDataFromDB = new GetDataFromDB() but that does not initialize the class, it just gives me access to any static methods in the class. So what do I do to get the onCreate method to run? I have tried using intent but keep getting an error because this is a static class
public class FacadeDataFromDB extends Activity {
static ArrayList<HashMap<String, String>> visitorsList;
private static FacadeDataFromDB dataFromDB;
static boolean accessDB = false;
private FacadeDataFromDB() {
}
public static void initInstance() {
}
public static FacadeDataFromDB getInstance() {
if (dataFromDB == null) {
// Create the instance
dataFromDB = new FacadeDataFromDB();
}
return dataFromDB;
}
public static void setData() {
if (!accessDB) {
GetDataFromDB gDataFromDB = new GetDataFromDB();
accessDB = true;
}
// visitorsList = gDataFromDB.returnInfoFromDB();
}
public static ArrayList<HashMap<String, String>> getVisitorForDay() {
// TODO Auto-generated method stub
setData();
return visitorsList;
}
}
GetDataFromDB is the other class that I am calling. The current class is a static class and uses a singleton because I only want one initialization of the class the gets data from the db. If you have more questions or want me to post code let me know. Thanks
It seems to me that your two classes FacadeDataFromDB GetDataFromDB should not inherit Activity
Activities are made for GUI and user-interaction (I don't see any in your example) and their life-cycle is managed by the framework : you never create them manually with new.
See the android tutorial : https://developer.android.com/guide/components/activities.html and Activity javadoc : https://developer.android.com/reference/android/app/Activity.html.
I'm not sure that you completely understand the Android runtime. You should start Activities using Intent objects, not by creating them with the new keyword as you are. To ensure that your onCreate() method is called within your Activity, you could launch an explicit Intent from some other Activity/Context: Intent intent = new Intent(currentContext, FacadeDataFromDB.class);.
Also, when it comes to Activities, you shouldn't use private constructors. See this post for reasons why.

Categories