getting error when updating location in background - android

I am trying to update the location in the background and foreground so first, I have defined two buttons like update and remove button. so when I click update then it will update the location in the background and remove for removing location listener.
but after some time I want to remove those buttons and when I open that activity then it should update location automatically without button click.
so I decided to remove code from the update button (Start location update) and copy-paste into oncreate method. so that it will update whenever activity opened without clicking on the button. now I'm getting null pointer exception pls someone helps me
I am attaching my complete code.
public class UserLocation extends AppCompatActivity implements SharedPreferences.OnSharedPreferenceChangeListener {
DatabaseReference publiclocation;
private static final int MY_PERMISSION_REQUEST_CODE = 7171;
private static final int PLAY_SERVICES_RES_REQUEST = 7172;
private LocationRequest mlocationRequest;
String uid;
SharedPreferences settings;
Button requestLocation, removeLocation;
MyBackgroundService mService = null;
boolean mBound = false;
private final ServiceConnection mServiceConnection = new ServiceConnection() {
#Override
public void onServiceConnected(ComponentName name, IBinder iBinder) {
MyBackgroundService.LocalBinder binder = (MyBackgroundService.LocalBinder) iBinder;
mService = binder.getService();
mBound = true;
}
#Override
public void onServiceDisconnected(ComponentName name) {
mService = null;
mBound = false;
}
};
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_user_location);
publiclocation = FirebaseDatabase.getInstance().getReference(Common.PUBLIC_LOCATION);
FirebaseUser firebaseUser = FirebaseAuth.getInstance().getCurrentUser();
settings = getSharedPreferences(PREFS_NAME, 0);
String user_uid = settings.getString("uid", "Null");
uid = firebaseUser.getUid();
//Run time permission
Dexter.withActivity(this)
.withPermissions(Arrays.asList(
Manifest.permission.ACCESS_FINE_LOCATION,
Manifest.permission.ACCESS_BACKGROUND_LOCATION,
Manifest.permission.ACCESS_COARSE_LOCATION
))
.withListener(new MultiplePermissionsListener() {
#Override
public void onPermissionsChecked(MultiplePermissionsReport report) {
requestLocation = (Button) findViewById(R.id.request_location_updates_button);
removeLocation = (Button) findViewById(R.id.remove_location_updates_button);
//Update location when i click on button
requestLocation.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
mService.requestLocationUpdates();
}
});
//Remove location when i click remove button
removeLocation.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
mService.removeLocationUpdates();
}
});
setButtonState(Common.requestingLocationUpdates(UserLocation.this));
bindService(new Intent(UserLocation.this,
MyBackgroundService.class),
mServiceConnection,
Context.BIND_AUTO_CREATE
);
}
#Override
public void onPermissionRationaleShouldBeShown(List<PermissionRequest> permissions, PermissionToken token) {
}
})
.check();
}
#Override
protected void onStart() {
super.onStart();
PreferenceManager.getDefaultSharedPreferences(this)
.registerOnSharedPreferenceChangeListener(this);
EventBus.getDefault().register(this);
}
#Override
protected void onStop() {
if (mBound) {
unbindService(mServiceConnection);
mBound = false;
}
PreferenceManager.getDefaultSharedPreferences(this)
.unregisterOnSharedPreferenceChangeListener(this);
EventBus.getDefault().unregister(this);
super.onStop();
}
#Override
public void onSharedPreferenceChanged(SharedPreferences sharedPreferences, String s) {
if (s.equals(Common.KEY_REQUESTING_LOCATION_UPDATES)) {
setButtonState(sharedPreferences.getBoolean(Common.KEY_REQUESTING_LOCATION_UPDATES, false));
}
}
private void setButtonState(boolean isRequestEnable) {
if (isRequestEnable) {
requestLocation.setEnabled(false);
removeLocation.setEnabled(true);
} else {
requestLocation.setEnabled(true);
removeLocation.setEnabled(false);
}
}
#Subscribe(sticky = true, threadMode = ThreadMode.MAIN)
public void onListenLocation(SendLocationToActivity event) {
FirebaseUser firebaseUser = FirebaseAuth.getInstance().getCurrentUser();
settings = getSharedPreferences(PREFS_NAME, 0);
String user_uid = settings.getString("uid", "Null");
uid = firebaseUser.getUid();
if (event != null) {
String data = new StringBuilder()
.append(event.getLocation().getLatitude())
.append("/")
.append(event.getLocation().getLongitude())
.toString();
Toast.makeText(mService, data, Toast.LENGTH_SHORT).show();
// Location location = event.getLastLocation();
Locations location = new Locations();
location.setLat(event.getLocation().getLatitude());
location.setLon(event.getLocation().getLongitude());
if (Common.currentUser != null) {
publiclocation.child(firebaseUser.getUid()).setValue(location);
} else {
publiclocation.child(user_uid).setValue(location);
}
}
}
}
so below is MyLocationService.java
public void requestLocationUpdates() {
Toast.makeText(getApplicationContext(),"Came",Toast.LENGTH_SHORT).show();
Common.setRequestingLocationUpdates(this, true);
startService(new Intent(getApplicationContext(), MyBackgroundService.class));
try {
fusedLocationProviderClient.requestLocationUpdates(locationRequest, locationCallback, Looper.myLooper());
} catch (SecurityException e) {
Log.e("FunDrive", "Lost location permissions.could not request it" + e);
}
}
Common java
public static final String KEY_REQUESTING_LOCATION_UPDATES = "LocationUpdatedEnable";
SharedPreferences settings;
public static final int TIME_DISPLAY_SLOT_TOTAL = 20;
//Current User
public static User currentUser;
public static String PUBLIC_LOCATION="PublicLocation";
public static boolean isTimeSelected = false;
public static void setRequestingLocationUpdates(Context context,boolean value) {
PreferenceManager.
getDefaultSharedPreferences(context)
.edit()
.putBoolean(KEY_REQUESTING_LOCATION_UPDATES,value)
.apply();
}
public static boolean requestingLocationUpdates(Context context) {
return PreferenceManager.getDefaultSharedPreferences(context)
.getBoolean(KEY_REQUESTING_LOCATION_UPDATES,false);
}
public static CharSequence getLocationTitle(com.example.fundrive.MyBackgroundService myBackgroundService) {
return String.format("Location Updated :%1$s", DateFormat.getDateInstance().format(new Date()));
}
below is what I tried in oncreate method
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
mService.requestLocationUpdates();
}

Related

when i launch the activity the switch is working fine but it still goes off when the activity is going to backhand?

I recently worked in the project for making screen dimmer app but I stuck with one problem. In my app, there is MaterialAnimatedSwitch it works fine but when the app goes to the backhand, the switch is automatically off but the working of the app is perfectly continued. I want that the switch remains active or on whenever the user come back to the app interface.I use MaterialAnimatedSwitch so how to do this task.
i want the switch to be active or ON whenever the app resumes.
public class MainActivity extends AppCompatActivity {
int b1 = 40;
int b2 = 90;
DiscreteSeekBar bSeekBar;
ChatHeadService binder=null;
boolean isOn = false;
boolean mBounded;
public boolean isRunning=false;
ServiceConnection mConnection = new ServiceConnection() {
public void onServiceDisconnected(ComponentName name) {
mBounded = false;
mService = null;
}
#Override
public void onServiceConnected(ComponentName name, IBinder service) {
mBounded = true;
LocalBinder mLocalBinder = (LocalBinder) service;
mService = mLocalBinder.getServerInstance();
int brightness = mService.getBrightness();
int brightness2 = mService.getBrightness2();
seekBar.setProgress(brightness);
bSeekBar.setProgress(brightness2);
}
};
ChatHeadService mService;
RadioGroup radioGroup;
DiscreteSeekBar seekBar;
MaterialAnimatedSwitch aSwitch;
SharedPreferences sharedPrefs;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
Fabric.with(this, new Kit[]{new Crashlytics()});
setContentView(R.layout.activity_main);
initInstances();
if (isOn && !isMyServiceRunning(ChatHeadService.class)) {
startService(new Intent(this, ChatHeadService.class));
}
}
private boolean isMyServiceRunning(Class<?> serviceClass) {
for (RunningServiceInfo service : ((ActivityManager) getSystemService(Context.ACTIVITY_SERVICE)).getRunningServices(Integer.MAX_VALUE)) {
if (serviceClass.getName().equals(service.service.getClassName())) {
return true;
}
}
return false;
}
private void initInstances() {
sharedPrefs = PreferenceManager.getDefaultSharedPreferences(this);
seekBar = (DiscreteSeekBar) findViewById(R.id.seekBar);
bSeekBar = (DiscreteSeekBar) findViewById(R.id.brightnessSeekBar);
int b = sharedPrefs.getInt("b", 40);
int bb = sharedPrefs.getInt("bb", 90);
seekBar.setProgress(b);
bSeekBar.setProgress(bb);
aSwitch=(MaterialAnimatedSwitch)findViewById(R.id.switch1);
aSwitch.setClickable(sharedPrefs.getBoolean("isOn",false));
aSwitch.setOnCheckedChangeListener(new OnCheckedChangeListener() {
#Override
public void onCheckedChanged(boolean b) {
if(b){
sharedPrefs.edit().putBoolean("isOn", true).apply();
isOn = true;
isRunning=aSwitch.isChecked();
startService(new Intent(MainActivity.this, ChatHeadService.class));
bindService();
}
else{
sharedPrefs.edit().putBoolean("isOn", false).apply();
isOn = false;
unBindService();
stopService(new Intent(MainActivity.this, ChatHeadService.class)); }
}
});
seekBar.setOnProgressChangeListener(new OnProgressChangeListener() {
public void onProgressChanged(DiscreteSeekBar seekBar, int value, boolean fromUser) {
b1 = value;
if (mService != null) {
mService.setBrightness(value, b2);
}
sharedPrefs.edit().putInt("b", value).apply();
}
public void onStartTrackingTouch(DiscreteSeekBar seekBar) {
}
public void onStopTrackingTouch(DiscreteSeekBar seekBar) {
}
});
bSeekBar.setOnProgressChangeListener(new OnProgressChangeListener() {
public void onProgressChanged(DiscreteSeekBar seekBar, int value, boolean fromUser) {
b2 = value;
if (mService != null) {
mService.setBrightness(b1, value);
}
sharedPrefs.edit().putInt("bb", value).apply();
}
public void onStartTrackingTouch(DiscreteSeekBar seekBar) {
}
public void onStopTrackingTouch(DiscreteSeekBar seekBar) {
}
});
}
#Override
protected void onStart() {
super.onStart();
if (isOn) {
bindService();
}
}
public void bindService() {
bindService(new Intent(this, ChatHeadService.class), mConnection,Context.BIND_AUTO_CREATE);
}
public void unBindService() {
if (mBounded) {
unbindService(mConnection);
mBounded = false;
}
}
#Override
protected void onPause() {
super.onPause();
isRunning=aSwitch.isPressed();
}
#Override
protected void onResume() {
super.onResume();
if(!isOn == aSwitch.isPressed()){
aSwitch.toggle();
}
}
}
Thanks in advance!
This is the screenshot when app is just open
This is the screenshot when night mode is ON
But When the going to backhand and then open the switch state changed
You are saving switch state in Shared preferences but not using it.
just add the following line above aswitch.setOnCheckedChangeListener
line, it will apply the state you saved in preferences
aSwitch.setChecked(sharedPrefs.getBoolean("isOn", false)); //false default
I suggest store value of your switch in one of your global variable and at time resume set it with the switch again like below:
public boolean isRunning = false;
#Override
protected void onPause() {
super.onPause();
isRunning = switchAler.isChecked();
}
#Override
protected void onResume() {
super.onResume();
binding.switchAler.setChecked(isRunning);
if(!isRunning == switchAler.isChecked()){
switchAler.toggle();
}
}

Stuck in this Firebase database in main activity

In this project I am displaying scores from database. When I change the value of scores from the database it changes there but when I check in the app, it doesn't show the change there, and whenever the points gets added through rewarded video ad it doesnt show in the scores.
We need to restart the app to see the video ads point added, and when I change the values from database, it never shows on the app, I think its solution is easy and I am just a beginner.
public class Home_page extends AppCompatActivity implements RewardedVideoAdListener {
TextView score_text;
LinearLayout spin_button, logout_button, redeem_button, watch_video_buuton,share_id,rate_button;
;
private RewardedVideoAd mRewardedVideoAd;
int myIntValue;
DatabaseReference user_id_child;
String user_id;
DatabaseReference databaseReference;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_home_page);
MobileAds.initialize(getApplicationContext(), "ca-app-pub-3940256099942544/5224354917");
databaseReference = FirebaseDatabase.getInstance().getReference().child("users");
FirebaseAuth mAuth = FirebaseAuth.getInstance();
user_id = mAuth.getCurrentUser().getUid();
user_id_child = databaseReference.child(user_id);
getSupportActionBar().setTitle("Earn Money");
// Admob video ads
MobileAds.initialize(getApplicationContext(), "ca-app-pub-3940256099942544/5224354917");
mRewardedVideoAd = MobileAds.getRewardedVideoAdInstance(this);
mRewardedVideoAd.setRewardedVideoAdListener(this);
loadRewardedVideoAd();
spin_button = (LinearLayout) findViewById(R.id.spin_linear_id);
redeem_button = (LinearLayout) findViewById(R.id.linear_redeem_id);
logout_button = (LinearLayout) findViewById(R.id.linear_logout_id);
watch_video_buuton = (LinearLayout) findViewById(R.id.linear_watch_video_id);
share_id = (LinearLayout)findViewById(R.id.linear_share_id);
score_text = (TextView) findViewById(R.id.wallet_text_score_id);
rate_button = (LinearLayout)findViewById(R.id.linear_rate_id);
SharedPreferences sp = getSharedPreferences("your_prefs", Activity.MODE_PRIVATE);
myIntValue = sp.getInt("your_int_key", 0);
rate_button.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
Uri uri = Uri.parse("https://www.instagram.com/dhruv__bhati/");
Intent intent = new Intent(Intent.ACTION_VIEW, uri);
startActivity(intent);
}
});
watch_video_buuton.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
if (mRewardedVideoAd.isLoaded()) {
mRewardedVideoAd.show();
}
else {
loadRewardedVideoAd();
Toast.makeText(Home_page.this , "video ad not loaded ", Toast.LENGTH_LONG).show();
}
}
});
redeem_button.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
Intent intent = new Intent(Home_page.this, Redeem.class);
startActivity(intent);
overridePendingTransition(R.anim.slide_right, R.anim.slide_left);
}
});
logout_button.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
diaglog();
}
});
spin_button.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
Intent intent = new Intent(Home_page.this, Spinwheel.class);
intent.putExtra("INT",myIntValue);
startActivity(intent);
overridePendingTransition(R.anim.slide_right, R.anim.slide_left);
}
});
share_id.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
share(view);
}
});
}
#Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.menu, menu);//Menu Resource, Menu
return super.onCreateOptionsMenu(menu);
}
#Override
public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()) {
case R.id.logout_id: {
logout();
}
return true;
}
return super.onOptionsItemSelected(item);
}
private void logout() {
FirebaseAuth.getInstance().signOut();
Intent intent = new Intent(Home_page.this, MainActivity.class);
intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
startActivity(intent);
}
#Override
public void finish() {
super.finish();
finish();
}
#Override
public void onRewardedVideoAdLoaded() {
}
#Override
public void onRewardedVideoAdOpened() {
}
#Override
public void onRewardedVideoStarted() {
}
#Override
public void onRewardedVideoAdClosed() {
loadRewardedVideoAd();
}
#Override
public void onRewarded(RewardItem rewardItem) {
Toast.makeText(Home_page.this,"Congratulations, you will get 1000 points next time you open the app ", Toast.LENGTH_LONG).show();
SharedPreferences sp = getSharedPreferences("your_prefs", Activity.MODE_PRIVATE);
SharedPreferences.Editor editor = sp.edit();
int n = myIntValue+1000;
editor.putInt("your_int_key", n);
editor.commit();
user_id_child.child("scores").setValue(+n);
watch_video_buuton.setEnabled(false);
final long startTime= Calendar.getInstance().getTime().getTime();
final Timer timer=new Timer();
TimerTask task=new TimerTask() {
#Override
public void run() {
long curentTime=Calendar.getInstance().getTime().getTime();
long elapsedTime=curentTime-startTime;
ToastTime(10*60*1000, elapsedTime);
if(curentTime-startTime>=10*60*1000){ //10 minutes in millisecond
timer.cancel();
watch_video_buuton.setEnabled(true);
}
}
};
timer.schedule(task, 500, 2000);
}
#Override
public void onRewardedVideoAdLeftApplication() {
}
#Override
public void onRewardedVideoAdFailedToLoad(int i) {
}
private void loadRewardedVideoAd() {
if(!mRewardedVideoAd.isLoaded()){
mRewardedVideoAd.loadAd("ca-app-pub-3940256099942544/5224354917",
new AdRequest.Builder().build());
}
}
#Override
public void onResume() {
mRewardedVideoAd.resume(this);
super.onResume();
}
#Override
public void onPause() {
mRewardedVideoAd.pause(this);
super.onPause();
}
#Override
public void onDestroy() {
mRewardedVideoAd.destroy(this);
super.onDestroy();
}
#Override
protected void onStart() {
super.onStart();
SharedPreferences sp = getSharedPreferences("your_prefs", Activity.MODE_PRIVATE);
myIntValue = sp.getInt("your_int_key", 0);
String s = String.valueOf(myIntValue);
score_text.setText(s);
loadRewardedVideoAd();
}
public void share(View view){
Intent sharingIntent = new Intent(android.content.Intent.ACTION_SEND);
sharingIntent.setType("text/plain");
sharingIntent.putExtra(android.content.Intent.EXTRA_SUBJECT, "Earn Money");
sharingIntent.putExtra(android.content.Intent.EXTRA_TEXT, "Earn unlimited money by simple tasks"+" "+"https://play.google.com/store/apps/details?id=wheel.top.best.online.money.make.techyunk.com.earningwheel");
startActivity(Intent.createChooser(sharingIntent, "Share via"));
}
public void diaglog(){
final Dialog dialog = new Dialog(Home_page.this);
dialog.setContentView(R.layout.custom_logout);
Button no = (Button) dialog.findViewById(R.id.no_id);
Button yes = (Button)dialog.findViewById(R.id.yes_id);
// if button is clicked, close the custom dialog
no.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
dialog.dismiss();
}
});
yes.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
logout();
}
});
dialog.show();
}
private void ToastTime(long totalTime, long elapsedTime) {
final int remainInSec = (int) (totalTime - elapsedTime) / 1000;
if (remainInSec > 0) {
final Activity activity = this;
runOnUiThread(new Runnable() {
#Override
public void run() {
Toast.makeText(activity, String.valueOf(remainInSec) + " seconds to enable video button", Toast.LENGTH_SHORT).show();
}
});
}
}
}
As I can see you didn't attach any listener to the Firebase, in your case you need to use addChildEventListener : ChildEventListener.
Be careful and only call this listener once in the onCreate method, If you call it more than once it attaches a new listener then you have two listeners and duplicated data.
UPDATE:
This is the user class you get from the firebase :
public class User {
private String email;
private String name;
private String scores;
public User() {
}
public User(String email, String name, String scores) {
this.email = email;
this.name = name;
this.scores = scores;
}
public String getEmail() {
return email;
}
public void setEmail(String email) {
this.email = email;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getScores() {
return scores;
}
public void setScores(String scores) {
this.scores = scores;
}
}
Now let's fetch the data :
firebaseReference.addChildEventListener(new ChildEventListener() {
#Override
public void onChildAdded(DataSnapshot dataSnapshot, String s) {
// Here you can handle the new added items.
// if you added a new user you will see it here
User user = dataSnapshot.getValue(User.class);
// Now For example let's log the result
Log.d(TAG, "the user score is : " + user.getScore());
}
#Override
public void onChildChanged(DataSnapshot dataSnapshot, String s) {
// If you change the score this will appear here :
User user = dataSnapshot.getValue(User.class);
// Here is the new score you can use to update the score in the view
String score = user.getScore();
}
#Override
public void onChildRemoved(DataSnapshot dataSnapshot) {
}
#Override
public void onChildMoved(DataSnapshot dataSnapshot, String s) {
}
#Override
public void onCancelled(DatabaseError databaseError) {
}
});
Now go and try this and you will get it.

In my Android app as splash screen disappears, next screen becomes black

This is my SplashActivity class.
In my Android app I've used a splash screen. But as splash screen disappears, then next screen becomes black before switching to main activity. So, how can I prevent that black screen?
public class SplashScreen extends Activity {
RegisterGCM registerGCM;
private GpsTracker1 mGps;
boolean canLocate;
public static boolean appVisible = false;
public static String lat;
public static String lon;
public static String addr;
public static String addr1;
public static String city;
public static String state;
public static String pin;
public static String country;
public void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.splash_screen);
this.mGps = new GpsTracker1(this);
canLocate = mGps.canGetLocation();
if (!canLocate)
{
this.mGps.showSettingsAlert();
}
else
{
getGpsInfo();
}
}
public void getGpsInfo()
{
registerGCM = new RegisterGCM(getApplicationContext());
String regId = registerGCM.getRegistrationId();
if (TextUtils.isEmpty(regId))
{
registerGCM.registerGCM();
}
lat = this.mGps.getLatitude();
lon = this.mGps.getLongitude();
addr = this.mGps.getAddress();
addr1 = this.mGps.getAddress1();
city = this.mGps.getCity();
state = this.mGps.getState();
pin = this.mGps.getPostalcode();
country = this.mGps.getCountry();
Thread timerThread = new Thread()
{
public void run()
{
try
{
sleep(2000);
}
catch(InterruptedException e)
{
e.printStackTrace();
}
finally
{
Intent intent = new Intent(SplashScreen.this, Category_Activity.class);
startActivity(intent);
finish();
}
}
};
timerThread.start();
}
#Override
public void onStart()
{
super.onStart();
}
public void onStop()
{
super.onStop();
}
public void onResume()
{
super.onResume();
appVisible = true;
}
public void onPause()
{
super.onPause();
appVisible = false;
}
}
Why don't you post your runnable instead of blocking a thread?
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.splash_screen);
new Handler().postDelayed(new Runnable() {
#Override
public void run() {
Intent intent = new Intent(SplashScreen.this, Category_Activity.class);
startActivity(intent);
finish();
}
}, 2000);
// Other details
}
It starts your activity in the main thread.

sinch conference call hung up right after it starts

I managed to start a conference call cut it closes right after I start it with HUNG_UP cause and I got this in my log:
11-03 17:28:08.940: E/sinch-android-rtc(19101): peermediaconnection: virtual void rebrtc::SetSDPObserver::OnFailure(const string&)Failed to set remote answer sdp: Offer and answer descriptions m-lines are not matching. Rejecting answer.
11-03 17:28:08.940: E/sinch-android-rtc(19101): mxp: Failed to set remote answer sdp: Offer and answer descriptions m-lines are not matching. Rejecting answer.
can anybody help me solve this please?
Edit:
my scenario is when a user clicks the call button I ask him if he wants to start a new call or join an already created one.
I managed to make my code from this question (Sinch conference call error) work as my GroupService class had some bugs.
I start my call like this:
Intent intent1 = new Intent(CreateGroupCallActivity.this,SinchClientService.class);
intent1.setAction(SinchClientService.ACTION_GROUP_CALL);
String id = String.valueOf(uid) + "-" + call_id.getText().toString();
intent1.putExtra(SinchClientService.INTENT_EXTRA_ID,id);
startService(intent1);
and in my SinchClientService:
if(intent.getAction().equals(ACTION_GROUP_CALL))
{
String id = intent.getStringExtra(INTENT_EXTRA_ID);
if(id != null)
groupCall(id);
}
public void groupCall(String id) {
if (mCallClient != null) {
Call call = mCallClient.callConference(id);
CurrentCall.currentCall = call;
Log.d("call", "entered");
Intent intent = new Intent(this, GroupCallService.class);
startService(intent);
}
}
nd here is my GroupCallService
public class GroupCallScreenActivity extends AppCompatActivity implements ServiceConnection {
private SinchClientService.MessageServiceInterface mMessageService;
private GroupCallService.GroupCallServiceInterface mCallService;
private UpdateReceiver mUpdateReceiver;
private ImageButton mEndCallButton;
private TextView mCallDuration;
private TextView mCallState;
private TextView mCallerName;
//private TextView locationview;
private ImageView user_pic;
private long mCallStart;
private Timer mTimer;
private UpdateCallDurationTask mDurationTask;
ImageButton chat;
ImageButton speaker;
ImageButton mic;
boolean speaker_on = false;
boolean mic_on = true;
PowerManager mPowerManager;
WakeLock mProximityWakeLock;
final static int PROXIMITY_SCREEN_OFF_WAKE_LOCK = 32;
com.galsa.example.main.ImageLoader mImageLoader;
/*String location;
String longitude;
String latitude;*/
private class UpdateCallDurationTask extends TimerTask {
#Override
public void run() {
GroupCallScreenActivity.this.runOnUiThread(new Runnable() {
#Override
public void run() {
updateCallDuration();
}
});
}
}
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
getWindow().addFlags(WindowManager.LayoutParams.FLAG_DISMISS_KEYGUARD);
getWindow().addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
getWindow().addFlags(WindowManager.LayoutParams.FLAG_SHOW_WHEN_LOCKED);
setContentView(R.layout.callscreen);
doBind();
mCallDuration = (TextView) findViewById(R.id.callDuration);
mCallerName = (TextView) findViewById(R.id.remoteUser);
mCallState = (TextView) findViewById(R.id.callState);
//locationview = (TextView) findViewById(R.id.location);
mEndCallButton = (ImageButton) findViewById(R.id.hangupButton);
chat = (ImageButton) findViewById(R.id.chat);
chat.setVisibility(View.GONE);
speaker = (ImageButton) findViewById(R.id.speaker);
mic = (ImageButton) findViewById(R.id.mic);
user_pic = (ImageView) findViewById(R.id.user_pic);
/*location = getIntent().getStringExtra("location");
longitude = getIntent().getStringExtra("longitde");
latitude = getIntent().getStringExtra("latitude");
locationview.setText(location);*/
mImageLoader = new com.galsa.example.main.ImageLoader(GroupCallScreenActivity.this, R.dimen.caller_image_height);
//mCallerName.setText(mCall.getRemoteUserId());
mPowerManager = (PowerManager) getSystemService(Context.POWER_SERVICE);
mProximityWakeLock = mPowerManager.newWakeLock(PROXIMITY_SCREEN_OFF_WAKE_LOCK, Utils.TAG);
/*chat.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
Intent intent = new Intent(GroupCallScreenActivity.this, MessagingActivity.class);
intent.putExtra(SinchClientService.INTENT_EXTRA_ID, mCallService.getCallerId());
intent.putExtra(SinchClientService.INTENT_EXTRA_NAME, mCallService.getCallerName());
startActivity(intent);
}
});*/
speaker.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
if(speaker_on)
{
mMessageService.speakerOn(speaker_on);
speaker_on = false;
speaker.setImageResource(R.drawable.speaker_off);
}
else
{
mMessageService.speakerOn(speaker_on);
speaker_on = true;
speaker.setImageResource(R.drawable.speaker_on);
}
}
});
mic.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
if(mic_on)
{
mMessageService.micOn(mic_on);
mic_on = false;
mic.setImageResource(R.drawable.mic_off);
}
else
{
mMessageService.micOn(mic_on);
mic_on = true;
mic.setImageResource(R.drawable.mic_on);
}
}
});
mEndCallButton.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
mCallService.endCall();
}
});
mCallStart = System.currentTimeMillis();
}
private void doBind() {
Intent intent = new Intent(this, SinchClientService.class);
bindService(intent, this, BIND_AUTO_CREATE);
intent = new Intent(this, GroupCallService.class);
bindService(intent, this, BIND_AUTO_CREATE);
}
private void doUnbind() {
unbindService(this);
}
#Override
protected void onStart() {
super.onStart();
mUpdateReceiver = new UpdateReceiver();
IntentFilter filter = new IntentFilter();
filter.addAction(GroupCallService.ACTION_FINISH_CALL_ACTIVITY);
filter.addAction(GroupCallService.ACTION_CHANGE_AUDIO_STREAM);
filter.addAction(GroupCallService.ACTION_UPDATE_CALL_STATE);
LocalBroadcastManager.getInstance(this).registerReceiver(mUpdateReceiver, filter);
}
#Override
public void onResume() {
super.onResume();
if(mProximityWakeLock != null && !mProximityWakeLock.isHeld()){
mProximityWakeLock.acquire();
}
mTimer = new Timer();
mDurationTask = new UpdateCallDurationTask();
mTimer.schedule(mDurationTask, 0, 500);
}
#Override
public void onPause() {
super.onPause();
if(isFinishing() && mProximityWakeLock != null && mProximityWakeLock.isHeld()){
mProximityWakeLock.release();
}
mDurationTask.cancel();
}
#Override
protected void onStop() {
super.onStop();
if(isFinishing() && mProximityWakeLock != null && mProximityWakeLock.isHeld()){
mProximityWakeLock.release();
}
if(mUpdateReceiver != null)
{
LocalBroadcastManager.getInstance(this).unregisterReceiver(mUpdateReceiver);
mUpdateReceiver = null;
}
}
#Override
public void onBackPressed() {
// User should exit activity by ending call, not by going back.
}
private void updateCallDuration() {
mCallDuration.setText(Utils.formatTimespan(System.currentTimeMillis() - mCallStart));
}
#Override
public void onServiceConnected(ComponentName componentName, IBinder iBinder) {
if(iBinder instanceof GroupCallService.GroupCallServiceInterface)
{
mCallService = (GroupCallService.GroupCallServiceInterface) iBinder;
Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
setSupportActionBar(toolbar);
getSupportActionBar().setDisplayShowHomeEnabled(true);
ActionBar actionBar = getSupportActionBar();
if(mCallService.getCallerName() != null)
actionBar.setTitle(mCallService.getCallerName());
else
actionBar.setTitle("Group call");
actionBar.setIcon(R.drawable.callscreen);
if(mCallService.getCallerName() != null)
mCallerName.setText(mCallService.getCallerName());
else
mCallerName.setText("Group call");
mCallState.setText(mCallService.getCallState());
String pic = ChatDatabaseHandler.getInstance(this).getFriendpic(mCallService.getCallerId());
mImageLoader.displayImage(UserFunctions.hostImageDownloadURL + pic, user_pic);
}
else
mMessageService = (SinchClientService.MessageServiceInterface) iBinder;
mMessageService.enableMic();
mMessageService.disableSpeaker();
}
#Override
public void onServiceDisconnected(ComponentName componentName) {
mMessageService = null;
mCallService = null;
}
#Override
public void onDestroy() {
if(mUpdateReceiver != null)
{
LocalBroadcastManager.getInstance(this).unregisterReceiver(mUpdateReceiver);
mUpdateReceiver = null;
}
doUnbind();
super.onDestroy();
}
private class UpdateReceiver extends BroadcastReceiver
{
#Override
public void onReceive(Context context, Intent intent)
{
if(GroupCallService.ACTION_FINISH_CALL_ACTIVITY.equals(intent.getAction()))
{
finish();
}
else if(GroupCallService.ACTION_CHANGE_AUDIO_STREAM.equals(intent.getAction()))
{
setVolumeControlStream(intent.getIntExtra("STREAM_TYPE", AudioManager.USE_DEFAULT_STREAM_TYPE));
}
else if(GroupCallService.ACTION_UPDATE_CALL_STATE.equals(intent.getAction()))
{
mCallState.setText(intent.getStringExtra("STATE"));
}
}
}
}
I start the call with the same way whether the user will start a new call or join a created one.

Android: Execute http requests via Service

I have a trouble with getting Activity(Nullpointerexception) after that I have rotate screen and received callback from AsyncTask to update my views of the fragment. If I wont change orientation then everything is OK(but not all the time, sometimes this bug appears)
My main activity:
public class MainActivity extends SherlockFragmentActivity {
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.pager_layout);
fm = getSupportFragmentManager();
fm.addOnBackStackChangedListener(this);
session = new SessionManager(getApplicationContext());
if (session.isAuthorizated()) {
disableTabs();
FragmentTransaction ft = fm.beginTransaction();
if (session.termsAndConditions()) {
ft.replace(android.R.id.content, new TermsAndConditionsFragment(), "terms-and-conditions").commit();
}
}
} else {
enableTabs();
mTabsAdapter = new TabsAdapter(this, mViewPager);
mTabsAdapter.addTab(actionBar.newTab().setText("Log in"), LoginFragment.class, null);
mTabsAdapter.addTab(actionBar.newTab().setText("Calculator"), CalculatorFragment.class, null);
}
}
That`s my fragment:
public class TermsAndConditionsFragment extends SherlockFragment implements OnClickListener, OnTouchListener, OnEditorActionListener, ValueSelectedListener, AsyncUpdateViewsListener {
private static final String TAG = "TermsAndConditionsFragment";
private TermsAndConditionsManager termsAndConditionsM;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
prepareData();
}
public void prepareData() {
if (getSherlockActivity() == null)
Log.d(TAG, "Activity is null");
termsAndConditionsM = new TermsAndConditionsManager(getSherlockActivity().getApplicationContext());
termsAndConditions = termsAndConditionsM.getTermsAndConditions();
...
// some stuff
...
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
rootView = init(inflater, container);
return rootView;
}
private View init(LayoutInflater inflater, ViewGroup container) {
rootView = inflater.inflate(R.layout.fragment_terms_and_conditions, container, false);
//bla bla bla
return rootView;
}
public void updateTermsAndConditionsView() {
//update views here
}
#Override
public void onClick(View v) {
ft = fm.beginTransaction();
switch (v.getId()) {
case R.id.etHowMuch:
d = NumberPaymentsPickerFragment.newInstance(getSherlockActivity(), Integer.valueOf(howMuch.replace("£", "")), 0);
d.setValueSelectedListener(this);
d.show(getFragmentManager(), Const.HOW_MUCH);
break;
}
}
#Override
public void onValueSelected() {
Bundle args = new Bundle();
...
ExecuteServerTaskBackground task = new ExecuteServerTaskBackground(getSherlockActivity());
task.setAsyncUpdateViewsListener(this);
task.action = ServerAPI.GET_TERMS_AND_CONDITIONS;
task.args = args;
task.execute();
}
#Override
public void onUpdateViews() {
prepareData();
updateTermsAndConditionsView();
}
}
My AsyncTask with callback:
public class ExecuteServerTaskBackground extends AsyncTask<Void, Void, Void> {
private static final String TAG = "ExecuteServerTaskBackground";
Activity mActivity;
Context mContext;
private AsyncUpdateViewsListener callback;
public ExecuteServerTaskBackground(Activity activity) {
this.mActivity = activity;
this.mContext = activity.getApplicationContext();
}
public void setAsyncUpdateViewsListener(AsyncUpdateViewsListener listener) {
callback = listener;
}
#Override
protected Void doInBackground(Void... params) {
ServerAPI server = new ServerAPI(mContext);
if (!args.isEmpty())
msg = server.serverRequest(action, args);
else
msg = server.serverRequest(action, null);
return null;
}
#Override
protected void onPostExecute(Void result) {
super.onPostExecute(result);
callback.onUpdateViews();
}
}
Why does it behave so? How can I get activity correctly if I change orientation.
EDIT:
As I understand correctly nullpointer appears after orientation changed and asynctask executed due to wrong reference between asyctask and Activity. Recreated activity doesnt have this reference thats why when I receive callback I use wrong activity reference which isn`t exist anymore. But how can I save current activity reference?
EDIT:
I have decided to try realize my task throughout Service and that`s what I have done.
Activity:
public class MainFragment extends Fragment implements ServiceExecutorListener, OnClickListener {
private static final String TAG = MainFragment.class.getName();
Button btnSend, btnCheck;
TextView serviceStatus;
Intent intent;
Boolean bound = false;
ServiceConnection sConn;
RESTService service;
ProgressDialog pd = new ProgressDialog();
#Override
public void onActivityCreated(Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
setRetainInstance(true);
intent = new Intent(getActivity(), RESTService.class);
getActivity().startService(intent);
sConn = new ServiceConnection() {
#Override
public void onServiceConnected(ComponentName name, IBinder binder) {
Log.d(TAG, "MainFragment onServiceConnected");
service = ((RESTService.MyBinder) binder).getService();
service.registerListener(MainFragment.this);
if (service.taskIsDone())
serviceStatus.setText(service.getResult());
bound = true;
}
public void onServiceDisconnected(ComponentName name) {
Log.d(TAG, "MainFragment onServiceDisconnected");
bound = false;
}
};
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View rootView = inflater.inflate(R.layout.main_fragment, container, false);
serviceStatus = (TextView) rootView.findViewById(R.id.tvServiceStatusValue);
btnSend = (Button) rootView.findViewById(R.id.btnSend);
btnCheck = (Button) rootView.findViewById(R.id.btnCheck);
btnSend.setOnClickListener(this);
btnCheck.setOnClickListener(this);
return rootView;
}
#Override
public void onClick(View v) {
switch (v.getId()) {
case R.id.btnSend:
pd.show(getFragmentManager(), "ProgressDialog");
service.run(7);
service.run(2);
service.run(4);
break;
case R.id.btnCheck:
if (service != null)
serviceStatus.setText(String.valueOf(service.taskIsDone()) + service.getTasksCount());
break;
}
}
#Override
public void onStart() {
super.onStart();
Log.d(TAG, "Bind service");
getActivity().bindService(intent, sConn, 0);
}
#Override
public void onPause() {
super.onDestroy();
Log.d(TAG, "onDestroy: Unbind service");
if (!bound)
return;
getActivity().unbindService(sConn);
service.unregisterListener(this);
bound = false;
}
#Override
public void onComplete(String result) {
Log.d(TAG, "Task Completed");
pd.dismiss();
serviceStatus.setText(result);
}
}
Dialog:
public class ProgressDialog extends DialogFragment implements OnClickListener {
final String TAG = ProgressDialog.class.getName();
public Dialog onCreateDialog(Bundle savedInstanceState) {
setRetainInstance(true);
AlertDialog.Builder adb = new AlertDialog.Builder(getActivity())
.setTitle("Title!")
.setPositiveButton(R.string.yes, this)
.setNegativeButton(R.string.no, this)
.setNeutralButton(R.string.maybe, this)
.setCancelable(false)
.setMessage(R.string.message_text)
.setOnKeyListener(new OnKeyListener() {
#Override
public boolean onKey(DialogInterface dialog, int keyCode, KeyEvent event) {
return true;
}
});
return adb.create();
}
public void onClick(DialogInterface dialog, int which) {
int i = 0;
switch (which) {
case Dialog.BUTTON_POSITIVE:
i = R.string.yes;
break;
case Dialog.BUTTON_NEGATIVE:
i = R.string.no;
break;
case Dialog.BUTTON_NEUTRAL:
i = R.string.maybe;
break;
}
if (i > 0)
Log.d(TAG, "Dialog 2: " + getResources().getString(i));
}
public void onDismiss(DialogInterface dialog) {
Log.d(TAG, "Dialog 2: onDismiss");
// Fix to avoid simple dialog dismiss in orientation change
if ((getDialog() != null) && getRetainInstance())
getDialog().setDismissMessage(null);
super.onDestroyView();
}
public void onCancel(DialogInterface dialog) {
super.onCancel(dialog);
Log.d(TAG, "Dialog 2: onCancel");
}
}
Service:
public class RESTService extends Service {
final String TAG = RESTService.class.getName();
MyBinder binder = new MyBinder();
ArrayList<ServiceExecutorListener> listeners = new ArrayList<ServiceExecutorListener>();
Handler h = new Handler();
RequestManager mRequest;
ExecutorService es;
Object obj;
int time;
StringBuilder builder;
String result = null;
public void onCreate() {
super.onCreate();
Log.d(TAG, "RESTService onCreate");
es = Executors.newFixedThreadPool(1);
obj = new Object();
builder = new StringBuilder();
}
public void run(int time) {
RunRequest rr = new RunRequest(time);
es.execute(rr);
}
class RunRequest implements Runnable {
int time;
public RunRequest(int time) {
this.time = time;
Log.d(TAG, "RunRequest create");
}
public void run() {
Log.d(TAG, "RunRequest start, time = " + time);
try {
TimeUnit.SECONDS.sleep(time);
} catch (InterruptedException e) {
e.printStackTrace();
}
try {
Log.d(TAG, "RunRequest obj = " + obj.getClass());
} catch (NullPointerException e) {
Log.d(TAG, "RunRequest error, null pointer");
}
builder.append("result " + time + ", ");
result = builder.toString();
sendCallback();
}
}
private void sendCallback() {
h.post(new Runnable() {
#Override
public void run() {
for (ServiceExecutorListener listener : listeners)
listener.onComplete();
}
});
}
public boolean taskIsDone() {
if (result != null)
return true;
return false;
}
public String getResult() {
return result;
}
public void registerListener(ServiceExecutorListener listener) {
listeners.add(listener);
}
public void unregisterListener(ServiceExecutorListener listener) {
listeners.remove(listener);
}
public IBinder onBind(Intent intent) {
Log.d(TAG, "RESTService onBind");
return binder;
}
public boolean onUnbind(Intent intent) {
Log.d(TAG, "RESTService onUnbind");
return true;
}
public class MyBinder extends Binder {
public RESTService getService() {
return RESTService.this;
}
}
}
As you mention in your edit, the current Activity is destroyed and recreated on orientation change.
But how can I save current activity reference?
You shouldn't. The previous Activity is no longer valid. This will not only cause NPEs but also memory leaks because the AsyncTask might hold the reference to old Activity, maybe forever.
Solution is to use Loaders.

Categories

Resources