How to get Activity/getWindow() from services java class? - java

I'm trying to run a function that requires passing it a screen capture. When I run this from the main activity, I can run the code like this:
SendScreenFunction(getWindow().getDecorView().getRootView(), getApplicationContext());
I'm not trying to call this function from a service and I can't access the getWindow() function because it requires an activity (which isn't available in the service). I was looking around online and someone suggested a function to get the activity so I can use the function. My current code looks like this:
public class ASTasks extends Service {
// This method run only one time. At the first time of service created and running
#Override
public void onCreate() {
HandlerThread thread = new HandlerThread("ServiceStartArguments",
Process.THREAD_PRIORITY_BACKGROUND);
thread.start();
Log.d("onCreate()", "After service created");
}
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
Toast.makeText(this, "Entered Timer!", Toast.LENGTH_SHORT).show();
Activity main_activity = getActivity(getApplicationContext());
try {
Log.i("Services", "Before crash");
SendScreenFunction(main_activity.getWindow().getDecorView().getRootView(), getApplicationContext());
Log.i("Services", "After crash");
} catch (IOException e) {
e.printStackTrace();
}
return START_STICKY;
}
#Override
public IBinder onBind(Intent intent) {
// We don't provide binding
return null;
}
public void SendScreenFunction(View view, Context context){
// Function goes here
}
public static Activity getActivity(Context context) {
if (context == null) return null;
if (context instanceof Activity) return (Activity) context;
if (context instanceof ContextWrapper) return getActivity(((ContextWrapper)context).getBaseContext());
return null;
}
}
Unfortunately, that solution doesn't seem to work and it's crashing. The Logcat error is shown below:
Process: com.example.ASservice:remote, PID: 15966
java.lang.RuntimeException: Unable to start service com.example.ASservice.ASTasks#6e7fed5 with Intent { cmp=com.example.ASservice/.ASTasks }: java.lang.NullPointerException: Attempt to invoke virtual method 'android.view.Window android.app.Activity.getWindow()' on a null object reference
at android.app.ActivityThread.handleServiceArgs(ActivityThread.java:5110)
at android.app.ActivityThread.access$2100(ActivityThread.java:310)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:2319)
at android.os.Handler.dispatchMessage(Handler.java:106)
at android.os.Looper.loopOnce(Looper.java:226)
at android.os.Looper.loop(Looper.java:313)
at android.app.ActivityThread.main(ActivityThread.java:8680)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:567)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1135)
Caused by: java.lang.NullPointerException: Attempt to invoke virtual method 'android.view.Window android.app.Activity.getWindow()' on a null object reference
at com.example.ASservice.ASTasks.onStartCommand(ASTasks.java:41)
at android.app.ActivityThread.handleServiceArgs(ActivityThread.java:5092)
at android.app.ActivityThread.access$2100(ActivityThread.java:310) 
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:2319) 
at android.os.Handler.dispatchMessage(Handler.java:106) 
at android.os.Looper.loopOnce(Looper.java:226) 
at android.os.Looper.loop(Looper.java:313) 
at android.app.ActivityThread.main(ActivityThread.java:8680) 
at java.lang.reflect.Method.invoke(Native Method) 
at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:567) 
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1135) 
Any ideas on the best way to take the screen capture from within the service (or even a way to pass a flag back to main to process it there)?
Any suggestions would be greatly appreciated. Thanks!

Related

NullPointerException Context errors on code moved from one working source into a Main application

Context is not a strong point of mine, I keep getting this error this is part of code i have moved over from another application and works in there just fine, however i am trying to transplant the code from the smaller app to this main app, as adding it as a library was causing headaches which are best sorted out another day.
So the error i receive is:
E/AndroidRuntime: FATAL EXCEPTION: main
Process: com.app, PID: 12564
java.lang.NullPointerException: Attempt to invoke virtual method 'android.content.Context android.content.Context.getApplicationContext()' on a null object reference
at androidx.localbroadcastmanager.content.LocalBroadcastManager.getInstance(LocalBroadcastManager.java:107)
at com.app.TManager.startUpdatingTrace(TManager.java:229)
at com.app.activities.ui.routeaction.RouteActionFragment$2.onFinish(RouteActionFragment.java:128)
at android.os.CountDownTimer$1.handleMessage(CountDownTimer.java:127)
at android.os.Handler.dispatchMessage(Handler.java:107)
at android.os.Looper.loop(Looper.java:214)
at android.app.ActivityThread.main(ActivityThread.java:7356)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:492)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:930)
So this is the relevant code in TManager:
public class TManager extends AppCompatActivity implements Serializable {
BroadcastReceiver sensorReceiver;
BroadcastReceiver locationReceiver;
ExecutorService executorService = Executors.newFixedThreadPool(20);
public static Intent locationIntent;
public static Intent sensorService;
public LocalBroadcastManager localBroadcastManager;
public static MutableLiveData<Integer> status = new MutableLiveData<Integer>();
//Empty constructor
public TManager(){}
#RequiresApi(api = Build.VERSION_CODES.O)
public void startUpdating() {
status.setValue(0);
//register for sensorBroadcast
sensorReceiver = new BroadcastReceiver() {
#Override
public void onReceive(Context context, Intent intent) {
TCIMUEvent tcimuEvent = (TCIMUEvent) intent.getSerializableExtra("imuevent");
// Log.d(TAG, "In Motion Received "+ tcimuEvent.getTime());
Runnable provideDM = new Runnable() {
#Override
public void run() {
//traceCWrapper.provideDeviceMotion(tcimuEvent, Status, 0, RotationMode.Undetermined);
}
};
executorService.execute(provideDM);
}
};
localBroadcastManager.getInstance(MyApplication.getAppContext()).registerReceiver(
sensorReceiver, new IntentFilter("imuCreated")
);
//register for locationBroadcast
locationReceiver = new BroadcastReceiver() {
#Override
public void onReceive(Context context, Intent intent) {
TCLocationEvent tcLocationEvent = (TCLocationEvent) intent.getSerializableExtra("locationevent");
Runnable provideLoc = new Runnable() {
#Override
public void run() {
traceCWrapper.provideLocation(tcLocationEvent);
}
};
executorService.execute(provideLoc);
}
};
LocalBroadcastManager.getInstance(context).registerReceiver( //Error Here <-----
locationReceiver, new IntentFilter("locationCreated")
);
isRunning = true;
//Start the Services
AsyncTask as1 = new AsyncTask() {
#Override
protected Object doInBackground(Object[] objects) {
startUpdatingLocation();
return null;
}
}.execute();
AsyncTask as2 = new AsyncTask() {
#Override
protected Object doInBackground(Object[] objects) {
startUpdatingSensors();
return null;
}
}.execute();
}
}
This is just one example i keep getting these errors all through the code which was copied in another example error:
java.lang.NullPointerException: Attempt to invoke virtual method 'android.content.res.AssetManager android.content.Context.getAssets()' on a null object reference
It seeems to especially be where is use
MyApplication.getAppContext......
MyApplication just returns as below:
public class MyApplication extends Application {
private static Context context;
public void onCreate() {
super.onCreate();
MyApplication.context = getApplicationContext();
}
public static Context getAppContext() {
return MyApplication.context;
}
}
How do i resolve these issues? The whole classes have been moved over it is not code taken from one class dumped into another. So not sure why context should have changed.
As i was using the MyApplication static context class in some places i needed to add this line to my Manifest file within the tag
android:name="com.yourapp.app.yourapp.MyApplication"
and make sure the application class is placed in the top level main/java/com.yourapp.app.yourapp/
This worked for me and solved the issue throughout the App. I would pay attention to the comments made as this may well not be the best way to be using Context, however this solved my issue at the moment.

How to move reusable functionalities to a generic class and invoke another activity from there?

I am new to Android development and I am facing an issue in invoking an activity from a generic class where I have a reusable function.
I have MainActivity where I need to check if the application has Network connectivity and then check if the user is already signed in.
If the user is signed in I need to open the Rate activity otherwise I will open the Login activity.
I thought I can keep the logic that checks the Network connectivity and shows the popup reusable and move it to a Global class as below
public class Global extends AppCompatActivity {
public static boolean hasConnectivity = false;
public static boolean userSignedIn = false;
String TAG = "Debug Log - Helper";
Context context;
#Override
public void onCreate(Bundle savedInstanceState){
super.onCreate(savedInstanceState);
context = this;
}
private void networkConnectionErrorDialog(final Context context, final Class targetClass){
Log.d(TAG, "Show Alert Dialog");
new AlertDialog.Builder(context)
.setTitle(R.string.connection_error_title)
.setMessage(R.string.connection_error_message)
.setIcon(R.drawable.warning)
.setPositiveButton(
R.string.try_again,
new DialogInterface.OnClickListener() {
#Override
public void onClick(DialogInterface dialog, int which) {
Log.d(TAG, "Trying Again");
isNetworkAvailable(context, targetClass);
}
}).show();
}
protected void isNetworkAvailable(Context context, Class targetClass) {
if(NetworkUtil.isConnected(context)){
Log.d(TAG, "Has connectivity");
if(targetClass != null){
Log.d(TAG, targetClass.toString());
Intent targetIntent = new Intent(context, targetClass);
startActivity(targetIntent);
}
hasConnectivity = true;
return;
}else{
Log.d(TAG, "Has no connectivity");
hasConnectivity = false;
networkConnectionErrorDialog(context, targetClass);
}
}
}
I pass in the targetClass as Login.class or Rate.class (based on user signed in state) from the MainActivity where isNetworkAvailable() is invoked.
I am getting the following error. Could someone help me fix the issue and help me understand if my approach needs improvement?
java.lang.RuntimeException: Unable to resume activity {com.solitontech.dayatsoliton/com.solitontech.dayatsoliton.MainActivity}: java.lang.NullPointerException: Attempt to invoke virtual method 'android.app.ActivityThread$ApplicationThread android.app.ActivityThread.getApplicationThread()' on a null object reference
at android.app.ActivityThread.performResumeActivity(ActivityThread.java:3581)
at android.app.ActivityThread.handleResumeActivity(ActivityThread.java:3621)
at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2862)
at android.app.ActivityThread.-wrap11(Unknown Source:0)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1589)
at android.os.Handler.dispatchMessage(Handler.java:106)
at android.os.Looper.loop(Looper.java:164)
at android.app.ActivityThread.main(ActivityThread.java:6494)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:438)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:807)
Caused by: java.lang.NullPointerException: Attempt to invoke virtual method 'android.app.ActivityThread$ApplicationThread android.app.ActivityThread.getApplicationThread()' on a null object reference
at android.app.Activity.startActivityForResult(Activity.java:4488)
at android.support.v4.app.BaseFragmentActivityJB.startActivityForResult(BaseFragmentActivityJB.java:50)
at android.support.v4.app.FragmentActivity.startActivityForResult(FragmentActivity.java:79)
at android.app.Activity.startActivityForResult(Activity.java:4445)
at android.support.v4.app.FragmentActivity.startActivityForResult(FragmentActivity.java:859)
at android.app.Activity.startActivity(Activity.java:4806)
at android.app.Activity.startActivity(Activity.java:4774)
at com.solitontech.dayatsoliton.Global.isNetworkAvailable(Global.java:50)
at com.solitontech.dayatsoliton.MainActivity.onResume(MainActivity.java:68)
at android.app.Instrumentation.callActivityOnResume(Instrumentation.java:1355)
at android.app.Activity.performResume(Activity.java:7117)
at android.app.ActivityThread.performResumeActivity(ActivityThread.java:3556)
It looks like your application is experiencing a null pointer exception in your activity's onResume method. If you had called startActivityForResult, make sure that the data in
#Override
protected void onActivityResult(int requestCode, int resultCode, Intent data)
{..}
is non null before processing it.
As for your question about starting an activity from your helper class Global, you can define a function like this.
private static void goToActivity(Context context, Class<?> activityClass){
Intent intent = new Intent(context, activityClass);
context.startActivity(intent);
}
You can call this method as below.
goToActivity(context,TargetActivity.class);
Good luck.
Intent targetIntent = new Intent(context, targetClass);
startActivity(targetIntent);
above code is wrong. You should pass your current activity and target activity here.
Intent intent = new Intent(CurrentActivity.this, TargetingActivity.class);
startActivity(intent);
As a example :
If you want to start ActivtyB form ActivtyA
Intent intent = new Intent(ActivityA.this, ActivityD.class);
startActivity(intent);
1st try to correct this error. then you can find some others.

java.lang.IllegalStateException in MediaPlayer

This is my code:
final MediaPlayer[] threeSound = new MediaPlayer[1];
threeSound[0] = new MediaPlayer();
final CountDownTimer playThreeSound = new CountDownTimer(1000, 1) {
boolean timerStarted = false;
#Override
public void onTick(long millisUntilFinished) {
torgText.setText("3...");
if (!timerStarted) {
timerStarted = true;
threeSound[0] = MediaPlayer.create(PlayActivity.this, R.raw.three);
try {
threeSound[0].prepare();
threeSound[0].start();
} catch (IOException e) {
e.printStackTrace();
Log.e("IOE", "Something went wrong");
}
}
}
#Override
public void onFinish() {
if (threeSound[0].isPlaying()) {
threeSound[0].stop();
}
playTwoSound.start();
}
};
It throws IllegalStateException. These are logs:
FATAL EXCEPTION: main
Process: testapplication.android.com.guesstune_v2, PID: 3641
java.lang.IllegalStateException
at android.media.MediaPlayer._prepare(Native Method)
at android.media.MediaPlayer.prepare(MediaPlayer.java:1351)
at testapplication.android.com.guesstune_v2.PlayActivity$6.onTick(PlayActivity.java:316)
at android.os.CountDownTimer$1.handleMessage(CountDownTimer.java:133)
at android.os.Handler.dispatchMessage(Handler.java:102)
at android.os.Looper.loop(Looper.java:145)
at android.app.ActivityThread.main(ActivityThread.java:7007)
at java.lang.reflect.Method.invoke(Native Method)
at java.lang.reflect.Method.invoke(Method.java:372)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1404)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1199)
What is wrong with preparing MediaPlayer? What should I add to the code? I'm a newbie, sorry for a probably stupid question and for bad English.
The documentation for MediaPlayer states:
MediaPlayer create (Context context, int resid)
Convenience method to create a MediaPlayer for a given resource id. On success, prepare() will already have been called and must not be called again.
https://developer.android.com/reference/android/media/MediaPlayer.html#create(android.content.Context, int)
So your IllegalStateException occurs because prepare() requires the MediaPlayer to be in either a Initialized or Stopped state, but when create(Context context, int resid) is invoked, it calls prepare() resulting in the MediaPlayer being in the Prepared state which it must not be when prepare() is invoked.
In short: remove the prepare() call and the IllegalStateException should no longer occur.
A full State Diagram and list of valid states is presented in the documentation.

Context for intent in onpostexecute is not null but getting null exception

I've been stumped with this problem for two days now. I've checked this forum and other forums but can't get a question or answer close enough to my problem.
Basically I'm trying to execute an intent to open an activity from a non-activities onpostexecute, I'm sending the context (MainActivty.this) and string from a onMarkerClick function that is in a method in the MainActivity. This is going to a constructor in the non-activity which has the parameters for context and the string.
The issue is that I'm getting a null exception, but after debugging, the context is not null, it has the value of MainActivity, but when the intent is executed it returns a null exception. I've also tried many variations eg. Activity, getApplicationContext, this.context, (classname).context, (classname).this and tried a global context to no avail. The odd thing is I put the intent into an if statement if(context != null) and it passes through and it executes the intent which in turn gives me null exception which doesn't make sense. I know I'm new to android if anyone has any other suggestions on opening the activity that would be great thanks very much.
E/AndroidRuntime: FATAL EXCEPTION: main
Process: com.example.quantusapps.joggertest, PID: 12253
java.lang.NullPointerException: Attempt to invoke virtual method 'java.lang.String android.content.Context.getPackageName()' on a null object reference
at android.content.ContextWrapper.getPackageName(ContextWrapper.java:131)
at android.content.ComponentName.(ComponentName.java:77)
at android.content.Intent.(Intent.java:4029)
at com.example.quantusapps.joggertest.BusCoachTramInfo.onPostExecute(BusCoachTramInfo.java:131)
at com.example.quantusapps.joggertest.BusCoachTramInfo.onPostExecute(BusCoachTramInfo.java:25)
at android.os.AsyncTask.finish(AsyncTask.java:632)
at android.os.AsyncTask.access$600(AsyncTask.java:177)
at android.os.AsyncTask$InternalHandler.handleMessage(AsyncTask.java:645)
at android.os.Handler.dispatchMessage(Handler.java:102)
at android.os.Looper.loop(Looper.java:155)
at android.app.ActivityThread.main(ActivityThread.java:5696)
at java.lang.reflect.Method.invoke(Native Method)
at java.lang.reflect.Method.invoke(Method.java:372)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1028)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:823)<
This is the Mainactivity Method with onMarkerClick
mGoogleMap.setOnMarkerClickListener(new GoogleMap.OnMarkerClickListener() {
#Override
public boolean onMarkerClick(Marker marker) {
String bctID = bctExtraMarkerInfo.get(marker.getId());
BusCoachTramInfo busCoachTramInfo = new BusCoachTramInfo(bctID, MainActivity.this);
busCoachTramInfo.execute(bctID);
return false;
}
});
This is the non-activity constructor.
Context context;
BusCoachTramInfo(String busstopID, Context context) {
this.context = context;
naptanIdUrl = "https://api.tfl.gov.uk/StopPoint/" + busstopID + "/Arrivals?app_key=" + tfl_API_KEY + "&app_id=9c0b3009";
}
This is where the null exception is happening.
#Override
protected void onPostExecute(TreeMap<Integer, String[]> Map) {
super.onPostExecute(Map);
Intent i = new Intent(context, BusArrivalTime.class);
context.startActivity(i);
One way to get things done is implementing the AsyncTask as part of a method which takes an instance of MainActivity as a parameter. The AsyncTask on the other hand would work with a WeakReference:
void doExecuteBusCoachTramInfo(final String busstopID, MainActivity activity){
final WeakReference<MainActivity> wrActivity = new WeakReference<MainActivity>(MainActivity.this);
new AsyncTask<Void, Void, TreeMap<Integer, String[]>>(){
#Override
protected TreeMap<Integer, String[]> doInBackground(Void... params)
{
// your code from BusCoachTramInfo here
}
#Override
protected void onPostExecute(TreeMap<Integer, String[]> integerTreeMap)
{
// get back to the original Activity if possible:
MainActivity activity = wrActivity.get();
if (activity != null){
Intent i = new Intent(activity, BusArrivalTime.class);
activity.startActivity(i);
}
}
}.execute();
}
This method may be part of MainActivity, but it can just as well belong to some other class.

Error java.lang.NullPointerException: Attempt to invoke virtual method 'java.lang.Object android.content.Context.getSystemService

I'm creating a simple Android Class that update a variable with the most recent value readed from some specific sensors (Light, temp and more), which I access it(sensor value) by getData() method, but i'm getting an error. I hope u can help me!
Here is my generic sensor class.
MySensor
public class mySensor extends Service implements SensorEventListener {
private SensorManager mSensorManager =null;
private Sensor s=null;
float data = 0;
public void onCreate(){
super.onCreate();
mSensorManager= (SensorManager) getSystemService(Context.SENSOR_SERVICE);
}
public mySensor(int type){
//HERE I'M GETTING THE ERROR
s= mSensorManager.getDefaultSensor(type);
}
public String getData(){
return String.valueOf(data);
}
#Override
public IBinder onBind(Intent intent) {
return null;
}
#Override
public void onSensorChanged(SensorEvent event) {
if (event.sensor.getType() == Sensor.TYPE_LIGHT) {
data = event.values[0];
}
}
#Override
public void onAccuracyChanged(Sensor sensor, int i) {
}
protected void onResume() {
mSensorManager.registerListener((SensorEventListener) this, s, SensorManager.SENSOR_DELAY_NORMAL);
}
protected void onPause() {
// super.onPause();
mSensorManager.unregisterListener((SensorEventListener) this);
}
}
Here is the log
...
E/AndroidRuntime: FATAL EXCEPTION: main
Process: project.luke.com.sensorreader, PID: 25297
java.lang.RuntimeException: Unable to start activity ComponentInfo{project.luke.com.sensorreader/project.luke.com.sensorreader.MainActivity}: java.lang.NullPointerException: Attempt to invoke virtual method 'android.hardware.Sensor android.hardware.SensorManager.getDefaultSensor(int)' on a null object reference
at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2460)
at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2522)
at android.app.ActivityThread.access$800(ActivityThread.java:169)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1421)
at android.os.Handler.dispatchMessage(Handler.java:111)
at android.os.Looper.loop(Looper.java:194)
at android.app.ActivityThread.main(ActivityThread.java:5546)
at java.lang.reflect.Method.invoke(Native Method)
at java.lang.reflect.Method.invoke(Method.java:372)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:967)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:762)
Caused by: java.lang.NullPointerException: Attempt to invoke virtual method 'android.hardware.Sensor android.hardware.SensorManager.getDefaultSensor(int)' on a null object reference
at project.luke.com.sensorreader.mySensor.<init>(mySensor.java:39)
at project.luke.com.sensorreader.MainActivity.onCreate(MainActivity.java:32)
at android.app.Activity.performCreate(Activity.java:5975)
at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1111)
at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2413)
at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2522) 
at android.app.ActivityThread.access$800(ActivityThread.java:169) 
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1421) 
at android.os.Handler.dispatchMessage(Handler.java:111) 
at android.os.Looper.loop(Looper.java:194) 
at android.app.ActivityThread.main(ActivityThread.java:5546) 
at java.lang.reflect.Method.invoke(Native Method) 
at java.lang.reflect.Method.invoke(Method.java:372) 
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:967) 
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:762) 
In my MainActivity class I simple call mLight=new mySensor(Sensor.TYPE_LIGHT); but this trigger the error, cause mSensorManager=null, always.
From your MainActivity:
Intent intent = new Intent(this, mySensor.class);
intent.putExtra("type", Sensor.TYPE_LIGHT);
and within your service:
#Override
public IBinder onBind(Intent intent) {
mSensorManager= (SensorManager) getSystemService(Context.SENSOR_SERVICE);
int type = intent.getExtras().get("type");
s= mSensorManager.getDefaultSensor(type);
return null;
}
then you can remove:
public mySensor(int type){
...
}
and eventually the code you wrote within the onCreate.

Categories