Generic classes in my application - java

I've created a few minor apps for Android while learning. Being a PHP developer, it's a challenge to get used to it.
I'm especially wondering how I could define a couple of "general" functions in a separate class. Eg I have a function that checks if network connection is available, and if not, shows a dialog saying that the user should enable it. Currently, that function exists in several of my activities. Of course that seems strange - I suppose it would be more logical to define it once and include it in the activites where needed.
I tried putting it in a new class, and included that class in the original activity. But that failed since eg getBaseContext() is not accepted anymore.
I'm wondering how to go ahead. What should I be Google-ing for ? What is this mechanism called?

You need to create class with static methods. Like this
public class HelperUtils {
public static void checkNetworkConnection(Context ctx) {...}
}
Then you can call it from any place like this:
HelperUtils.checkNetworkConnection(this.getContext());
Assuming current class has Context.
You should read books on general OOP concepts where different type of methods are explained.

You can for example create a class - let's call it NetworkUtils. In this class you can create static method boolean isNetworkConnectionAvailable() and return true if is available and false otherwise. In this class you can create another static method void showNoConnectionDialog(Activity activity) - and in this method you create dialog starting with
public static void showNoConnectionDialog(Activity activity) {
AlertDialog.Builder builder = new AlertDialog.Builder(this);
//setting message, listener etc. and finally
builder.create().show();
}
In your activity, where you want to check and handle network connection you should call:
if (!NetworkUtils.isConnectionAvailable(getApplicationContext())) {
NetworkUtils.showNoConnectionDialog(YourActivityClassName.this)
}
I guess this should work.

Related

Best way to return data to MainActivity from AsyncTask

I'm using an ASyncTask in my app to get some data (a short URL) via a REST API from a web service (Bitly).
When the ASyncTask completes I want to pass the result back to my MainActivity.
Getting the data back to the MainActivity is acheievd by using the onPostExecute method of the AsyncTask.
I've read and read and read about how to do this and there seem to be two general approaches.
Originally I was using a 'WeakReference' approach whereby at the start of the AsyncTask class you create a weak reference to your MainActivity as follows:
private class getShortURL extends AsyncTask<String, Void, String> {
private WeakReference<MainActivity> mainActivityWeakReference;
myASyncTask(MainActivity activity) {
mainActivityWeakReference = new WeakReference<>(activity);
}
{etc etc}
With this approach your AsyncTask class sits outside of your MainActivity class and so a lot of things need to be referenced via the weak reference.
This worked fine (except I suspected - possibly incorrectly - that this weak reference may have been the cause of occassional NPEs), but I then found another way of doing things.
This second approach involved moving the ASyncTask class inside of the MainActivity class.
This way I was able to access everything that was accessible in the MainActivity class directly, inlcuding UI elements and methods defined in the MainActivity. It also means that I can access resources such as strings etc and can generate toasts to advise the user what is happening.
In this case the whole of the WeakReference code above can be removed and the AsyncTask class can be made private.
I am also then able to do things like this directly in onPostExecute or to keep this in a method within the MainActivity that I can call directly from onPostExecute:
shorten_progress_bar.setIndeterminate(false);
shorten_progress_bar.setVisibility(View.INVISIBLE);
if (!shortURL.equals("")) {
// Set the link URL to the new short URL
short_link_url.setText(shortURL);
} else {
CommonFuncs.showMessage(getApplicationContext(), getString(R.string.unable_to_shorten_link));
short_link_url.setHint(R.string.unable_to_shorten_link);
}
(note that CommonFuncs.showMessage() is my own wrapper around the toast function to make it easier to call).
BUT, Android Studio then gives a warning that "the AsyncTask class should be static or leaks might occur".
If I make the method static I then get a warning that the method from the MainActivity that I want to call from onPostExecute cannot be called as it is non-static.
If I make that method from MainActivity a static method, then it cannot access string resources and any other methods that are non static - and down the rabbit hole I go!
The same is true, as you would expect, if I just move the code from the method in the MainActivity into the onPostExecute method.
So...
Is having an AsyncTask as a non-static method really a bad thing? (My
app seems to work fine with this warning in AS, but I obviously don't
want to be creating a memory leak in my app.
Is the WeakReference appraoch actually a more correct and safer approach?
If I use the WeakReference approach, how can I create things like toasts which need to be run on the UI thread and access string
resources etc from the MainActivity?
I read somewhere about creating an interface but got a bit lost and couldn't find that again. Also would this not have the same kind of reliance on the MainActivity that a WeakReference does and is that a bad thing?
I'm really looking for best practice guidance on how to get some data back to the MainActivity and the UI thread from an AsyncTask that is safe and doesn't risk memory leaks.
Is having an AsyncTask as a non-static method really a bad thing? (My app seems to work fine with this warning in AS, but I obviously don't want to be creating a memory leak in my app.
Yes, your Views and your Context will leak.
Enough rotations and your app will crash.
Is the WeakReference approach actually a more correct and safer approach?
It's lipstick on a dead pig, WeakReference in this scenario is more-so a hack than a solution, definitely not the correct solution.
What you're looking for is a form of event bus from something that outlives the Activity.
You can use either retained fragments* or Android Architecture Component ViewModel for that.
And you'll probably need to introduce Observer pattern (but not necessarily LiveData).
If I use the WeakReference approach, how can I create things like toasts which need to be run on the UI thread and access string resources etc from the MainActivity?
Don't run that sort of thing in doInBackground().
I'm really looking for best practice guidance on how to get some data back to the MainActivity and the UI thread from an AsyncTask that is safe and doesn't risk memory leaks.
The simplest way to do that would be to use this library (or write something that does the same thing yourself, up to you), put the EventEmitter into a ViewModel, then subscribe/unsubscribe to this EventEmitter inside your Activity.
public class MyViewModel: ViewModel() {
private final EventEmitter<String> testFullUrlReachableEmitter = new EventEmitter<>();
public final EventSource<String> getTestFullUrlReachable() {
return testFullUrlReachableEmitter;
}
public void checkReachable() {
new testFullURLreachable().execute()
}
private class testFullURLreachable extends AsyncTask<Void, Void, String> {
...
#Override
public void onPostExecute(String result) {
testFullUrlReachableEmitter.emit(result);
}
}
}
And in your Activity/Fragment
private MyViewModel viewModel;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
viewModel = ViewModelProviders.of(this).get(MyViewModel.class);
// ...
}
private EventSource.NotificationToken subscription;
#Override
protected void onStart() {
super.onStart();
subscription = viewModel.getTestFullUrlReachable().startListening((result) -> {
// do `onPostExecute` things here
});
}
#Override
protected void onStop() {
super.onStop();
if(subscription != null) {
subscription.stopListening();
subscription = null;
}
}

Call() is not public in android.telecom.Call, Cannot be accessed from outside package

I have the next class within SDK23 which should support playDtmfTone() :
import android.telecom.Call;
public class myDtmf {
public void myPlayDtmfTone() {
Call mytone = new Call(); // error here for Call()
mytone.playDtmfTone('0');
}
}
The Call() in the line 'Call mytone = new Call()' shows the error:
Call() is not public in android.telecom.Call, Cannot be accessed from outside package.
How can I make Call() public or make it accessible ?
Thank you very much.
In this specific case, referring to the Javadoc of Call:
[Call] Represents an ongoing phone call that the in-call app should present to the user.
So it doesn't really make sense to "create" an instance of it, since that requires you actually to create an actual phone call to some endpoint.
In general, if a method is not accessible outside the package, you aren't supposed to access it - it is not part of the API that the class developer has provided. There are ways to access it - specifically, reflection - but this is hacky and it is massively unlikely to be the way that you are meant to use the class.
The class may provide you with some other means to create an instance, like a static factory method (or an external factory) - but, for the reasons outlined above, that doesn't make sense in this case either.

Find Method usages only for specified class in Intelij-Idea

I am using IntelliJ IDEA and I have problem with method usage finding.
Suppose I have interface Worker.
public interface Worker {
void startWork();
void endWork();
}
And I have two implementations.
public class Develper implements Worker {
#Override
public void startWork() {
System.out.println("Developer Start Working");
}
#Override
public void endWork() {
}
}
public class Qa implements Worker {
#Override
public void startWork() {
System.out.println("QA start Work");
}
#Override
public void endWork() {
}
}
I open the Developer class and trying to find usages of startWork().
I want only to view usage of the Developer.startWork() implemented method.
But when I find usages it shows both Developer and Qa.startWork() method usages. How can I avoid Qa.startWork() method usage when finding Developer.startWork() usages?
Using Ctrl+Shift+Alt+F7 (⌘+⇧+⌥+F7 for Mac) should show the prompt from Jim Hawkins answer.
See: https://www.jetbrains.com/help/idea/find-usages-method-options.html
When you search for usages of a method implementation with this dialog Ctrl+Shift+Alt+F7, IntelliJ IDEA will ask whether or not you want to search for the base method. With any other find usages actions such as Alt+F7 or Ctrl+Alt+F7, the base method will be included in the search results automatically.
I'm using IntelliJ IDEA 15.0.1 .
I think what you see when using the "find usages" functionality depends from the context.
If you place the cursor in method name Developer.startWork and invoke find usages , you should see a small dialog. You are asked "Do you want to find usages of the base method?" .
If you say "No", and in your sources you did only call the method via the base class or interface (Worker.start() in your example), IDEA doesn't show you any hits. Thats correct.
If you call the overridden method via Developer.startWork() , and press "No" in the dialog, then you will see the usages of the specific implementation.
Update:
After reading the answer from #JimHawkins, I think the elephant is still in the room :) The question is, do you want to see where Developer.startWork() is actually called, or do you want to see where it is statically referenced?
Eg:
Developer developer = new Developer();
developer.startWork(); // you want to find only this?
Worker worker = developer;
worker.startWork(); // ..or this as well?
The find usages method can only tell, where a given method is statically referenced, but not where it is actually used (that is determined runtime via the mechanism of polymorphism).

Playing audio from different class?

I have 15 or so activities. Each one of them has a method, and I want to play audio in that method. Now, I have the obvious option to copy and paste the following line of code into each and every one of my activities Now, if I wanted to change something, I would have to go back into each and every one of my activities again. Here is the code:
MediaPlayer pop = MediaPlayer.create(CurrentActivity.this, R.raw.pop);
pop.start();
So, after searching the web for a few hours, I found that most people would just copy and paste it into each activity. So, I put the line of code (above) into a separate java class (which was a service by the way) tried to call that method in the service every time I needed to play the audio. So, I did the following:
public class TwentySeconds extends Service{
public void myPop(View view){
MediaPlayer pop = MediaPlayer.create(TwentySeconds.this, R.raw.pop);
pop.start();
}
}
Now, I got the error non static method cannot be referenced from static context. So, naturally, I tried to make method myPop static. Then, I got the error on TwentySeconds.this about being referenced from static context. So, it seems I am stuck. Changing the methods to static can't work, as I am trying to use an instance of the class as well using this. So, how should I go about calling method myPop where the MediaPlayer can successfully play?
Thanks for the advice,
Rich
Typically, if a utility method needs a Context, it is passed in.
public class Utilities {
public static void myPop(Context context){
MediaPlayer pop = MediaPlayer.create(context, R.raw.pop);
pop.start();
}
}
Utilities.myPop(CurrentActivity.this);

Passing objects between Android Activities, or config file?

I am trying to build my first android app. I have multiple Activities and I am using a Handler and an AssetFileDescriptor in order to play a sound file.
My problem is, how can I pass these objects around? I have one Activity that starts a timer via the handler, and another which stops the timer via the handler. Should I pass these objects around between Activities, or is there another way?
I am not used to Java, but I was wondering if I could make a config static class or something that creates all of these objects, and then each one of my Activities would just access these objects from this static config class. However, this has its own problems, since in order to call the method getAssets(), I cannot use a static class ("Cannot make a static reference to a non-static method.")
Any ideas?
This simplest solution would be to store objects in the Application class, here is a SO answer on the topic Using the Android Application class to persist data
Another more advanced option would be to use Dagger. It is a Dependency Injection framework that can do a lot of cool stuff but is somewhat difficult to get running (atleast took me some time to get working).
Dagger enables defining a Singleton class like this:
#Singleton
public class MySingletonObject {
#Inject
MySingletonObject() {
...
}
}
And whenever you need it in your app:
public class SomeActivityOrFragment {
#Inject MySingletonObject mySingletonObject;
...
mySingletonObject.start();
}
public class SomeOtherActivityOrFragment {
#Inject MySingletonObject mySingletonObject;
...
mySingletonObject.stop();
}

Categories

Resources