I am trying to create a softphone application that can receive and make calls with a users credentials. I have everything working but the issue I am having now is keeping the user logged in, or registered, to the SIP Client. I have read many articles to keep the Wifi connection alive while I am trying to connect. I added some code I got from another program and even that doesn't work.
What I really need is a way for the phone to stay registered all the time. I know it can be done because of apps like Linphone and Bria. Does anyone have any suggestions.
Here is my onNetworkChangeReceiver which listens for network changes. Please let me know if this code is garbage and if you have any suggestions please let me know
import com.zxd.activity.util.PhoneState;
import android.content.Context;
import android.content.Intent;
import android.support.v4.content.WakefulBroadcastReceiver;
public class OnNetworkChangeReceiver extends WakefulBroadcastReceiver {
#Override
public void onReceive(Context context, Intent intent) {
PhoneState phoneState = PhoneState.getInstance();
// This is the Intent to deliver to our service.
Intent service = new Intent(context, OnNetworkChangeListener.class);
if(phoneState.threadIntent != null){
WakefulBroadcastReceiver.completeWakefulIntent(phoneState.threadIntent);
}
phoneState.setThreadIntent(intent);
// Start the service, keeping the device awake while it is launching.
startWakefulService(context, service);
}
}
PS: This receiver gets android.net.conn.CONNECTIVITY_CHANGE
This is the OnNetworkChangeListener
import android.app.IntentService;
import android.content.Intent;
import android.support.v4.content.WakefulBroadcastReceiver;
import com.zxd.activity.SipManager;
public class OnNetworkChangeListener extends IntentService{
private static String TAG = "OnNetworkChangeListener";
private static Intent i;
public OnNetworkChangeListener() {
super(TAG);
}
#Override
protected void onHandleIntent(Intent intent) {
i = intent;
SipManager sipManager = SipManager.getInstance();
sipManager.onNetworkChange();
}
#Override
public void onDestroy(){
super.onDestroy();
if(i != null){
WakefulBroadcastReceiver.completeWakefulIntent(i);
}
}
}
I used this for my app. But in the end, that damage my battery.
Android Developer Docs:
Settings.System.putInt(getContentResolver(), Settings.System.WIFI_SLEEP_POLICY, Settings.System.WIFI_SLEEP_POLICY_NEVER);
Have you tried to use WifiLock?
For my solution I looked at linphone. They are an open-source softphone application and they have a great way to implement a KeepAlive Service and KeepAlive Handler. This has worked for me
Did you try using a WakeLock? Also have a look at the PowerManager class.
Hope this helps.
Related
I have made an app in which a service runs in the background. But if the android system requires resources, it will stop the service. However I may still require my service to run.
Is it a bad practice to restart the service (if condition relevant to my app still holds true) in the onDestroy method of my service?
How can I make sure my service runs indefinitely (if condition relevant to my app still holds true)? Or atleast on high priority?
Probably the best you can do is use the START_STICKY flag, which tells Android to attempt to restart the service if it has stopped. Beyond that ensure that it consumes as few resources as possible, so that it is less likely to be destroyed.
Android prioritizes the UI over everything. Then processes that are related to the UI. Then processes that are consuming the least amount of resources. A Service runs in the background, so unless it has resources that are also in use on the UI or connected to the UI in some way, it should be a lower priority.
Also you cannot tell Android how to prioritize your Service (everyone would make theirs the "highest priority" right?). So it goes by how well you minimize the impact on overall resources - why kill 3 Services when it could kill 1 and regain all the resources it needs?
To help understand how to manage memory better: http://developer.android.com/training/articles/memory.html
set it START_STICKY. It Causes after killing service the service will restart again. it is my code :
android manifest :
<application
....
<service android:name=".UpdateService" />
</application>
service class :
import android.app.Service;
import android.content.BroadcastReceiver;
import android.content.Intent;
import android.content.IntentFilter;
import android.os.IBinder;
import android.util.Log;
import android.widget.Toast;
public class UpdateService extends Service {
BroadcastReceiver mReceiver;
#Override
public void onCreate() {
super.onCreate();
// register receiver that handles screen on and screen off logic
IntentFilter filter = new IntentFilter(Intent.....);
filter.addAction(Intent....);
mReceiver = new MyReceiver();
registerReceiver(mReceiver, filter);
}
#Override
public void onDestroy() {
unregisterReceiver(mReceiver);
Log.i("onDestroy Reciever", "Called");
super.onDestroy();
}
#Override
public void onStart(Intent intent, int startId) {
Log.i("log", "action Called");
}
}
#Override
public IBinder onBind(Intent intent) {
// TODO Auto-generated method stub
return null;
}
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
return Service.START_STICKY;
}
}
receiver class :
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.util.Log;
public class MyReceiver extends BroadcastReceiver {
#Override
public void onReceive(Context context, Intent intent) {
Log.i("Log", "recevid");
}
}
in StartupActivity :
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
Context context = getApplicationContext();
Intent service = new Intent(context, UpdateService.class);
context.startService(service);
}
i am writing a bluetooth app communicating with a bluetooth module. Actually it works very well. But i want the connection to stay established also while the app is in background and other apps are used, so that another activity like incoming sms or something else can trigger my app in background to send messages to my device.
Until now i am very confused how to do this. Can anyone give me advice?
I also checked this: Background Bluetooth App - Threading? but it doesn't help me.
Here is my code so far:
http://pastebin.com/C7Uynuan
Side information: there is a connect button, which establishs the connection and then there are 3 other buttons sending different messages to my device.
In OnResume i reconnect to my device, but this should be not necessary when having a stable connection.
Thanks,
progNewfag
EDIT: Now i am pretty sure that i need to use an IntentService, but not sure how.
You Have to learn the service first
Here is the Example of Service
Create a new Class and Name it for Exmaple: MyService
import android.app.Service;
import android.content.Intent;
import android.os.IBinder;
import android.widget.Toast;
public class MyService extends Service {
public MyService() {
}
#Override
public IBinder onBind(Intent intent) {
return Null;
}
#Override
public void onCreate() {
Toast.makeText(this, "The new Service was Created", Toast.LENGTH_LONG).show();
}
#Override
public void onStart(Intent intent, int startId) {
// For time consuming an long tasks you can launch a new thread here...
// Do your Bluetooth Work Here
Toast.makeText(this, " Service Started", Toast.LENGTH_LONG).show();
}
#Override
public void onDestroy() {
Toast.makeText(this, "Service Destroyed", Toast.LENGTH_LONG).show();
}
}
Now in your main activity you can start the service through this code
startService(new Intent(this, MyService.class));
For Stopping the service put this code in MainActivity
stopService(new Intent(this, MyService.class));
See this Post
Connection between Activity and Service
Also See this link
http://www.javacodegeeks.com/2014/01/android-service-tutorial.html
http://examples.javacodegeeks.com/android/core/service/android-service-example/
EDIT:
Example: Communication between Activity and Service using Messaging
http://www.intertech.com/Blog/using-localbroadcastmanager-in-service-to-activity-communications/
Ok, I think this is a recurring question, sorry for that. I need to update my DB collecting some data from web and display a dialog while the data are being downloaded.
I have my dialog, data comes fine and writes in database.
I'm doing some improvements. Today this works starting from one Activity. My will is this occurs in all application and start after a interval. And this is the moment when problems arise.
I'm using AlertManager to schedule my action. I have a BroadcastReceiver that, checks my database and starts to get data from web. At this point I'm facing problems. My progress dialog aren't shown and data doesn't come totally from web.
Code from BroadcastReceiver:
import android.app.Activity;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteException;
import android.os.Handler;
import android.util.Log;
import android.widget.Toast;
public class SchedulerUpdate extends BroadcastReceiver {
private Handler mHandler = null;
#Override
public void onReceive(Context context, Intent intent) {
try {
mHandler = new Handler();
Log.i("INFO", "SCHEDULED");
if(checkDataBase(context)){
updateData(context);
}
}
catch (Exception e) {
e.printStackTrace();
}
}
private boolean checkDataBase(Context context){
String path = "/data/data/"+context.getPackageName()+"/databases/mdsdacpdatabase.db";
SQLiteDatabase database = null;
boolean result = false;
try{
database = SQLiteDatabase.openDatabase(path, null, SQLiteDatabase.CREATE_IF_NECESSARY);
database.close();
result = true;
}
catch(SQLiteException e){
}
return result;
}
private void updateData(final Context context) {
((Activity)context.getApplicationContext()).showDialog(ID_DIALOG_PROGRESS_DOWNLOAD);
Runnable runnable = new Runnable(){
public void run(){
Log.i("INFO", "RUNNING");
...
mHandler.post(new Runnable() {
public void run() {
((Activity)context).dismissDialog(ID_DIALOG_PROGRESS_DOWNLOAD);
Log.i("INFO", "DONE");
}
});
};
};
new Thread(runnable).start();
}
}
Reading these posts on StackOverflow and on Kam:
BroadCast receiver dialog issue in Android
AlertDialog in BroadcastReceiver
show an alert dialog in broadcast receiver after a system reboot
How to send data from BroadcastReceiver to an Activity in android?
Android: Prefer Alarms and Intent Receivers to Services <--This is Kam
My conclusions are:
BroadcastReceivers can't display dialogs because they aren't
Activities(like Commonsware point out);
BroadcastReceivers can't
handle orientation issues that crashes app(I fix this in my activity
overriding onCreateDialog method);
Handlers aren't indicated to use
in BroadcastReceivers;
Services aren't indicated to do this kind of
task;
I thought a way to solve this. Creating a class that inherits from activity and inside that I handle orientation issues, schedule my broadcast in it to download the content at some time and displays dialog. And all of other classes inherits from it.
This solution works I think, but it's big workaround to solve the problem.
Sorry if my question is too long. I would like to discuss some other solutions(if what I proposed is a valid solution, I didn't tested).
A BroadcastReceiver object is only valid for the duration of the call
to onReceive(Context, Intent). Once your code returns from this
function, the system considers the object to be finished and no longer
active.
This has important repercussions to what you can do in an
onReceive(Context, Intent) implementation: anything that requires
asynchronous operation is not available, because you will need to
return from the function to handle the asynchronous operation, but at
that point the BroadcastReceiver is no longer active and thus the
system is free to kill its process before the asynchronous operation
completes.
In particular, you may not show a dialog or bind to a service from
within a BroadcastReceiver. For the former, you should instead use the
NotificationManager API. For the latter, you can use
Context.startService() to send a command to the service.
Source: http://developer.android.com/reference/android/content/BroadcastReceiver.html
I am trying to get my service to run when there is an outgoing call on my phone. But for some reason my service does not run when this happens. I know the code for the "CallReceiver" executes since I used a toast message to display if that runs. I am able to run the service through my main activity, but this means it will run regardless of whether an outgoing call is made....
Below is my code:
The Receiver:
package com.example.hiworld;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.util.Log;
import android.widget.Toast;
public class CallReceiver extends BroadcastReceiver{
#Override
public void onReceive(Context context, Intent intent) {
context.startService(new Intent(context, CallService.class));
Toast.makeText(context, "Call Receiver started",
Toast.LENGTH_LONG).show();
Log.d("Calling Someone", "onReceived");
}
}
The Service:
package com.example.hiworld;
import android.app.IntentService;
import android.content.Context;
import android.content.Intent;
import android.telephony.TelephonyManager;
import android.widget.Toast;
public class CallService extends IntentService {
public long StartTime=0;
public long EndTime =0;
public long TotalTime = 0;
public long NumFreeMins = 0;
public CallService() {
super("CallService");
}
#Override
protected void onHandleIntent(Intent intent) {
StartTime = (System.currentTimeMillis())/60;
TelephonyManager tm = (TelephonyManager) getSystemService(Context.TELEPHONY_SERVICE);
if(tm.getCallState()==0) //getting the time whenever the phone is off
{
EndTime = (System.currentTimeMillis())/60;
TotalTime = EndTime-StartTime;
NumFreeMins = 300-TotalTime;
//notify user
this.displaymsg();
}
}
public void displaymsg()
{
Toast toast = Toast.makeText(getApplicationContext(), ""+NumFreeMins, Toast.LENGTH_SHORT);
toast.show();
}
}
I have seen some people use the line:
context.startService(new Intent(this, CallService.class));
instead of:
context.startService(new Intent(context, CallService.class));
but the latter does not work for me...
Try specifying an <intent-filter> for your IntentService in the manifest for a specific 'action'. Example...
<service
android:name=".CallService" >
<intent-filter>
<action android:name="com.example.hiworld.intent.DO_SOMETHING" />
</intent-filter>
</service>
Then in the onReceive(...) method of your BroadcastReceiver do something like the following...
Intent callReceiverIntent = new Intent("com.example.hiworld.intent.DO_SOMETHING");
// Put the Intent received by the BroadcastReceiver as extras so the
// IntentService can process it...
callReceiverIntent.putExtras(intent);
context.startService(callReceiverIntent);
EDIT:
I built a simple test app based on the code you posted to pasrebin. I kept the code identical for the manifest, receiver and service and simply had to add a default Activity in order to get it to run.
I can see from monitoring logcat in the DDMS perspective of eclipse that the CallReceiver successfully receives the NEW_OUTGOING_CALL Intent and does, in fact, start the CallService.
The problem is, however, with attempting to show a Toast from an IntentService which causes an exception due to a 'leaked handler' and silently crashes.
The reason behind this is that an IntentService uses a background thread to carry out its work and trying to show the Toast (i.e., a UI element) from a non-UI thread won't work as the app has no UI components running. So, regardless of whether you use the local context variable or getApplicationContext(), there simply is no UI context with which to associate the Toast.
The reason why it works when starting the CallService from an Activity is obviously because the Activity provides a UI context that can be used by the Toast. In short, it generally seems that attempting to use Toast from an IntentService isn't a good idea unless the IntentService is always started by a UI component and even then, having a background thread create UI elements (such as a Toast) may cause problems.
The only way that this can be made to work with the current model is to change the IntentService to a Service. By default, code execution of a Service is done on the main (UI) thread and it is quite legal for a Service to show a Toast regardless of whether there are any of the app's Activities showing or not. In fact, I modified the code to use a Service and placed the code from onHandleIntent in onStartCommand() and I can see the Toasts when making an outgoing call.
Try
context.startService(new Intent(context.getApplicationContext(), CallService.class));
I Have a BroadcastReceiver set up to turn Bluetooth on and off according to power state (when plugged in, bluetooth is on, unplugged, bluetooth is off). This is working just fine (yay!). however, my very simple app has a single button, which also turns Bluetooth on and off, and has the text "Bluetooth on" or "Bluetooth Off", as applicable. I would like to update this single button, BUT, I only have to update it if the app is in the foreground.
Inside onResume on m,y main activity, I'm calling my updateUI method, which checks the Bluetooth state, and updates the button accordingly. however, that only applies if the program was open and in the background, and is resumed, NOT if i'm in the program while plugging/unplugging the power.
I created a new activity (CheckIfAppIsRunningActivity.java) with this code which is supposed to check if my app is running in the foreground, and if so, take it to the activity (BluetoothOnActivity) which will update the button:
package vermel.BluetoothOn;
import java.util.List;
import android.app.Activity;
import android.app.ActivityManager;
import android.app.ActivityManager.RunningAppProcessInfo;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.widget.Toast;
public class CheckIfAppIsRunningActivity extends Activity{
public void onCreate() {
checkStatus();
}
private BroadcastReceiver myBroadcastReceiver = new BroadcastReceiver() {
#Override
public void onReceive(Context context, Intent intent) {
Intent it = new Intent();
it.setClassName("vermel.BluetoothOn", "vermel.BluetoothOn.BluetoothOnActivity");
context.startActivity(it);
}
};
public void checkStatus() {
ActivityManager activityManager = (ActivityManager) getApplicationContext().getSystemService(Context.ACTIVITY_SERVICE);
List<RunningAppProcessInfo> runningProcInfo = activityManager.getRunningAppProcesses();
for(int i = 0; i < runningProcInfo.size(); i++){
if(runningProcInfo.get(i).processName.equals("vermel.BluetoothOn")) {
if (runningProcInfo.get(i).lru == RunningAppProcessInfo.IMPORTANCE_FOREGROUND){
//start activity
/* Intent it = new Intent();
it.setClassName("vermel.BluetoothOn", "vermel.BluetoothOn.BluetoothOnActivity");
context.startActivity(it); */
}
}
}
}
}
and i'm pointing to it from my broadcast receiver:
package vermel.BluetoothOn;
import android.bluetooth.BluetoothAdapter;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.widget.Button;
import android.widget.Toast;
public class BTDetector extends BroadcastReceiver {
BluetoothAdapter mBluetoothAdapter = BluetoothAdapter.getDefaultAdapter();
public void onReceive(Context context , Intent intent) {
String action = intent.getAction();
if (action.equals(Intent.ACTION_POWER_CONNECTED)) {
if (!mBluetoothAdapter.isEnabled()) {
mBluetoothAdapter.enable();
//TODO if app is open, change text on button to on
//Toast.makeText(context, "turned on bluetooth", Toast.LENGTH_LONG).show();
Intent i = new Intent();
i.setClassName("vermel.BluetoothOn", "vermel.BluetoothOn.CheckIfAppIsRunningActivity");
context.startActivity(i);
}
} else if (action.equals(Intent.ACTION_POWER_DISCONNECTED)) {
if (mBluetoothAdapter.isEnabled()){
mBluetoothAdapter.disable();
//TODO if app is open, change text on button to off
//Toast.makeText(context, "turned off bluetooth", Toast.LENGTH_LONG).show();
Intent i = new Intent();
i.setClassName("vermel.BluetoothOn", "vermel.BluetoothOn.CheckIfAppIsRunningActivity");
context.startActivity(i);
}
}
}
}
a few things: yes, I know i'm not supposed to use .enable() without user permission. in a weird way, plugging in the phone IS my user permission, since this is ALL that this app does, so, it's not sneaky, since you know what you're getting when you're installing the app.
The commented stuff is mostly things i've tried in vain..
I'm very open to the fact that i'm making this WAY harder than I need to...
so, as i said, it does turn Bluetooth on and off beautifully, but simply crashes after that. I can't debug it, since the emulator doesn't have Bluetooth , and i'm disconnecting the phone to get the crash result, so, it's not logging anything, since it's now connected...
I'm new in both Java and Android, and would appreciate a bit of patience. I try reading the official android documentation, but that's like chinese to me... so, an extended explanation would be great...
Thanks for reading!