Get NullPointerException when calling getSystemService() - android

My problem is, that in onCreate() method of my MainActivity I am creating new Thread object to which I want to pass reference to this activity, and than in that thread use it to call getSystemService(). But in the end, when I start the app it crashes and I get NullPointerException.
I have already found that problem could be that I am passing reference to activity befor super.onCreate(), but in my code super.onCreate() is performed before passing the reference.
This is my MainActivity's onCreate() method
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
// Instance which contains thread for obtaining wifi info
final WifiInfoThread wifi_info = new WifiInfoThread(this);
....
}
And this is Thread class in which I am trying to get reference to system service
public class WifiInfoThread extends Thread {
// Constructor for passing context to this class to be able to access xml resources
Activity activity;
WifiInfoThread(Activity current) {
activity = current;
}
// Flag for stopping thread
boolean flag = false;
// Obtain service and WifiManager object
WifiManager current_wifi = (WifiManager) activity.getSystemService(Context.WIFI_SERVICE);
// Runnable object passed to UIThread
Runnable uirunnable = new Runnable() {
#Override
public void run() {
// Get current wifi status
WifiInfo wifi_info = current_wifi.getConnectionInfo();
// Things with showing it on screen
TextView tv_output = (TextView) activity.findViewById(R.id.tv_output);
String info = "SSID: " + wifi_info.getSSID();
info += "\nSpeed: " + wifi_info.getLinkSpeed() + " Mbps";
tv_output.setText(info);
}
};
public void run() {
flag = true;
for(; flag; ) {
activity.runOnUiThread(uirunnable);
try {
this.sleep(500);
}
catch(InterruptedException e) {}
}
}
}

You are using activity.getSystemService before initializing activity. To get ride of this, move below line into Constructor
// Obtain service and WifiManager object
WifiManager current_wifi = (WifiManager) activity.getSystemService(Context.WIFI_SERVICE);
Like
WifiManager current_wifi;
WifiInfoThread(Activity current) {
activity = current;
current_wifi = (WifiManager) activity.getSystemService(Context.WIFI_SERVICE);
}

move the initialitation current_wifi in the Constructor of your Thread.
// Obtain service and WifiManager object
WifiManager current_wifi = (WifiManager) activity.getSystemService(Context.WIFI_SERVICE);
in your case, activity is still a null reference. It gets a valid one after you assign it in the constructor

The other answers show you how to fix this. You should also know what is the reason for the NullPointerException: In java your code does not get executed in the order you write it. Every thing written outside of member functions (methods) gets executed first (sort of). Then the constructor is called. Hence you are calling Conetxt.getSystemService() on activity, which is null.
Also for background work, android has AsyncTask and IntentService. Look them up.

Related

Method skips a synchronous operation working asynchronously

Using Retrofit to check values in database for a login operation. I don't want to move forward without checking this thus want this to occur synchronically.
I am using the execute method instead of enqueue but still getting the result asynchronously. I understand if I do it all in the same class, it might work but I am trying to keep things separately to prevent code duplicate for other future calls. Please advice what I am doing wrong or how I could go about addressing this. Thanks.
Following method occurs when I click a submit button. This method is at my Activity.
Note that everything in this method works. Problem is after startService, it doesn't wait to get information from my rest service and instead jumps straight to the Toast. After that it carries on to perform the execute method which is useless by then.
private void sendLoginRequest(User user){
String token = verificationHelper.createToken(properties.API_KEY, user, 60000);
Retrofit retrofit = retrofitHelper.getRetrofit(properties.BASE_URL);
UserRepository userRepository = retrofit.create(UserRepository.class);
Call<User> call = userRepository.login(token);
if(call != null){
syncService = new SyncService(call);
Intent i = new Intent(this, SyncService.class);
startService(i);
if(verificationHelper.isValidLogin()){
goToMainActivity();
}
}
Toast.makeText(this, "Invalid Login", Toast.LENGTH_SHORT).show();
}
This is my service which gets into the onHandleIntent method after the Toast is called. (Expecting this to be called first and validated before ever going to the Toast).
public class SyncService extends IntentService {
private VerificationHelper verificationHelper = new VerificationHelper();
private PropertiesUtil properties = new PropertiesUtil();
private RetrofitHelper retrofitHelper = new RetrofitHelper(verificationHelper, properties);
private static Call<User> staticCall;
public SyncService(Call<User> call) {
super("SyncService");
staticCall = call;
}
public SyncService(){
super("SyncService");
}
#Override
protected void onHandleIntent(Intent intent) {
retrofitHelper.performCallBackSync(staticCall);
}
}
This is over at my RetrofitHelper for reference.
public class RetrofitHelper {
private VerificationHelper verificationHelper;
private PropertiesUtil properties;
public RetrofitHelper(VerificationHelper verificationHelper, PropertiesUtil properties) {
this.verificationHelper = verificationHelper;
this.properties = properties;
}
public void performCallBackSync(Call<User> call){
try {
// some logic that handles and verifies token values.
verificationHelper.setValidLogin(true);
} catch (IOException e) {
//some error handling
}
}
}

Using common function in multiple activity android

I want to use common function in multiple activity. How can I achieve this?
In my application I am displaying a Dialog box which have some data coming from some api. And this Dialog box, used in multiple activities. Right now I have implemented same Dialog box in all activities. Now I want common Dialog box for all activities. I am using this Dialog box in activity as well in adapter.
How could I do this? Using extends or using fragment.
I am already extending some class so I can not extend again( As I read, we can not extends more than one class.).
Also I want to pass some value to this function and based on return value I want to call another function.
private boolean allGroupsEdit(final String type) {
String allGroups = "allGroups";
final String url = Constants.CONSTANT_SERVER_URL + Constants.CONSTANT_GET_GROUPS_URL;
final ProgressDialog dialog = new ProgressDialog(context);
dialog.setMessage(context.getResources().getString(R.string.please_wait));
dialog.show();
StringRequest allGroupsRequest = new StringRequest(Request.Method.POST, url, new Response.Listener<String>() {
#Override
public void onResponse(String s) {
final SharedPreferences sharedPreferencesRemember = PreferenceManager.getDefaultSharedPreferences(context);
sessionGroupId = sharedPreferencesRemember.getString(Constants.CONSTANT_session_group_id, "");
try {
JSONObject jsonObject = new JSONObject(s);
JSONArray jsonArray = jsonObject.optJSONArray(Constants.CONSTANT_data);
int a = jsonArray.length();
for (int i = 0; i < jsonArray.length(); i++) {
JSONObject schObj = jsonArray.optJSONObject(i);
schData = schObj.optJSONArray(Constants.CONSTANT_data);
}
dialog.dismiss();
final Dialog dialog = new Dialog(context);
dialog.requestWindowFeature(Window.FEATURE_NO_TITLE);
dialog.getWindow().setBackgroundDrawable(new ColorDrawable(Color.TRANSPARENT));
dialog.setContentView(R.layout.dialog_checkbox_options);
Window window = dialog.getWindow();
window.setLayout(DrawerLayout.LayoutParams.MATCH_PARENT, DrawerLayout.LayoutParams.WRAP_CONTENT);
if(..someting){
editPublicComments(type);
}else{
editPublicPosts(type);
}
}catch(){}
}
}
Note: This a very long function so I am pasting some code for basic understand. If u need anything more detail let me know. Thanks in advance and editing and suggestions are welcome.
Edit_1: I want this whole function to be common.
Edit_2: How to return value to activity from utils ?
Edit_3: Now I created a static function in a class and I am able to call it from my activity. Now I want call another function based on common function result. (I am using SharedPreferences to store value of common function).
But in my activity where I called a common function, I doesn't execute common function first. It call another function then It call common function and after completing common method, it doesn't call another method again.
All I want to call another function based on result of common function which is true or false
boolean abab = CommonGroupBox.allGroupsEdit(context,"share", selectedPostId, localGrpArray);
if (abab){
boolean pubFlag = pref.getBoolean("isPublicFlag", false);
String qType = pref.getString("questionType","0");
if (pubFlag) {
editPublicComments(qType);
}else{
ediComments(qType);
}
else{
boolean pubFlag = pref.getBoolean("isPublicFlag", false);
String qType = pref.getString("questionType","0");
if (pubFlag) {
PublicComments(qType);
}else{
Comments(qType);
}
}
Here it doesn't call CommonGroupBox.allGroupsEdit firsts. It is called after if and else loop.
Just create a normal java class
public class Utility {
//your common method
public static void showDialog(Context context,int type){
//TODO task
}
}
Now you can use the showDialog method any where in your application
Utility.showDialog(ctx,type);
You can create an abstract class which extends AppCompatActivity, implement your method there and make all your other activities extend this class:
public abstract class BaseActivity extends AppCompatActivity {
protected boolean allGroupsEdit(final String type) {
// ...
}
// Other methods
}
Then implement your activity as :
public class MainActivity extends BaseActivity {
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
allGroupsEdit("Some type");
}
...
To create a Utility Class:
1) Create a Java file with name AppUtil which extends Activity.
2) Select a common method that you are going to use in your Application.
3) Write the function in AppUtil java file
4) Make all the function as static in your Java file so it can be easy to call inside your activity (example: AppUtil.yourMethod() )
5) Pass the context of your Activity.
Here is a simple example to check internet connection:
public class AppUtilities extends Activity {
public static boolean isInternetConnected(Context context) {
ConnectivityManager cm = (ConnectivityManager)
context.getSystemService(Context.CONNECTIVITY_SERVICE);
NetworkInfo netInfo = cm.getActiveNetworkInfo();
return netInfo != null && netInfo.isConnectedOrConnecting() &&
netInfo.isAvailable();
}
}
And you can easily call this method from anywhere in your Application
example ::
AppUtilities.isInternetConnected(YourActivity.this);

Android. How can I test a method which uses an Intent over the activity Context

After three days trying to find this over this website and others, I really need your help.
I want to test a method in a class. This method uses the activity class context to call an intent.
When I call it from the test method i get a NullPointerException.
How can i do this? (add example code please).
Accesories is the ActivityClass.
The Method in the Docking class:
public boolean powerConnected() {
boolean res = false;
IntentFilter filter = new IntentFilter(Intent.ACTION_BATTERY_CHANGED);
Context cont = Accessories.context;
Intent intent = cont.registerReceiver(null, filter); --Throws the exception
int plugged = intent.getIntExtra(BatteryManager.EXTRA_PLUGGED, -1);
if(plugged == BatteryManager.BATTERY_PLUGGED_AC){
Log.d(TAG, "AC "+plugged);
res = true;
}else if (plugged == BatteryManager.BATTERY_PLUGGED_USB){
Log.d(TAG, "USB "+plugged);
res = false;
}
return res;
}
The testing Method:
#Test
public void testPowerConnected_AssertParamConnected_ReturnTrue() {
Docking docking = new Docking();
boolean result = docking.powerConnected();
assertTrue(result);
}
Thank you so much.
You could refractor your code to give the context as a parameter to your method:
public boolean powerConnected(Context cont) {
....
}
so that when you call it with your test, you can use a MockContext
class CustomMock extends MockContext {
Intent registerReceiver(BroadcastReceiver receiver, IntentFilter filter) {
// You can return a MockIntent based on your testing needs.
}
}
#Test
public void testPowerConnected_AssertParamConnected_ReturnTrue() {
Docking docking = new Docking();
MockContext cont = new CustomMock ();
boolean result = docking.powerConnected(cont);
assertTrue(result);
}
Just found the solution.
If the TestClass extends AndroidTestCase and not ActivityInstrumentationTestCase2 as I had,
there is a protected mContext in the AndroidTestCase that stores the context as a field.
After that, the only I have to do is pass this context to my method to test.
so the final code will be just this:
#Test
public void testPowerConnected_AssertParamA1Connected_ReturnTrue() {
Docking docking = new Docking();
//MockContext context = new CustomMock();
boolean result = docking.powerConnected(mContext);
assertTrue("Expected true and get "+result,result);
}
Have you considered making the powerConnected() function static? Then there would be no need for the
Docking docking = new Docking()
which I imagine is causing your problems....if it isn't then I recommend posting the LogCat output.
If Docking is a subclass of Activity, you cannot do this:
Docking docking = new Docking();
Only the Android framework can instantiate Android components (Activity, Service, BroadcastReceiver, ContentProvider), because it doesn't just call the constructors, it also sets up the appropriate Context.
You can only test a method of the activity, if it is being called within the context of that activity. This means that you need to actually have Android create the activity first and then you can test methods within that activity.
Your other option is to change the method so that it uses the Application context using getApplicationContext() instead of the activity context. In that case you wouldn't have to create an instance of the activity just to call this method.

How to open Activity.openOptionsMenu() from a service

I have a service (it's for communications) that needs to call openOptionsMenu() of the current running activity. I have about 3 or so activities that need to show their options menu upon this request from the service. How can I find this current running activity?
What I'd suggest is that from the active Activity you call bindService() and open a connection to the service. One of the methods defined on your Service's binder connection should take a Binder as an argument. The Activity will instantiate this Binder and pass it into the Service's binder method. When the interesting event happens, the Service should invoke a method on Binder that the Activity passed it.
When one of your Activities goes into the background, it should unregister the Binder it previously passed in and unbind from the Service.
So, you've have an AIDL for the Service that looks something like
interface IServiceConnection {
void registerCallback(IActivityCallback callback);
void unregisterCallback(IActivityCallback callback);
}
Then you have an IActivityCallback.aidl that looks like
oneway interface IActivityCallback {
void openOptionsMenu();
}
In your Service you have
private ArrayList<IActivityCallback> mCallbacks = new ArrayList<IActivityCallback>();
private IServiceConnection.Stub mBinder = new IServiceConnection.Stub() {
public void registerCallback(IActivityCallback callback) {
mCallbacks.add(callback);
}
public void registerCallback(IActivityCallback callback) {
mCallbacks.remove(callback);
}
}
private void onEvent() {
for (int ptr = mCallbacks.size() - 1; ptr > -1; ptr--) {
mCallbacks.get(ptr).openOptionsMenu();
}
}
In your Service's onBind method you return mBinder.
In your activity you have
private IActivityCallback.Stub mPlayerBinder = new IActivityCallback.Stub() {
public void openOptionsMenu() {
// call method in Activity to show options menu
}
}
You bind to your Service from your Activity with a bindService call and when the ServiceConnection receives onServiceConnected you cast its stub to IServiceConnection and then invoke the registerCallback method.
I don't advise that plan of action. Manipulating and UI features without the users permission and foreknowledge is unkind. But to do it, you will need a solid reference to your Activity maintained via a static field or a field in your Application extension (or a singleton state machine etc...).

How to reference the current or main activity from another class

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.

Categories

Resources