I want to implement Call Recording for one of my client application but above Android 10 I am unable to do is successfully. here is my code classes. Your suggestions will be highly appreciated.
I know due to security reasons Google stopped working around Call Recording above Android 10(Q), But I needs this feature for CRM application.
This is my Receiver Class
public abstract class PhonecallReceiver extends BroadcastReceiver {
// The receiver will be recreated whenever android feels like it.
// We need a static variable to remember data between instantiations
private static int lastState = TelephonyManager.CALL_STATE_IDLE;
private static Date callStartTime;
private static boolean isIncoming;
private static String savedNumber; // because the passed incoming is only valid in ringing
#Override
public void onReceive(final Context context, Intent intent) {
// We listen to two intents. The new outgoing call only tells us of an outgoing call.
// We use it to get the number.
if (intent.getAction().equals("android.intent.action.NEW_OUTGOING_CALL")) {
savedNumber = intent.getExtras().getString("android.intent.extra.PHONE_NUMBER");
} else {
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.P) {
String stateStr = intent.getExtras().getString(TelephonyManager.EXTRA_STATE);
String number = intent.getExtras().getString(TelephonyManager.EXTRA_INCOMING_NUMBER);
int state = 0;
if (stateStr.equals(TelephonyManager.EXTRA_STATE_IDLE)) {
state = TelephonyManager.CALL_STATE_IDLE;
} else if (stateStr.equals(TelephonyManager.EXTRA_STATE_OFFHOOK)) {
state = TelephonyManager.CALL_STATE_OFFHOOK;
} else if (stateStr.equals(TelephonyManager.EXTRA_STATE_RINGING)) {
state = TelephonyManager.CALL_STATE_RINGING;
}
onCustomCallStateChanged(context, state, number);
} else {
// Android 9+
TelephonyManager telephony = (TelephonyManager) context.getSystemService(Context.TELEPHONY_SERVICE);
telephony.listen(new PhoneStateListener() {
#Override
public void onCallStateChanged(int state, String number) {
onCustomCallStateChanged(context, state, number);
}
}, PhoneStateListener.LISTEN_CALL_STATE);
}
}
}
// Derived classes should override these to respond to specific events of interest
protected abstract void onIncomingCallStarted(Context ctx, String number, Date start);
protected abstract void onOutgoingCallStarted(Context ctx, String number, Date start);
protected abstract void onIncomingCallEnded(Context ctx, String number, Date start, Date end);
protected abstract void onOutgoingCallEnded(Context ctx, String number, Date start, Date end);
protected abstract void onMissedCall(Context ctx, String number, Date missed);
// Deals with actual events
// Incoming call - goes from IDLE to RINGING when it rings, to OFFHOOK when it's answered, to IDLE when its hung up
// Outgoing call - goes from IDLE to OFFHOOK when it dials out, to IDLE when hung up
public void onCustomCallStateChanged(Context context, int state, String number) {
if (lastState == state) {
// No change, debounce extras
return;
}
switch (state) {
case TelephonyManager.CALL_STATE_RINGING:
isIncoming = true;
callStartTime = new Date();
savedNumber = number;
onIncomingCallStarted(context, number, callStartTime);
break;
case TelephonyManager.CALL_STATE_OFFHOOK:
// Transition of ringing->offhook are pickups of incoming calls. Nothing done on them
if (lastState != TelephonyManager.CALL_STATE_RINGING) {
isIncoming = false;
callStartTime = new Date();
onOutgoingCallStarted(context, savedNumber, callStartTime);
}
break;
case TelephonyManager.CALL_STATE_IDLE:
// Went to idle - this is the end of a call. What type depends on previous state(s)
if (lastState == TelephonyManager.CALL_STATE_RINGING) {
// Ring but no pickup - a miss
onMissedCall(context, savedNumber, callStartTime);
} else if (isIncoming) {
onIncomingCallEnded(context, savedNumber, callStartTime, new Date());
} else{
onOutgoingCallEnded(context, savedNumber, callStartTime, new Date());
}
break;
}
lastState = state;
}
}
This is my service that will work in background to record Audio Calls.
class CallRecorderNew : Service(), onCallingListner {
private lateinit var recorder: MediaRecorder
private var recordStarted = false
private var savedNumber: String? = null
private var lastState = TelephonyManager.CALL_STATE_IDLE
private var isIncoming = false
var fileName //Obtained by intent
: String? = null
var audiouri: Uri? = null
var file: ParcelFileDescriptor? = null
private val CHANNEL_ID = "NOTIFICATION_CHANNEL"
private lateinit var callReceiver: CallReceiver
private var viewmodal: ViewModal? = null
override fun onBind(arg0: Intent): IBinder? {
// TODO Auto-generated method stub
return null
}
override fun onDestroy() {
this.unregisterReceiver(callReceiver)
}
override fun onStartCommand(intent: Intent, flags: Int, startId: Int): Int {
val intentFilter = IntentFilter()
intentFilter.addAction(ACTION_IN)
intentFilter.addAction(ACTION_OUT)
callReceiver = CallReceiver(this)
this.registerReceiver(callReceiver, intentFilter)
val notificationIntent = Intent(this, MainActivity::class.java)
val pendingIntent = PendingIntent.getActivity(
this,
0, notificationIntent,
PendingIntent.FLAG_UPDATE_CURRENT or PendingIntent.FLAG_MUTABLE
)
val notification = NotificationCompat.Builder(this, CHANNEL_ID)
.setContentTitle(R.string.app_name.toString() + " is running")
.setContentText("Please don not use battery optimizations")
.setSmallIcon(R.drawable.meeting_ic)
.setContentIntent(pendingIntent)
.setColor(resources.getColor(R.color.colorPrimary))
.build()
startForeground(1, notification)
// return super.onStartCommand(intent, flags, startId);
return START_STICKY
}
private fun stopRecording() {
if (recordStarted) {
try {
recorder.stop()
} catch (e: Exception) {
e.printStackTrace()
}
recordStarted = false
}
}
override fun onCreate() {
super.onCreate()
createNotificationChannel()
isServiceRunning = true
}
private fun createNotificationChannel() {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
val appName = getString(R.string.app_name)
val serviceChannel = NotificationChannel(
CHANNEL_ID,
appName,
NotificationManager.IMPORTANCE_DEFAULT
)
val manager = getSystemService(
NotificationManager::class.java
)
manager.createNotificationChannel(serviceChannel)
}
}
private fun saveAudioToExternalStorage(displayName: String): Boolean {
val recordingCollection = sdk29AndUp {
MediaStore.Audio.Media.getContentUri(MediaStore.VOLUME_EXTERNAL_PRIMARY)
} ?: MediaStore.Audio.Media.EXTERNAL_CONTENT_URI
val contentValue = ContentValues().apply {
put(MediaStore.Audio.Media.DISPLAY_NAME, displayName)
put(MediaStore.Audio.Media.MIME_TYPE, "audio/mpeg")
put(MediaStore.Audio.Media.TITLE, displayName)
put(MediaStore.Audio.Media.DATE_ADDED, (System.currentTimeMillis() / 1000).toInt())
}
return try {
contentResolver.insert(recordingCollection, contentValue)?.also { uri ->
contentResolver.openOutputStream(uri).use { outputStream ->
file = contentResolver.openFileDescriptor(uri, "w")
if (file != null) {
recorder = MediaRecorder()
recorder.setAudioSource(MediaRecorder.AudioSource.MIC)
recorder.setOutputFormat(MediaRecorder.OutputFormat.THREE_GPP)
recorder.setAudioEncoder(MediaRecorder.AudioEncoder.AMR_NB)
recorder.setOutputFile(file!!.fileDescriptor)
recorder.prepare()
recorder.start()
MainActivity.history[MainActivity.history.size - 1].recordingUrl =
uri.toString()
}
}
} ?: throw IOException("Couldn't create Media Store Entry")
true
} catch (e: Exception) {
e.printStackTrace()
false
}
}
companion object {
const val ACTION_IN = "android.intent.action.PHONE_STATE"
const val ACTION_OUT = "android.intent.action.NEW_OUTGOING_CALL"
const val EXTRA_PHONE_NUMBER = "android.intent.extra.PHONE_NUMBER"
var isServiceRunning = false
}
override fun onIncomingCallStarted(ctx: Context?, number: String?, date: String) {
isIncoming = true
savedNumber = number
saveAudioToExternalStorage("Incoming $savedNumber $date")
recordStarted = true
}
override fun onIncomingCallEnded(ctx: Context?, number: String?, date: String) {
stopRecording()
}
override fun onOutgoingCallStarted(ctx: Context?, number: String?, date: String) {
isIncoming = true
savedNumber = number
saveAudioToExternalStorage("Outgoing $savedNumber $date")
recordStarted = true
}
override fun onOutgoingCallEnded(ctx: Context?, number: String?, date: String) {
stopRecording()
}
override fun onMissedCall(ctx: Context?, number: String?, date: String) {
stopRecording()
}
internal class CallReceiver(private val callingListner: onCallingListner) :
PhonecallReceiver() {
override fun onOutgoingCallStarted(ctx: Context, number: String, start: Date) {
val msg = "start outgoing call: $number at $start"
Log.d("CallReceiverChecker", msg)
Toast.makeText(ctx.applicationContext, msg, Toast.LENGTH_SHORT).show()
callingListner.onOutgoingCallStarted(ctx, number, setDateTime())
}
override fun onOutgoingCallEnded(ctx: Context, number: String, start: Date?, end: Date) {
val msg = "end outgoing call: $number at $end"
Log.d("CallReceiverChecker", msg)
Toast.makeText(ctx.applicationContext, msg, Toast.LENGTH_SHORT).show()
callingListner.onOutgoingCallEnded(ctx, number, setDateTime())
}
override fun onIncomingCallStarted(ctx: Context, number: String, start: Date) {
val msg = "start incoming call: $number at $start"
Log.d("CallReceiverChecker", msg)
Toast.makeText(ctx.applicationContext, msg, Toast.LENGTH_SHORT).show()
callingListner.onIncomingCallStarted(ctx, number, setDateTime())
}
override fun onIncomingCallEnded(ctx: Context, number: String, start: Date?, end: Date) {
val msg = "end incoming call: $number at $end"
Log.d("CallReceiverChecker", msg)
Toast.makeText(ctx.applicationContext, msg, Toast.LENGTH_SHORT).show()
callingListner.onIncomingCallEnded(ctx, number, setDateTime())
}
override fun onMissedCall(ctx: Context, number: String, missed: Date) {
// callingListner.onMissedCall(ctx, number, setDateTime())
val msg = "missed call: $number at $missed"
Log.d("CallReceiverChecker", msg)
Toast.makeText(ctx.applicationContext, msg, Toast.LENGTH_SHORT).show()
callingListner.onMissedCall(ctx, number, setDateTime())
}
}
}
This is manifest file
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
package="app.sten.wit">
<uses-permission android:name="android.permission.READ_CALL_LOG" />
<uses-permission android:name="android.permission.READ_PHONE_STATE" />
<uses-permission android:name="android.permission.PROCESS_OUTGOING_CALLS" />
<uses-permission android:name="android.permission.CALL_PHONE" />
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.FOREGROUND_SERVICE" />
<uses-permission android:name="android.permission.RECORD_AUDIO" />
<uses-permission android:name="android.permission.MANAGE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED"/>
<uses-permission android:name="android.permission.READ_CONTACTS" />
<uses-permission android:name="android.permission.WRITE_CONTACTS" />
<uses-permission android:name="android.permission.PROCESS_INCOMING_CALLS" />
<uses-permission android:name="android.permission.DISABLE_KEYGUARD" />
<uses-permission android:name="android.permission.WAKE_LOCK" />
<uses-permission android:name="android.permission.MODIFY_AUDIO_SETTINGS"/>
<uses-permission android:name="android.permission.ANSWER_PHONE_CALLS" />
<uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW"/>
<uses-permission android:name="com.android.vending.BILLING"/>
<uses-permission android:name="android.permission.ACCESS_NOTIFICATION_POLICY"/>
<application
android:allowBackup="true"
android:fullBackupContent="true"
android:icon="#mipmap/ic_launcher"
android:label="#string/app_name"
android:roundIcon="#mipmap/ic_launcher_round"
android:supportsRtl="true"
android:theme="#style/AppTheme"
android:usesCleartextTraffic="true"
tools:ignore="GoogleAppIndexingWarning">
<!-- <activity-->
<!-- android:name=".Views.MainActivity"-->
<!-- android:exported="true">-->
<!-- <intent-filter>-->
<!-- <action android:name="android.intent.action.MAIN" />-->
<!-- <category android:name="android.intent.category.LAUNCHER" />-->
<!-- </intent-filter>-->
<!-- </activity>-->
<service android:name=".CallRecorderNew" />
<activity
android:name=".Views.HistoryActivity"
android:exported="true" />
<activity
android:name=".Views.AddMeetingsActivity"
android:exported="true" />
<activity
android:name=".Views.AddClientActivity"
android:exported="false" />
<activity
android:name=".Views.ScheduleMeetingsActivity"
android:exported="false" /> <!-- <activity -->
<!-- android:name=".Views.MeetingsActivity" -->
<!-- android:exported="false" /> -->
<activity
android:name=".Views.DetailsActivity"
android:exported="false" />
<activity
android:name=".Views.MainActivity"
android:exported="true">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<!-- <receiver-->
<!-- android:name=".BootCompleteReceiver"-->
<!-- android:exported="true">-->
<!-- <intent-filter android:priority="999">-->
<!-- <action android:name="android.intent.action.BOOT_COMPLETED" />-->
<!-- <action android:name="android.intent.action.QUICKBOOT_POWERON" />-->
<!-- <action android:name="com.htc.intent.action.QUICKBOOT_POWERON" />-->
<!-- </intent-filter>-->
<!-- </receiver>-->
<service android:name=".CallRecorderNew" />
</application>
</manifest>
I have also added permission for MediaProjectionManager but I don't think this is working.
Google is actively disallowing call recording by 3rd-party apps. Here's a good write-up for it, but the short answer is that you simply can't record calls any longer
Related
I have an NFC TAG scanner application which works fine and scans the tag and i can also read and write into tags without any issues , the only issue is that when i change the app package name and start the code , the nfc no longer works and scans tags , but when i revert to the other package name it works fine , any reason why and what could be wrong , Thank you in advance
class ActivateActivity : AppCompatActivity() {
private lateinit var binding : ActivityActivateScreenBinding
lateinit var writeTagFilters: Array<IntentFilter>
var nfcAdapter: NfcAdapter? = null
var pendingIntent: PendingIntent? = null
var writeMode = false
var myTag: Tag? = null
var actualMsg = ""
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
binding = ActivityActivateScreenBinding.inflate(layoutInflater)
setContentView(binding.root)
binding.btnActivate.setOnClickListener {
val organizationId = binding.organizationIdEdit.text.toString()
val nfcMsg = binding.txtNFCMessage.text.toString()
actualMsg = DOMAIN + organizationId + ucync + nfcMsg
try {
if(myTag == null){
Toast.makeText(this, ERROR_DETECTED,Toast.LENGTH_LONG).show()
} else {
write(actualMsg,myTag)
Toast.makeText(this, WRITE_SUCCESS,Toast.LENGTH_LONG).show()
}
}
catch (e : IOException){
Toast.makeText(this, WRITE_ERROR, Toast.LENGTH_LONG).show()
e.printStackTrace()
}
catch (e: FormatException){
Toast.makeText(this, WRITE_ERROR, Toast.LENGTH_LONG).show()
e.printStackTrace()
}
}
nfcAdapter = NfcAdapter.getDefaultAdapter(this)
if (nfcAdapter == null) {
// Stop here, we definitely need NFC
Toast.makeText(this, "This device doesn't support NFC.", Toast.LENGTH_LONG).show()
finish()
}
//For when the activity is launched by the intent-filter for android.nfc.action.NDEF_DISCOVERE
readFromIntent(intent)
pendingIntent = PendingIntent.getActivity(this, 0, Intent(this, javaClass)
.addFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP),
PendingIntent.FLAG_IMMUTABLE)
val tagDetected = IntentFilter(NfcAdapter.ACTION_TAG_DISCOVERED)
tagDetected.addCategory(Intent.CATEGORY_DEFAULT)
writeTagFilters = arrayOf(tagDetected)
}
/******************************************************************************
* Read From NFC Tag
****************************************************************************/
private fun readFromIntent(intent: Intent) {
val action = intent.action
if (NfcAdapter.ACTION_TAG_DISCOVERED == action || NfcAdapter.ACTION_TECH_DISCOVERED == action || NfcAdapter.ACTION_NDEF_DISCOVERED == action) {
myTag = intent.getParcelableExtra<Parcelable>(NfcAdapter.EXTRA_TAG) as Tag?
val rawMsgs = intent.getParcelableArrayExtra(NfcAdapter.EXTRA_NDEF_MESSAGES)
val msgs = mutableListOf<NdefMessage>()
if (rawMsgs != null) {
for (i in rawMsgs.indices) {
msgs.add(i, rawMsgs[i] as NdefMessage)
}
buildTagViews(msgs.toTypedArray())
}
}
}
private fun buildTagViews(msgs: Array<NdefMessage>) {
if (msgs.isEmpty()) return
val text: String
val payload = msgs[0].records[0].payload
val textEncoding: Charset = if ((payload[0] and 128.toByte()).toInt() == 0) Charsets.UTF_8 else Charsets.UTF_16 // Get the Text Encoding
val languageCodeLength: Int = (payload[0] and 51).toInt() // Get the Language Code, e.g. "en"
try {
// Get the Text
text = String(payload, languageCodeLength + 1, payload.size - languageCodeLength - 1, textEncoding)
Log.d("VALUE","VALUE IS " + text)
} catch (e: UnsupportedEncodingException) {
Log.e("UnsupportedEncoding", e.toString())
}
}
/******************************************************************************
* Write to NFC Tag
****************************************************************************/
private fun write(msg : String , tag : Tag?){
val records = arrayOf(createRecord(msg))
val message = NdefMessage(records)
// Get an instance of Ndef for the tag.
val ndef = Ndef.get(tag)
// Enable I/O
ndef.connect()
// Write the message
ndef.writeNdefMessage(message)
// Close the connection
ndef.close()
}
#Throws(UnsupportedEncodingException::class)
private fun createRecord(text: String): NdefRecord {
val lang = "en"
val textBytes = text.toByteArray()
val langBytes = lang.toByteArray(charset("US-ASCII"))
val langLength = langBytes.size
val textLength = textBytes.size
val payload = ByteArray(1 + langLength + textLength)
// set status byte (see NDEF spec for actual bits)
payload[0] = langLength.toByte()
// copy langbytes and textbytes into payload
System.arraycopy(langBytes, 0, payload, 1, langLength)
System.arraycopy(textBytes, 0, payload, 1 + langLength, textLength)
return NdefRecord(NdefRecord.TNF_WELL_KNOWN, NdefRecord.RTD_TEXT, ByteArray(0), payload)
}
/**
* For reading the NFC when the app is already launched
*/
override fun onNewIntent(intent: Intent) {
super.onNewIntent(intent)
setIntent(intent)
readFromIntent(intent)
if (NfcAdapter.ACTION_TAG_DISCOVERED == intent.action) {
myTag = intent.getParcelableExtra(NfcAdapter.EXTRA_TAG)
}
}
public override fun onPause() {
super.onPause()
writeModeOff()
}
public override fun onResume() {
super.onResume()
writeModeOn()
}
/******************************************************************************
* Enable Write and foreground dispatch to prevent intent-filter to launch the app again
****************************************************************************/
private fun writeModeOn() {
writeMode = true
nfcAdapter!!.enableForegroundDispatch(this, pendingIntent, writeTagFilters, null)
}
/******************************************************************************
* Disable Write and foreground dispatch to allow intent-filter to launch the app
****************************************************************************/
private fun writeModeOff() {
writeMode = false
nfcAdapter!!.disableForegroundDispatch(this)
}
<uses-permission android:name="android.permission.POST_NOTIFICATIONS"/>
<uses-permission android:name="android.permission.INTERNET"/>
<uses-permission android:name="android.permission.NFC"/>
<uses-feature android:name="android.hardware.nfc"
android:required="true"/>
<application
android:name=".BaseApplication"
android:allowBackup="true"
android:dataExtractionRules="#xml/data_extraction_rules"
android:fullBackupContent="#xml/backup_rules"
android:icon="#mipmap/ic_launcher"
android:label="#string/app_name"
android:roundIcon="#mipmap/ic_launcher_round"
android:supportsRtl="true"
android:theme="#style/Theme.UcyncBusiness"
tools:targetApi="31">
<activity
android:name=".ui.ActivateActivity"
android:exported="false">
<meta-data
android:name="android.app.lib_name"
android:value="" />
</activity>
<activity
android:name=".ui.HomeActivity"
android:exported="false">
<intent-filter>
<action android:name="android.nfc.action.NDEF_DISCOVERED" />
<category android:name="android.intent.category.DEFAULT" />
<data android:mimeType="text/plain" />
</intent-filter>
<meta-data
android:name="android.nfc.action.TECH_DISCOVERED"
android:resource="#xml/nfc_tech_filter" />
<meta-data
android:name="android.app.lib_name"
android:value="" />
</activity>
<activity
android:name=".ui.SplashActivity"
android:exported="true">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
<meta-data
android:name="android.app.lib_name"
android:value="" />
</activity>
<activity android:name=".MainActivity" />
</application>
I am making a code for making phone calls. Everything successful except that I am unable to get the system time when TelephonyManager.CALL_STATE_OFFHOOK state from the onCallStateChanged(int state, String incomingNumber).
Similarly, I want to get the system time when TelephonyManager.CALL_STATE_IDLE state is arrived. Once I get both the values in the Mainactivity I can get the difference and based its value I can start some other activity.
For example, if the time difference between TelephonyManager.CALL_STATE_IDLE state and TelephonyManager.CALL_STATE_IDLE state is less than 30 second, then I can assume that the call is not attended and I can start another call(or to another number). I am able to do all these inside the onCallStateChanged Method of PhoneStateListener class. But unable to pass this values to Mainactivity either by variables or Methods etc. This is the code for invoking call and it is working fine
Intent myIntentCall = new Intent(Intent.ACTION_CALL, Uri.parse("tel:0123456789"));
if (ActivityCompat.checkSelfPermission(this, Manifest.permission.CALL_PHONE)
!= PackageManager.PERMISSION_GRANTED) {
requestPermissions();
}
else
{
startActivity(myIntentCall);
}
private void requestPermissions () {
ActivityCompat.requestPermissions(this, new String[]{Manifest.permission.CALL_PHONE}, 1);
}
From the below piece of code, I expect the updated value of _seconds to the Mainactivity class by accessing PhoneReceiver._seconds statement. But always it remain 0. But I get the correct value for _seconds in the PhoneReceiver class. The code is given below
public class PhoneReceiver extends PhoneStateListener {
Context context;
static boolean _callStarted = false;
long _callStartTime;
long _callEndTime;
long _callDuration;
long _minutes;
static long _seconds;
public PhoneReceiver(Context context) {
this.context = context;
}
#Override
public void onCallStateChanged(int state, String incomingNumber) {
if ((state == TelephonyManager.CALL_STATE_OFFHOOK) && !_callStarted) {
_callStarted = !_callStarted;
_callStartTime = new Date().getTime();
Toast.makeText(context, "Stage 1: " + "Off Hook -> Boolean: "+_callStarted, Toast.LENGTH_LONG).show();
}
if ((state == TelephonyManager.CALL_STATE_IDLE) && _callStarted)
{
_callEndTime = new Date().getTime();
_callDuration = _callEndTime - _callStartTime;
_minutes = (_callDuration / 1000) / 60;
_seconds = (_callDuration / 1000) % 60;
Toast.makeText(context, "Stage 2: " + "IDLE State->Boolean: "+_callStarted, Toast.LENGTH_LONG).show();
}
}
}
Android Manifest.xml is given below
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.callerApppackage.callerapp">
<uses-permission android:name="android.permission.CALL_PHONE" />
<uses-permission android:name="android.permission.READ_PHONE_STATE" />
<application
android:allowBackup="true"
android:icon="#mipmap/ic_launcher"
android:label="#string/app_name"
android:roundIcon="#mipmap/ic_launcher_round"
android:supportsRtl="true"
android:theme="#style/AppTheme">
<activity android:name=".MainActivity">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<!-- put this here so that even if the app is not running,
your app can be woken up if there is a change in phone
state -->
<receiver android:name=".PhoneStateReceiver">
<intent-filter>
<action
android:name=
"android.intent.action.PHONE_STATE" />
</intent-filter>
</receiver>
</application>
PhonestateReciver Class is given below
public class PhoneStateReceiver extends BroadcastReceiver {
TelephonyManager manager;
PhoneReceiver myPhoneStateListener;
static boolean alreadyListening = false;
#Override
public void onReceive(Context context, Intent intent) {
myPhoneStateListener = new PhoneReceiver(context);
manager = ((TelephonyManager) context.getSystemService(Context.TELEPHONY_SERVICE));
//---do not add the listener more than once---
if (!alreadyListening) {
manager.listen(myPhoneStateListener,
PhoneStateListener.LISTEN_CALL_STATE);
alreadyListening = true;
}
}
}
I hope I made it clear Thanking you all in advance for earlier reply.
In my application, I want to put a log for the state when someone picks up the call. The getState() on the switch statement must return the correct state of the call, but it always returns zero. Here is my onRecieve() method:
public void onReceive(Context context, Intent intent) {
if(intent.getAction().equals(Intent.ACTION_NEW_OUTGOING_CALL)){
incomingFlag = false;
String phoneNumber = intent.getStringExtra(Intent.EXTRA_PHONE_NUMBER);
Log.i(TAG, "call OUT:"+phoneNumber);
TelephonyManager tm =
(TelephonyManager)context.getSystemService(Service.TELEPHONY_SERVICE);
Log.e("log state", String.valueOf(tm.getCallState()));
switch (tm.getCallState()) {
case TelephonyManager.CALL_STATE_RINGING:
incomingFlag = true;
incoming_number = intent.getStringExtra("incoming_number");
Log.i(TAG, "RINGING :"+ incoming_number);
break;
case TelephonyManager.CALL_STATE_OFFHOOK:
if(incomingFlag){
Log.i(TAG, "incoming ACCEPT :"+ incoming_number);
}
break;
case TelephonyManager.CALL_STATE_IDLE:
if(incomingFlag){
Log.i(TAG, "incoming IDLE");
}
break;
default:
Log.e("ds","Error");
}
}
manifest file :
<activity android:name=".MainActivity">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<receiver android:name=".BroadCast" >
<intent-filter>
<action android:name="android.intent.action.PHONE_STATE" />
</intent-filter>
<intent-filter>
<action android:name="android.intent.action.NEW_OUTGOING_CALL"/>
</intent-filter>
</receiver>
Permissions :
<uses-permission android:name="android.permission.CALL_PHONE"/>
<uses-permission android:name = "android.permission.READ_PHONE_STATE"/>
<uses-permission android:name="android.permission.PROCESS_OUTGOING_CALLS"/>
The onCreate() method mentioned above is in a seperate class I created called BroadCast, and I call it by creating a new instance of it.
Please let me know if more details are required.
Try to use a BroadcastReceiver to handle the incoming call.
In your onResume, set up the receiver
IntentFilter filter2 = new IntentFilter(TelephonyManager.ACTION_PHONE_STATE_CHANGED);
filter2.setPriority(99999);
this.registerReceiver(incomingCallReceiver, filter2);
and handle it such as
BroadcastReceiver incomingCallReceiver = new BroadcastReceiver() {
#Override
public void onReceive(Context context, Intent intent) {
final Bundle bundle = intent.getExtras();
if (bundle == null) return;
// Incoming call
// Get the state
String state = bundle.getString(TelephonyManager.EXTRA_STATE);
// Process the states
if ((state != null) && (state.equalsIgnoreCase(TelephonyManager.EXTRA_STATE_RINGING))) {
// Ringing State
}
if ((state != null) && (state.equalsIgnoreCase(TelephonyManager.EXTRA_STATE_IDLE))) {
// Idle State
}
if ((state != null) && (state.equalsIgnoreCase(TelephonyManager.EXTRA_STATE_OFFHOOK))) {
// Offhook State
}
}
};
Receiver works on all android versions from 4.2 upto 8.0. Even if app is removed from Recent Apps But if removed from Recent Apps in Android Oreo, it then never triggers receiver again.
my manifest.xml :
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />
<uses-permission android:name="android.permission.READ_PHONE_STATE" />
<uses-permission android:name="android.permission.VIBRATE" />
<uses-permission android:name="android.permission.READ_CONTACTS" />
<uses-permission android:name="android.permission.SEND_SMS" />
<uses-permission android:name="android.permission.READ_SMS" />
<uses-permission android:name="android.permission.WRITE_SMS" />
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.GET_ACCOUNTS" />
<application
android:allowBackup="true"
android:icon="#mipmap/ic_launcher"
android:label="#string/app_name"
android:roundIcon="#mipmap/ic_launcher_round"
android:supportsRtl="true"
android:theme="#style/AppTheme">
<activity
android:name=".MainActivity"
android:screenOrientation="portrait">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<service
android:name=".WatchMan"
android:enabled="true"
android:exported="true" />
<receiver
android:name=".Receiver"
android:enabled="true"
android:exported="true">
<intent-filter>
<action android:name="android.intent.action.PHONE_STATE" />
</intent-filter>
</receiver>
</application>
My receiver.java :
public class Receiver extends BroadcastReceiver
{
public String PhoneNumber = "UNKNOWN";
#Override
public void onReceive(Context context, Intent intent)
{
Log.d("RECEIVER :","CAPTURED THE EVENT.....");
try
{
PhoneNumber = intent.getStringExtra(Intent.EXTRA_PHONE_NUMBER);
PhoneNumber = intent.getStringExtra(TelephonyManager.EXTRA_INCOMING_NUMBER);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O)
{
context.startForegroundService(new Intent(context, WatchMan.class));
}
else
{
context.startService(new Intent(context, WatchMan.class));
}
}
catch (Exception e)
{
e.printStackTrace();
Log.e("RECEIVER EXCEPTION : ", "Exception is : ", e);
}
}
I want to know if i am doing any mistake in code? Android Developers Documentation asking to register receiver runtime using context. Then i searched for registering it in runtime on stackoverflow but looks no proper thread accepted as answer. How can make receiver to to be ready again, even if removed from recents of Android Oreo?
Thanking you in advance.
I have deleted unrelated posts. I am posting final answer as it may help others. #WIZARD help was thankful.
PHONE_STATE is implicit and will not be triggered on android Oreo or higher. So just place permissions in manifest like :
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />
<uses-permission android:name="android.permission.PROCESS_OUTGOING_CALLS" />
<uses-permission android:name="android.permission.READ_PHONE_STATE" />
<uses-permission android:name="android.permission.VIBRATE" />
<uses-permission android:name="android.permission.READ_CONTACTS" />
<uses-permission android:name="android.permission.SEND_SMS" />
<uses-permission android:name="android.permission.READ_SMS" />
<uses-permission android:name="android.permission.WRITE_SMS" />
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.GET_ACCOUNTS" />
<application
android:allowBackup="true"
android:icon="#mipmap/ic_launcher"
android:label="#string/app_name"
android:roundIcon="#mipmap/ic_launcher_round"
android:supportsRtl="true"
android:theme="#style/AppTheme">
<activity
android:name=".MainActivity"
android:excludeFromRecents="true">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<service
android:name=".WatchMan"
android:enabled="true"
android:exported="true">
</service>
<service
android:name=".CatchNumbers"
android:enabled="true"
android:exported="true">
</service>
<receiver
android:name=".MyReceiver"
android:enabled="true"
android:exported="true">
<intent-filter>
<action android:name="android.intent.action.BOOT_COMPLETED" />
</intent-filter>
</receiver>
</application>
Register implicit receivers from foreground service :
public class WatchMan extends Service
{
NotificationManager mNotifyManager;
NotificationCompat.Builder mBuilder;
NotificationChannel notificationChannel;
String NOTIFICATION_CHANNEL_ID = "17";
private boolean running;
private BroadcastReceiver mCallBroadcastReceiver = new BroadcastReceiver()
{
#Override
public void onReceive(Context context, Intent intent)
{
String PhoneNumber = "UNKNOWN";
Log.d("RECEIVER : ","HERE HERE");
try
{
String state = intent.getStringExtra(TelephonyManager.EXTRA_STATE);
if(state == null)
{
PhoneNumber = "UNKNOWN";
}
else if (state.equals(TelephonyManager.EXTRA_STATE_RINGING))
{
PhoneNumber = intent.getStringExtra(TelephonyManager.EXTRA_INCOMING_NUMBER);
Log.d("INCOMING ","Incoming number : "+PhoneNumber);
}
if(intent.getAction().equals("android.intent.action.NEW_OUTGOING_CALL"))
{
PhoneNumber = intent.getStringExtra(Intent.EXTRA_PHONE_NUMBER);
Log.d("OUTGOING ","Outgoing number : "+PhoneNumber);
}
if(!PhoneNumber.contentEquals("UNKNOWN"))
{
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O)
{
context.startForegroundService(new Intent(context, CatchNumbers.class));
}
else
{
context.startService(new Intent(context, CatchNumbers.class));
}
}
}
catch (Exception e)
{
e.printStackTrace();
Log.e("RECEIVER EXCEPTION : ", "Exception is : ", e);
}
}
};
public WatchMan() { }
#Override
public void onCreate()
{
super.onCreate();
mBuilder = new NotificationCompat.Builder(this, null);
IntentFilter filterstate = new IntentFilter();
filterstate.addAction("android.intent.action.NEW_OUTGOING_CALL");
filterstate.addAction("android.intent.action.PHONE_STATE");
this.registerReceiver(mCallBroadcastReceiver, filterstate);
Log.d("RECEIVER : ", "\nCreated....");
mNotifyManager = (NotificationManager) getApplicationContext().getSystemService(NOTIFICATION_SERVICE);
mBuilder = new NotificationCompat.Builder(this, null);
mBuilder.setContentTitle("Insta Promo")
.setContentText("Insta Promo Is Up..")
.setTicker("Insta Promo Is Up..")
.setSmallIcon(R.drawable.ic_launcher_background)
.setPriority(Notification.PRIORITY_HIGH)
.setDefaults(Notification.DEFAULT_ALL)
.setVisibility(Notification.VISIBILITY_PUBLIC)
.setOngoing(true)
.setAutoCancel(false);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O)
{
notificationChannel = new NotificationChannel(NOTIFICATION_CHANNEL_ID, "My Notifications", NotificationManager.IMPORTANCE_HIGH);
// Configure the notification channel.
notificationChannel.setDescription("Channel description");
notificationChannel.enableLights(true);
notificationChannel.setLightColor(Color.RED);
notificationChannel.setVibrationPattern(new long[]{0, 1000, 500, 1000});
notificationChannel.enableVibration(true);
notificationChannel.setLockscreenVisibility(Notification.VISIBILITY_PUBLIC);
mNotifyManager.createNotificationChannel(notificationChannel);
}
running = true;
mBuilder.setChannelId(NOTIFICATION_CHANNEL_ID);
startForeground(17, mBuilder.build());
}
#Override
public int onStartCommand(Intent intent, int flags, int startId)
{
Log.d("RECEIVER : ", "\nOnStartCommand....");
new Thread(new Runnable()
{
public void run()
{
while(running)
{
try
{
Log.d("RECEIVER : ", "\nALIVE..");
Thread.sleep(10000);
}
catch (InterruptedException e)
{
Log.d("RECEIVER : ", "\nThread : InterruptedException in Receiver...");
Log.e("RECEIVER : ", "\nException is : ", e);
}
catch (Exception e)
{
Log.d("RECEIVER : ", "\nThread : Exception Error in Receiver...");
Log.e("RECEIVER : ", "\nException is : ", e);
}
}
}
}).start();
return START_STICKY;
}
#Override
public void onDestroy()
{
this.unregisterReceiver(mCallBroadcastReceiver);
running = true;
Log.d("RECEIVER : ", "\nDestroyed....");
Log.d("RECEIVER : ", "\nWill be created again....");
}
#Override
public IBinder onBind(Intent intent)
{
// TODO: Return the communication channel to the service.
throw new UnsupportedOperationException("Not yet implemented");
}
#Override
public void onTaskRemoved(Intent rootIntent)
{
super.onTaskRemoved(rootIntent);
Log.d("SERVICE : ", "\nTask Removed....");
}
}
There are some intent actions like NEW_OUTGOING_CALL AND BOOT_COMPLETED which are excluded and can be implemented in receiver and placed in manifest like :
public class MyReceiver extends BroadcastReceiver
{
#Override
public void onReceive(Context context, Intent intent)
{
Log.d("INSTA_BOOT : ", "\nBOOT_COMPLETE_EVENT_OF_INSTA....");
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O)
{
context.startForegroundService(new Intent(context, WatchMan.class));
}
else
{
context.startService(new Intent(context, WatchMan.class));
}
}
}
As i wanted to re-register or say want to restart foreground service on REBOOT OR BOOT-COMPLETE
CatchNumbers.java is a simple service which performs operation when receiver triggers perticular actions.
It works good on every restart and as android:excludeFromRecents="true" is not needed anymore as even if user removes it from recents on Oreo it will restart the service as it is STICKY. Hope it helps someone like me..!!
Based on the documentation for restrictions on implicit broadcast in Android 8, you cannot use implicit receivers in your manifest (although there are some exceptions, but phone state receiver is not among those exceptions)
You have to use foreground service and register your receiver in your foreground service instead of manifest
remove phone state receiver from manifest
register receiver in onCreate of Service:
#Override
public void onCreate() {
super.onCreate();
phoneStateReceiver = new PhoneStateReceiver();
registerReceiver(phoneStateReceiver, new IntentFilter(TelephonyManager.ACTION_PHONE_STATE_CHANGED));
}
unregister in onDestroy:
#Override
public void onDestroy() {
unregisterReceiver(phoneStateReceiver);
super.onDestroy();
}
add a static method to your service to start service:
// start service even if your app is in stopped condition in android 8+
static void requestStart(#NonNull final Context context, #NonNull final String action){
final Context appContext = context.getApplicationContext();
Intent intent = new Intent(appContext, AppService.class);
intent.setAction(action);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
// this is required to start the service if there is
// no foreground process in your app and your app is
// stopped in android 8 or above
appContext.startForegroundService(intent);
} else {
appContext.startService(intent);
}
}
start foreground in your onStartCommand
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
if(ACTION_START.equals(intent.getAction()))
startForeground(ID, notification);
else if(ACTION_STOP.equals(intent.getAction()))
stopForeground(true);
return START_STICKY;
}
this thing is behaving very strange with us. Some devices hit onmsgrcv, while others dont when the app is closed. How come apps like Whatsapp receives notification when they are closed? Why dont I receive when my app is closed? Need help...
alert.php
$divisions = $_GET['divisions'];
$tokens = array();
$tokens[0] = "e3-nlNImIR8:APA91bGQ3WJW_jWfelz5mEp6L6--wNgdZtb93Bx7kZBSsXUaGYOvdg0_RaP7KlnlfGBD4Xqs3Kyr-IKc0s3072DPGCvToeFeO0w9EHazGOqZt30KbNE7zQr4gbklJ9nZlypyU8IyYzIl";
$tokens[1] = "fWFN3lpvIjI:APA91bF1Kkh-EBEEi8-qkrBgtwxzFAK4WfupWvgjA1PlWjquKTg8yUzMALO9UeTBJHw8UMbE_SLM2cObpf_PolQNkg4AW10Dsg7rtwvI41tIL83Kpm8BZ8cs4GEGXOYrbF0KaB_GG3jo";
$tokens[2] = "eimGs3j1bsA:APA91bFhJHRtxTKldSsrIVr8d12fVLId1DYkUIKgiczTrXGgKLQnoud9ZMIvi1wKHHQWkGcV2ptmLqLfHywgIwWzRxpfaJuICNvgqF2OUnfKist3_t-2XuASukuc4_6Ua9sER29c-oi9";
$data = array(
"divisions" => $divisions
);
$fields = array(
'to' => "/topics/ALERT",
'data' => $data
);
$headers = array(
'Authorization:key = AAAAjCAUSaQ:APA91bGa0FsAjY-5tjEBIiavo960rU39UmendbRC-akMdKxJIdSsqwwlNl4YMl1iAIYd2evyp_5kWe6l_RmpzLGXHiY91NY8LRKa75XNruD9Jvnyu8xNA2IIinLlkJLi8TL5Ud4M9hjY',
'Content-Type: application/json'
);
$ch = curl_init();
$url = "https://fcm.googleapis.com/fcm/send";
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_POST, true);
curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch,CURLOPT_SSL_VERIFYHOST,0);
curl_setopt($ch,CURLOPT_SSL_VERIFYPEER,false);
curl_setopt($ch, CURLOPT_POSTFIELDS,json_encode($fields));
$result = curl_exec($ch);
echo $result;
curl_close($ch);
?>
AndroidManifest.xml
<?xml version="1.0" encoding="utf-8"?>
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />
...
<!-- Needed only if your app targets Android 5.0 (API level 21) or higher. -->
<uses-feature android:name="android.hardware.location.gps" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
<uses-permission android:name="android.permission.CAMERA"/>
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>
<uses-permission android:name="android.permission.WAKE_LOCK" />
<application
android:allowBackup="true"
android:icon="#drawable/ic_launcher"
android:hardwareAccelerated="false"
android:largeHeap="true"
android:label="#string/app_name"
android:roundIcon="#drawable/ic_launcher"
android:supportsRtl="true"
android:theme="#style/AppTheme"
android:name="android.support.multidex.MultiDexApplication"
>
<meta-data
android:name="com.google.firebase.messaging.default_notification_icon"
android:resource="#drawable/ic_launcher" />
android:name="com.google.firebase.messaging.default_notification_color"
android:resource="#color/colorAccent" />
<activity
android:name="com.kayhanswarup.avtro.prokriti.ui.HomeActivity"
android:configChanges="locale|orientation"
android:label="#string/app_name"
android:theme="#style/AppTheme.NoActionBar">
</activity>
<!-- <service android:name=".services.MyService" android:process=":my_service" /> -->
<service android:name="com.kayhanswarup.avtro.prokriti.services.CloudMessagingService">
<intent-filter>
<action android:name="com.google.firebase.MESSAGING_EVENT" />
</intent-filter>
</service>
<service android:name="com.kayhanswarup.avtro.prokriti.services.InstanceTokenService">
<intent-filter>
<action android:name="com.google.firebase.INSTANCE_ID_EVENT" />
</intent-filter>
</service>
<provider android:authorities="com.facebook.app.FacebookContentProvider1697853730520523"
android:name="com.facebook.FacebookContentProvider"
android:exported="true"/>
<meta-data android:name="com.facebook.sdk.ApplicationId"
android:value="#string/facebook_app_id"/>
<activity android:name="com.kayhanswarup.avtro.prokriti.ui.MainActivity">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<activity android:name="com.facebook.FacebookActivity"
android:configChanges="keyboard|keyboardHidden|screenLayout|screenSize|orientation"
android:label="#string/app_name" />
<activity
android:name="com.facebook.CustomTabActivity"
android:exported="true">
<intent-filter>
<action android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.DEFAULT" />
<category android:name="android.intent.category.BROWSABLE" />
<data android:scheme="#string/fb_login_protocol_scheme" />
</intent-filter>
</activity>
</application>
CloudMessagingService.java
public class CloudMessagingService extends FirebaseMessagingService {
#Override
public void onMessageReceived(RemoteMessage remoteMessage) {
super.onMessageReceived(remoteMessage);
if (remoteMessage.getData().size() > 0) {
ML.d("Message data exists. Should go background: " + remoteMessage.getData());
goBackend(remoteMessage.getData().get("divisions"));
}
else if (remoteMessage.getNotification() != null) {
ML.d("Message Notification Body: " + remoteMessage.getNotification().getBody());
sendNotification(remoteMessage.getNotification().getBody());
}
}
public int currentDivisionIndex = -1;
public String currentDivision="";
private void goBackend(final String messageBody){
ML.setTagServer(true);
ML.i("Reached with data: "+messageBody);
final Intent intent1 = new Intent(this,HomeActivity.class);
final String[] divisions = ApiEndPoints.DIVISIONS;
try {
provider = LocationManager.NETWORK_PROVIDER;
locationManager=(LocationManager)getBaseContext().getSystemService(Context.LOCATION_SERVICE);
final Location location = locationManager.getLastKnownLocation(LocationManager.NETWORK_PROVIDER);
if(location!=null){
ML.d("location(lng,lat) value in background app: "+location.getLongitude()+","+location.getLatitude());
ApiClient.getInstance(getBaseContext())
.getWeather(location.getLatitude()+"", location.getLongitude()+"", new OnResponse<Weather, ANError>() {
#Override
public void onResponse(Weather response) {
try{
currentDivision= response.getQuery().getResults().getChannel().getLocation()
.getRegion();
}catch (Exception e){
ML.e("Exception during api client weather: "+e.getMessage());
return;
}
ML.d("Current DIVISION: "+currentDivision);
if(currentDivision!=null&¤tDivision.length()>=3){
ML.d("current Division is: "+currentDivision);
for(int i=0;i<divisions.length;i++){
ML.i("No#"+i+" division: "+divisions[i]);
if((currentDivision.toLowerCase().contains(divisions[i].toLowerCase()))||divisions[i].toLowerCase().contains(currentDivision.toLowerCase())){
ML.d("We got a match: "+i);
currentDivisionIndex = i;
}else{
ML.d("Current division: "+currentDivision.toLowerCase());
ML.d("INDEX DIVISION: "+divisions[i].toLowerCase());
}
}
ML.d("Current: "+currentDivisionIndex);
if(currentDivisionIndex<0||(currentDivisionIndex>=0&&messageBody.substring(currentDivisionIndex,currentDivisionIndex+1).equals("0"))){
ML.d("Returning from background" +
"DONE");
ML.d("Reached background but location mismatched");
if(currentDivisionIndex>=0){
ML.d("What is this: "+messageBody.substring(currentDivisionIndex,currentDivisionIndex+1));
}
return;
}else{
ML.d("Atleast found sth...");
}
ML.d("VALUE ACCORDING TO : "+messageBody.substring(currentDivisionIndex,currentDivisionIndex+1));
int val=0;
try {
val= Integer.parseInt(messageBody.substring(currentDivisionIndex,currentDivisionIndex+1));
} catch (Exception e) {
ML.e("Integer parsing error: "+e.getMessage());
}
if(currentDivisionIndex>=0&&val!=0){
String lang = "en";
try {
lang = isLangBangla()?"bn":"en";
} catch (Exception e) {
ML.e("GOT EXCEPTION");
lang="bn";
}
FirebaseDatabase.getInstance().getReference("versions")
.child("001")
.child("locales")
.child(lang)
.child("alert")
.addListenerForSingleValueEvent(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
ML.d("Will show an alert... IF LUCKY...");
final Alert alert = dataSnapshot.getValue(Alert.class);
DatabaseReference ref = FirebaseDatabase.getInstance().getReference("versions").child("001")
.child("LOG");
String key = ref.push().getKey();
ref.child(key).setValue(ML.getLog() + "", new DatabaseReference.CompletionListener() {
#Override
public void onComplete(DatabaseError databaseError, DatabaseReference databaseReference) {
if(databaseError==null)
Log.d("Prokriti","sent");
ML.setTagServer(false);
Notify.getInstance().setHasNotification(true);
String title = getString(R.string.alert_title);
String body = getString(R.string.alert_body);
try {
if(alert!=null){
ML.d("Alert: "+alert.toString());
title = alert.getTitle();
body = alert.getBody();
}else ML.e("Alert is null");
} catch (Exception e) {
ML.e("no alert found"+e.getMessage());
}
try {
Notify.getInstance().setTitle(title);
Notify.getInstance().setDescription(body);
} catch (Exception e) {
ML.e("Notify error: "+e.getMessage());
Notify.getInstance().setTitle("Title");
Notify.getInstance().setDescription("Danger");
}
PendingIntent pendingIntent = PendingIntent.getActivity(CloudMessagingService.this, 0 /* Request code */, intent1,
PendingIntent.FLAG_UPDATE_CURRENT);
ML.d("Pack res path: "+getPackageResourcePath());
ML.d("Pack res: "+getPackageName());
Uri defaultSoundUri= Uri.parse("android.resource://"+getPackageName()+"/"+ R.raw.alert);
NotificationCompat.Builder notificationBuilder = new NotificationCompat.Builder(CloudMessagingService.this)
.setSmallIcon(R.drawable.ic_cloud)
.setContentTitle(title)
.setContentText(body)
.setAutoCancel(true)
.setSound(defaultSoundUri)
.setContentIntent(pendingIntent);
NotificationManager notificationManager =
(NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
notificationManager.notify(0 /* ID of notification */, notificationBuilder.build());
}
});
// intent.putExtra("locale","notify");
}
#Override
public void onCancelled(DatabaseError databaseError) {
DatabaseReference ref = FirebaseDatabase.getInstance().getReference("versions").child("001")
.child("LOG");
String key = ref.push().getKey();
ref.child(key).setValue(ML.getLog() + "", new DatabaseReference.CompletionListener() {
#Override
public void onComplete(DatabaseError databaseError, DatabaseReference databaseReference) {
if(databaseError==null)
Log.d("Prokriti","sent");
ML.setTagServer(false);
}
});
}
});
}
}
}
#Override
public void onError(ANError error) {
ML.e("Error: "+error.getMessage());
}
});
}
} catch (Exception e) {
ML.e("Still shows fucking ERROR: "+e.getMessage());
}
}
public static boolean isLangBangla(){
return LocaleManager.getInstance().getLocale().getDisplayLanguage().toLowerCase().contains("bengali");
}
LocationManager locationManager=null;
String provider;
private void sendNotification(String messageBody) {
Intent intent = new Intent(this, MainActivity.class);
intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
// provider = LocationManager.NETWORK_PROVIDER;
// locationManager=(LocationManager)getBaseContext().getSystemService(Context.LOCATION_SERVICE);
Location location = locationManager.getLastKnownLocation(provider);
if(location!=null){
ML.d("location(lng,lat): "+location.getLongitude()+","+location.getLatitude());
}else ML.d("location is null...");
intent.putExtra("locale","notify");
Notify.getInstance().setHasNotification(true);
Notify.getInstance().setTitle("Title");
Notify.getInstance().setDescription("ED");
PendingIntent pendingIntent = PendingIntent.getActivity(this, 0 /* Request code */, intent,
PendingIntent.FLAG_UPDATE_CURRENT);
ML.d("Pack res path: "+getPackageResourcePath());
ML.d("Pack res: "+getPackageName());
Uri defaultSoundUri= Uri.parse("android.resource://"+getPackageName()+"/"+ R.raw.alert);
NotificationCompat.Builder notificationBuilder = new NotificationCompat.Builder(this)
.setSmallIcon(R.drawable.ic_cloud)
.setContentTitle(getString(R.string.alert_title))
.setContentText(getString(R.string.alert_body))
.setAutoCancel(false)
.setSound(defaultSoundUri)
.setContentIntent(pendingIntent);
NotificationManager notificationManager =
(NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
notificationManager.notify(0 /* ID of notification */, notificationBuilder.build());
}
LocationListener locationListener = new LocationListener() {
#Override
public void onLocationChanged(Location location) {
}
#Override
public void onStatusChanged(String provider, int status, Bundle extras) {
}
#Override
public void onProviderEnabled(String provider) {
}
#Override
public void onProviderDisabled(String provider) {
}
};
}