Android detect incoming calls? - java

I am trying to develop an app where it will turn on your ringer if someone calls you a certain amount of times in a row in a certain period of time. This is my first real app, so I'm a little stuck.
How would I record whenever a call is received in an internal list? Would this need to be a service to always be running, or could this work in a normal app by just receiving the intent of the dialer app?
I apologize if this question is a little vague.

The best way to do it is, by declaring your broadcast receiver in the manifest, this will cause that the code on your BroadcastReceiver class to get executed everytime the event is fired, without the need of a service running in the background all the time, let the OS handle the observing part for you...
<receiver android:name=".ReceiverExample">
<intent-filter>
<action android:name="android.intent.action.PHONE_STATE" />
</intent-filter>
</receiver>
Now, in your broadcastreceiver class "ReceiverExample", create a SharedPreference to store the number of incomming calls, and based on that, you can validate if is time to do something else or not...
public class ReceiverExample extends BroadcastReceiver {
#Override
public void onReceive(Context context, Intent intent) {
//Logic to listen incoming calls, and keep track of them using Shared Preferences..
}
}
Services are good for long tasks but the OS it self is well suited to Monitor/Observe events (like Telephony events e.g. Incomming calls...), try not to re-do the OS work by creating Services just to monitor already known events...
Regards

use single Tone Class for recording
public class Recording {
private static MediaRecorder recorder;
private File audiofile;
private static Recording mInstance;
public MediaRecorder getRecorder() {
System.out.println("From singleton..!!!");
return recorder;
}
public static Recording getInstance(Context context) {
return mInstance == null ? (mInstance = new Recording(context))
: mInstance;
}
private Recording(Context context) {
System.out.println("Again initiated object");
File sampleDir = Environment.getExternalStorageDirectory();
try {
audiofile = File.createTempFile("" + new Date().getTime(), ".amr",
sampleDir);
} catch (IOException e) {
e.printStackTrace();
return;
}
recorder = new MediaRecorder();
recorder.setAudioSource(MediaRecorder.AudioSource.MIC);
recorder.setOutputFormat(MediaRecorder.OutputFormat.AMR_NB);
recorder.setAudioEncoder(MediaRecorder.AudioEncoder.AMR_NB);
recorder.setOutputFile(audiofile.getAbsolutePath());
}
}

Related

Bring Android app back from background programmatically

I'm new to Android coding but I already had played with java.
I want to open or bring my app back once it is in background.
I've been searching around but nothing seems to work.
I have a function of a class that is called every time a notification is received which is CordovaNotificationReceivedHandler and it is instantiated by the OneSignal init as per the code below.
OneSignal.init(this.cordova.getActivity(),
googleProjectNumber,
appId,
new CordovaNotificationOpenedHandler(notifOpenedCallbackContext),
new CordovaNotificationReceivedHandler(notifReceivedCallbackContext)
);
Trying to get my application to be reordered and displayed, even if the user is in another application, I made the following changes:
OneSignal.init(this.cordova.getActivity(),
googleProjectNumber,
appId,
new CordovaNotificationOpenedHandler(notifOpenedCallbackContext),
new CordovaNotificationReceivedHandler(this.cordova.getActivity(), notifReceivedCallbackContext));
In the body of the function that is called when receiving a push notification I added the following code:
Intent it = new Intent("intent.my.action");
it.setComponent(new ComponentName(contextActivy.getPackageName(), MainActivity.class.getName()));
it.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
contextActivy.getApplicationContext().startActivity(it);
this.handleActivityLifecycleHandler();
Como a classe ficou após a modificação:
private class CordovaNotificationReceivedHandler implements NotificationReceivedHandler {
private CallbackContext jsNotificationReceivedCallBack;
private Context contextActivy;
public CordovaNotificationReceivedHandler(Context contextActivy, CallbackContext inCallbackContext) {
jsNotificationReceivedCallBack = inCallbackContext;
this.contextActivy = contextActivy;
}
#Override
public void notificationReceived(OSNotification notification) {
Log.w("Got here","Aqui");
Intent it = new Intent("intent.my.action");
it.setComponent(new ComponentName(contextActivy.getPackageName(), MainActivity.class.getName()));
it.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
contextActivy.getApplicationContext().startActivity(it);
this.handleActivityLifecycleHandler();
try {
CallbackHelper.callbackSuccess(jsNotificationReceivedCallBack, new JSONObject(notification.stringify()));
}
catch (Throwable t) {
t.printStackTrace();
}
}
}
The problem is that the application is not reordered to be applied or opened.
It is important to remember that I am assuming that the application should be open.
You can use this, It work fine.
Intent intent = new Intent("intent.my.action");
intent.setComponent(new ComponentName(this, yourActivity.class));
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
intent.addFlags(Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED);
startActivity(intent);
Don't Forget Add this in your activity in manifest
<intent-filter>
<action android:name="intent.my.action" />
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>

JobIntentService onHandleWork not being called

I have a skeleton class of JobIntentService
public class BackgroundRequestService extends JobIntentService {
/**
* Unique job ID for this service.
*/
static final int JOB_ID = 1234;
public static void enqueueWork(Context context, Intent work) {
BackgroundRequestService.enqueueWork(context, BackgroundRequestService.class, JOB_ID, work);
}
#Override
protected void onHandleWork(#NonNull Intent intent) {
if (intent.getExtras() != null){
String x = ";";
}
}
}
I have included the Service in the manifest
<service android:name=".BackgroundRequestService"
android:enabled="true"
android:permission="android.permission.BIND_JOB_SERVICE"
android:exported="false" />
And calling the proper enqueue method
Intent intent = new Intent();
intent.putExtra("hardware", hardware);
BackgroundRequestService.enqueueWork(context, intent);
But the onHandleWork is never getting called. i have looked at all the pages about setting the services correctly and making sure onBind isn't overridden, but this still isn't working, wondering if another set of eyes would spot something ive missed. Thank you
Try to start service this way:
ComponentName comp = new ComponentName(context.getPackageName(), BackgroundRequestService.class.getName());
BackgroundRequestService.enqueueWork(context, (getIntent().setComponent(comp)));
Found the issue through some proper looking into the Logcat
Turns out the "hardware" that i was putting into my Intent was missing a field to be Serialized.
This caused this message to appear in the Logcat
I/UDP: no longer listening for UDP broadcasts cause of error Parcelable encountered IOException writing serializable object (name = Project.Hardware)
After fixing this Serialization issue i was able to call the onHandleWork() method.

Communicate between service and activity

I have a class in a service
MyClass m = new MyClass();
and inside my class I check if I have permission to overlay the view; if so, it's ok, otherwise I must start an activity
if (Settings.canDrawOverlays(mContext)) {
// draw over app
} else {
// start the activity
Intent i = new Intent(context,Calls.class);
context.startActivity(i);
}
When I start the activity I have a problem communicating between the class and the activity. I know how to use the interface but how can I register it in activity.
Some time I want to pass an object or data from the class to the activity or from the activity to the class... how can I do that?
I saw many examples in Stack Overflow about how to communicate between service and activity; they suggest to start the class from the activity but this does not work in my app because my class must be running all the time.
Perhaps you could use an event bus like mechanism where you can send or receive events through out your app, Though there are several libraries out there, I would recommend using Otto library for android.
Usage is pretty simple just register in your activity onCreate
Bus bus = new Bus();
bus.register(this);
For sending events
// example data to post
public class TestData {
public String message;
}
// post this data
bus.post(new TestData().message="Hello from the activity");
And subscribe to events like this
#Subscribe public void getMessage(TestData data) {
// TODO: React to the event somehow!
}
More info here
If you want to implement a communication pattern between a Service and an Activity, you should use a LocalBroadcastManager.
It will turn handy because, in case your Service is still on but your Activity
has been destroyed (very common situation), then the 'messagging' between the two will simply have no effect (no NPE or whatsoever will be thrown).
Step 1
Create a BroadcastReceiver in your Activity and define an ID / Filter
this.localBroadcastReceiver = new BroadcastReceiver() {
#Override
public void onReceive(Context context, Intent intent) {
// Do what you have to do here if you receive data from the Service / Background Task
}
}
public static final IntentFilter SIGNAL_FILTER = new IntentFilter("com.you.yourapp.MY_SIGNAL")
Step 2
In your Activity register the broadcast in onResume() and unregister it in onPause().
#Override
protected void onResume() {
// Listen if a Service send me some data
LocalBroadcastManager.getInstance(getApplicationContext()).registerReceiver(this.localBroadcastReceiver, SIGNAL_FILTER);
}
#Override
protected void onPause() {
// I'm going to the background / or being destroyed: no need to listen to anything anymore...
LocalBroadcastManager.getInstance(getApplicationContext()).unregisterReceiver(this.localBroadcastReceiver);
}
Your Activity is now ready to receive data from any other component in your Application.
If it's in the background, then there is no need to update the UI: in fact the Activity will not respond if in the background.
In the same way, if it's being garbage collected, the Receiver will be unregistered and the Activity will just not respond to anything.
If the Activity is resumed / restarted, onResume() will be triggered and the Receiver will be registered again.
Step 3
All you need to do right now, is send data from the Service.
Simply call
final Intent intent = new Intent();
intent.setAction(SomeActivity.SIGNAL_FILTER);
// put your data in intent
LocalBroadcastManager.getInstance(getApplicationContext()).sendBroadcast(intent);
and your Activity will accordingly respond to the signal.
It's surprising how few people know about the LocalBroadcastManager and instead use some self-implemented callback / singleton pattern, which increases complexity and non-readability.
This pattern is built-in in Android, so you don't need external libraries. As for security, this ensures that your signals stay internal to your application: no data can therefore be read by other apps.
I similarly answered to another question here.

Load data if connected to the Internet

Helle Stack community,
I created a simple app that loads a json and loads the data in a recyclerview.
The recyclerview includes cardviews.
The activity shows me a blank page if I haven't any internet connection,
but normally I want to see some blank cardviews like in the 9GAG app.
In the 9GAG app you get all data on swipe the display.
My app should load all data on internet connection is available. I googled something about broadcast receiver, but can't find a simple example for my need.
Maybe someone can show me a simple example or the way to do some action like in the 9GAG app. Info: The app is for api 21 User.
I would appreciate it.
public class NetworkChangeReceiver extends BroadcastReceiver {
#Override
public void onReceive(final Context context, final Intent intent) {
if (Network.isNetworkAvailable(Constants.ApplicationContext)) {
} else {
}
}
}
public class Network {
public static boolean isNetworkAvailable(Context context) {
int retriesNum = Constants.checkConnectionRetriesNum;// a number that I put as 5 for retries to make consideration for bad connections
if(context!=null)
while (retriesNum > 0) {
try {
ConnectivityManager connectivityManager = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE);
NetworkInfo network = connectivityManager.getActiveNetworkInfo();
boolean isConnected = network != null &&
network.isConnectedOrConnecting();
if (isConnected) {
return true;
} else {
network = connectivityManager.getNetworkInfo(ConnectivityManager.TYPE_WIFI);
isConnected = network != null && network.isConnectedOrConnecting();
if (isConnected) {
return true;
} else {
network = connectivityManager.getNetworkInfo(ConnectivityManager.TYPE_MOBILE);
isConnected = network != null && network.isConnectedOrConnecting();
if (isConnected) {
return true;
} else {
retriesNum--;
}
}
}
}catch (Exception ex){
return true;
}
}
return false;
}
Use a BroadcastReceiver that gets notified, when the connection state changes. It is very important that you register it in your manifeset!
Add a class, similar to this to your project:
public class NetworkChangedReceiver extends BroadcastReceiver {
#Override
public void onReceive(Context context, Intent intent) {
// Network state changed!
// Check if the user connected using ConnectivityManager.getActiveNetworkInfo()
}
}
Add it to your manifest file, so the systems knows it should notify you:
<manifest>
...
<application>
...
<receiver
android:name=".NetworkChangedReceiver"
android:process=":remote">
<intent-filter>
<action android:name="android.net.conn.CONNECTIVITY_CHANGE"/>
</intent-filter>
</receiver>
...
</application>
</manifest>
Edit:
From the docs:
Apps targeting Android 7.0 (API level 24) do not receive CONNECTIVITY_ACTION broadcasts if they register to receive them in their manifest, and processes that depend on this broadcast will not start. This could pose a problem for apps that want to listen for network changes or perform bulk network activities when the device connects to an unmetered network. Several solutions to get around this restriction already exist in the Android framework, but choosing the right one depends on what you want your app to accomplish.
Note: A BroadcastReceiver registered with Context.registerReceiver()
continues to receive these broadcasts while the app is running.
I didn't knew about this, so thanks to #Paul Nie for letting me know :D
I can't really help further at this point. But this seems like a good point to start some research about this topic: https://developer.android.com/topic/performance/background-optimization.html#connectivity-action

Checking in with server in the background in Java-Android

I am trying to write an app that checks in with a server every X seconds.
I was able to make it work, but only when the application is running and active (not sure if it can be minimized, was not able to test it clearly) and the device is not locked. I would like for the checking to continue even if I lock the device or do other things on it.
From my searches, it seems like I should use service, but I was not able to figure out how to implement it with what I am trying to do. Or is there something else that could do this?
What I need to and failed to do is this:
User checks a CheckBox - start the service
Create the service and pass some information to it
Create an instance of my class in the service using the passed information
Call this instance's method every X seconds in a new thread (the method returns true/false)
Listen to ?something and if the method returns true then stop the service and notify user
If the user unchecks the CheckBox, stop the service.
I tried doing this, but I was unable to get any information out of the thread and out of the service. Is there a way to do so?
Starting the service from activity for example and binding it with your app
//make these 2 variables as fields in Activity for example
YourService yourService = null;
//this variable can be used for checking if your activity are binded already or not
boolean mBounded = false;
Intent mIntent = new Intent(this, YourService.class);
startService(mIntent);
bindService(mIntent, mConnection, BIND_AUTO_CREATE);
ServiceConnection mConnection = new ServiceConnection() {
public void onServiceDisconnected(ComponentName name) {
mBounded = false;
yourService = null;
}
public void onServiceConnected(ComponentName name, IBinder service) {
mBounded = true;
YourService.LocalBinder mLocalBinder = (YourService.LocalBinder) service;
yourService= mLocalBinder.getServerInstance();
}
};
Do not forget that you can use methods from Service in Activity only after it is bound to your Activity. In other words it is available only after onServiceConnected is executed.
So you have now service and activity who can communicate with each other.
For example you can call in Activity some public method of your Service, like
if (yourService != null)
yourService.test();
If you want to call your Activity methods in Service you should pass it to Service with simple setter.
If you want to stop Service its kinda easy too:
Intent mIntent = new Intent(this, YourService.class);
stopService(mIntent);
For doing request every X service:
1) You can do infinity separate thread inside Service and do request after delay for X seconds.
2) For checking every X seconds you can use something like AlarmManager.
3) Also its possible to use CountDownTimer inside your Service to do some requests to server.
If you want to create your Service after reboot if CheckBox was set, its easy too. So you should use simple BroadcastReceiver.
First of all you should save your CheckBox setting in SharedPreferences, then run your Service if you need.
public class SimpleReceiver extends WakefulBroadcastReceiver{
#Override
public void onReceive(Context context, Intent intent) {
//run below code if you need, depends on your saved value of Checkbox in SharedPreferences
Intent serviceIntent = new Intent(context, YourService.class);
context.startService(serviceIntent);
}
}
And for sure dont forget to add in AndroidManifest information about your Service and Receiver to be sure it will run automatically after reboot.
<service
android:name=".package.YourService"
android:enabled="true"
android:exported="false"> </service>
<receiver
android:name=".package.SimpleReceiver"
android:enabled="true"
android:exported="true">
<intent-filter>
<action android:name="android.intent.action.BOOT_COMPLETED" />
<action adroid:name="android.intent.action.QUICKBOOT_POWERON" />
</intent-filter>
</receiver>

Categories

Resources