I want update ListView from BroadcastReceiver in onReceiver event.
How to initialized ListView in this class then update to ListView:
public class CallBroadcast extends BroadcastReceiver {
private static int pState = TelephonyManager.CALL_STATE_IDLE;
#Override
public void onReceive(final Context context, final Intent intent) {
TelephonyManager telManager = (TelephonyManager) context
.getSystemService(Context.TELEPHONY_SERVICE);
telManager.listen(new PhoneStateListener() {
#Override
public void onCallStateChanged(int state, String incomingNumber) {
callDAO = new CallDAO(context);
if (configPreferenceManager.getAutoRecord()) {
if (state != pState) {
if (state == TelephonyManager.CALL_STATE_OFFHOOK && callInfoPreferenceManager.getCallState()) {
uri = Uri.withAppendedPath(
ContactsContract.PhoneLookup.CONTENT_FILTER_URI,
Uri.encode(callInfoPreferenceManager.getPhoneNumber()));
projection = new String[]{ContactsContract.CommonDataKinds.Phone.DISPLAY_NAME
, ContactsContract.Contacts.PHOTO_ID
};
// START SERVICES TO RECORD CALL. AFTER IT, I WANT UPDATE MY LIST
sIntent = new Intent(context.getApplicationContext(),
CallRecordService.class);
context.startService(sIntent);
} else if (state == TelephonyManager.CALL_STATE_RINGING && callInfoPreferenceManager.getCallState()) {
callInfoPreferenceManager.setPhoneNumber(incomingNumber);
callInfoPreferenceManager.setSending(String.valueOf(false));
} else if (state == TelephonyManager.CALL_STATE_IDLE && callInfoPreferenceManager.getCallState() == CALLING) {
callDAO.insert(callInfoPreferenceManager.getName(),
callInfoPreferenceManager.getPhoneNumber(),
callInfoPreferenceManager.getStartDate()
+ configPreferenceManager.getPathFormat());
callDAO.close();
// Record call start service
sIntent = new Intent(context.getApplicationContext(),
CallRecordService.class);
context.stopService(sIntent);
callInfoPreferenceManager.setCallState(IDLE);
}
pState = state;
}
}
}
}, PhoneStateListener.LISTEN_CALL_STATE);
}//onReceive
}
In the code I posted is BroadcastReceiver class.
And I can't using getActivity() class or findViewById(a, b) when extends BroadcastReceiver.
How to fix this problem?
Start the activity that will populate the listview using Intents.
Intent intent = new Intent(context,Myactivity.class)
startactivity(intent);
To avoid multiple instances of same 'Myactivity', use appropriate flags in the Manifest file.
If you want to transfer data between your broadcastReceiver and 'Myactivity', either use intent.putExtra() or store the data into sharedPreferences
Related
I'm developing an app that will only be used in house for testing purpose. I have searched a lot and tried different suggestions as suggested in different post but none seems to be working for me.
I'm open to any suggestions like Reflections, Accessibility Service, root or any other hack. Please help.
Regards
TRY THIS
Set all required permission in manifest.xml file.
Call this class in Service
public class PhoneListener extends PhoneStateListener {
private static PhoneListener instance = null;
/**
* Must be called once on app startup
*
* #param context - application context
* #return
*/
public static PhoneListener getInstance(Context context) {
if (instance == null) {
instance = new PhoneListener(context);
}
return instance;
}
public static boolean hasInstance() {
return null != instance;
}
private final Context context;
private CallLog phoneCall;
private PhoneListener(Context context) {
this.context = context;
}
AtomicBoolean isRecording = new AtomicBoolean();
AtomicBoolean isWhitelisted = new AtomicBoolean();
/**
* Set the outgoing phone number
* <p/>
* Called by {#link MyCallReceiver} since that is where the phone number is available in a outgoing call
*
* #param phoneNumber
*/
public void setOutgoing(String phoneNumber) {
if (null == phoneCall)
phoneCall = new CallLog();
phoneCall.setPhoneNumber(phoneNumber);
phoneCall.setOutgoing();
// called here so as not to miss recording part of the conversation in TelephonyManager.CALL_STATE_OFFHOOK
isWhitelisted.set(Database.isWhitelisted(context, phoneCall.getPhoneNumber()));
}
#Override
public void onCallStateChanged(int state, String incomingNumber) {
super.onCallStateChanged(state, incomingNumber);
switch (state) {
case TelephonyManager.CALL_STATE_IDLE: // Idle... no call
if (isRecording.get()) {
RecordCallService.stopRecording(context);
phoneCall = null;
isRecording.set(false);
}
break;
case TelephonyManager.CALL_STATE_OFFHOOK: // Call answered
if (isWhitelisted.get()) {
isWhitelisted.set(false);
return;
}
if (!isRecording.get()) {
isRecording.set(true);
// start: Probably not ever usefull
if (null == phoneCall)
phoneCall = new CallLog();
if (!incomingNumber.isEmpty()) {
phoneCall.setPhoneNumber(incomingNumber);
}
// end: Probably not ever usefull
RecordCallService.sartRecording(context, phoneCall);
}
break;
case TelephonyManager.CALL_STATE_RINGING: // Phone ringing
// DO NOT try RECORDING here! Leads to VERY poor quality recordings
// I think something is not fully settled with the Incoming phone call when we get CALL_STATE_RINGING
// a "SystemClock.sleep(1000);" in the code will allow the incoming call to stabilize and produce a good recording...(as proof of above)
if (null == phoneCall)
phoneCall = new CallLog();
if (!incomingNumber.isEmpty()) {
phoneCall.setPhoneNumber(incomingNumber);
// called here so as not to miss recording part of the conversation in TelephonyManager.CALL_STATE_OFFHOOK
isWhitelisted.set(Database.isWhitelisted(context, phoneCall.getPhoneNumber()));
}
break;
}
}
}
And use Broadcast Receiver
public class MyCallReceiver extends BroadcastReceiver {
public MyCallReceiver() {
}
static TelephonyManager manager;
#Override
public void onReceive(Context context, Intent intent) {
Log.i("JLCreativeCallRecorder", "MyCallReceiver.onReceive ");
if (!AppPreferences.getInstance(context).isRecordingEnabled()) {
removeListener();
return;
}
if (Intent.ACTION_NEW_OUTGOING_CALL.equals(intent.getAction())) {
if (!AppPreferences.getInstance(context).isRecordingOutgoingEnabled()) {
removeListener();
return;
}
PhoneListener.getInstance(context).setOutgoing(intent.getStringExtra(Intent.EXTRA_PHONE_NUMBER));
} else {
if (!AppPreferences.getInstance(context).isRecordingIncomingEnabled()) {
removeListener();
return;
}
}
// Start Listening to the call....
if (null == manager) {
manager = (TelephonyManager) context.getSystemService(Context.TELEPHONY_SERVICE);
}
if (null != manager)
manager.listen(PhoneListener.getInstance(context), PhoneStateListener.LISTEN_CALL_STATE);
}
private void removeListener() {
if (null != manager) {
if (PhoneListener.hasInstance())
manager.listen(PhoneListener.getInstance(null), PhoneStateListener.LISTEN_NONE);
}
}
}
I hope you get some help from this code.
Thanks
You can use accessibility events to detect the call duration and from that you can detect if the outgoing call is answered or not..
I have answered it in detail in Here` you can check that.
You need this permission in manifest
<uses-permission android:name="android.permission.READ_PHONE_STATE"/>
TelephonyManager has a listener to get phone state. implement this tho know if the phone is ringing or in a call.
TelephonyManager telephonyManager = (TelephonyManager) getSystemService(Context.TELEPHONY_SERVICE);
PhoneStateListener callStateListener = new PhoneStateListener() {
public void onCallStateChanged(int state, String incomingNumber) {
// TODO React to a incoming call.
try {
if (state == TelephonyManager.CALL_STATE_RINGING) {
Toast.makeText(getApplicationContext(), "Phone Is Ringing" + incomingNumber, Toast.LENGTH_LONG).show();
number = incomingNumber;
//g.setPhoneNo(incomingNumber);
AndroidNetCommunicationClientActivity.mMsgSendRequest("CommandMsgCallIncoming" + number);
} else if (state == TelephonyManager.CALL_STATE_OFFHOOK) {
Toast.makeText(getApplicationContext(), "Phone is Currently in A call" + incomingNumber, Toast.LENGTH_LONG).show();
//number = mIntent.getStringExtra(Intent.EXTRA_PHONE_NUMBER);
number = incomingNumber;
} else if (state == TelephonyManager.DATA_DISCONNECTED) {
number = "";
CallID = "";
}
} catch (Exception e) {
// TODO Auto-generated catch block
//conn.MessageBox(MainActivity.this, e.getMessage());
e.printStackTrace();
}
super.onCallStateChanged(state, incomingNumber);
}
};
telephonyManager.listen(callStateListener, PhoneStateListener.LISTEN_CALL_STATE);
I am using the code below in my activity class:
public static Activity list_Addresses_Activity;
And in my onCreate I used from this :
list_Addresses_Activity = this;
But it throws an error stated below:
Do not place Android context classes in static fields; this is a memory leak (and also breaks Instant Run)
I need to use it from static because I will use from this in my Service class.
My CloseActivies.class :
public class CloseActivies {
Activity a;
Activity b;
Activity c;
protected void CLSActivities(Activity ListAddresses, Activity ListOrder, Activity SendReports) {
a = ListAddresses;
b = ListOrder;
c = SendReports;
if (ListAddressesActivity.FlagLiveAddress && a != null) {
Log.e("ADASFSDAGWEG", "X");
a.finish();
ListAddressesActivity.FlagLiveAddress = false;
}
if (ListOrderActivity.FlagLiveOrder && b != null) {
Log.e("ADASFSDAGWEG", "Y");
b.finish();
ListOrderActivity.FlagLiveOrder = false;
}
if (SendReportsActivity.FlagSendReport && c != null) {
Log.e("ADASFSDAGWEG", "Z");
c.finish();
SendReportsActivity.FlagSendReport = false;
}
}
protected void CLSActivities() {
if (ListAddressesActivity.FlagLiveAddress && a != null) {
Log.e("ADASFSDAGWEG", "X");
a.finish();
ListAddressesActivity.FlagLiveAddress = false;
}
if (ListOrderActivity.FlagLiveOrder && b != null) {
Log.e("ADASFSDAGWEG", "Y");
b.finish();
ListOrderActivity.FlagLiveOrder = false;
}
if (SendReportsActivity.FlagSendReport && c != null) {
Log.e("ADASFSDAGWEG", "Z");
c.finish();
SendReportsActivity.FlagSendReport = false;
}
}
}
It will cause a memory leak as your service class is working on a separate thread and passing a static reference to your activity will keep the instance in memory even if the activity is dismissed and not garbage collected, a safer way to do this is passing a reference of your activity as a parameter to your service and storing it in a weakreference something like this
public class MyIntentService extends IntentService {
private final WeakReference<Context> mContextWeakReference;
public MyIntentService() {
super("MyIntentService");
}
public static void startActionFoo(Context context) {
mContextWeakReference = new WeakReference<>(context);
Intent intent = new Intent(context, MyIntentService.class);
context.startService(intent);
}
#Override
protected void onHandleIntent(Intent intent) {
Context context = mContextWeakReference.get();
if(context != null) {
//do your work as since context is not null means
//activity is still present and if activity is dismissed
//context will come null
}
}
}
If you need activity reference for one of its static variable you can pass it in intent extras, or you want to call a static function of activity, a broadcast receiver would be a better choice to do this.
If you are starting service from activity and use some data of activity in that service. You can pass them in intent.
Intent intent = new Intent(this,MyService.class);
intent.putExtra("data", "some_value");
startService(intent);
I am trying to make a call through my app by putting extra data and while but I am unable to receive that data during the call can some explain where I am wrong below is my code for making call and receiving call
String uri = "tel:"+my_name;
Intent callIntent = new Intent(Intent.ACTION_CALL, Uri.parse(uri));
callIntent.putExtra("data", "mynewdata");
callIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
_context.startActivity(callIntent);
And call receiver
public class PhoneStateReceiver extends BroadcastReceiver {
#Override
public void onReceive(Context context, Intent intent) {
final Bundle bundle = intent.getExtras();
if(bundle != null) {
showToast(intent.getExtras().getString("data"));
}
if (intent.getAction().equals("android.intent.action.PHONE_STATE")) {
String state = intent.getStringExtra(TelephonyManager.EXTRA_STATE);
Log.d(TAG,"PhoneStateReceiver**Call State=" + state);
if (state.equals(TelephonyManager.EXTRA_STATE_IDLE)) {
if(recieveCall){
}
Log.d(TAG,"PhoneStateReceiver**Idle");
} else if (state.equals(TelephonyManager.EXTRA_STATE_RINGING)) {
} else if (state.equals(TelephonyManager.EXTRA_STATE_OFFHOOK)) {
}
} else if (intent.getAction().equals("android.intent.action.NEW_OUTGOING_CALL")) {
// Outgoing call
String outgoingNumber = intent.getStringExtra(Intent.EXTRA_PHONE_NUMBER);
Log.d(TAG,"PhoneStateReceiver **Outgoing call " + outgoingNumber);
setResultData(null); // Kills the outgoing call
} else {
Log.d(TAG,"PhoneStateReceiver **unexpected intent.action=" + intent.getAction());
}
}
}
I'm receiving call perfectly and even broadcast is working perfectly but I am not getting data from intent "intent.getExtras().getBoolean("data")"
Here you need to create a java file (lets name it Constants.java):
public class Constants
{
public static boolean data;
public static String str = "";
}
Now see the changes i did in the project along with the comments.
String uri = "tel:"+my_name;
Intent callIntent = new Intent(Intent.ACTION_CALL, Uri.parse(uri));
Constants.data = true; /*see change, set data in Constants.data*/
Constants.str = "some data to pass..."; /*see change*/
callIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
_context.startActivity(callIntent);
Now in broadcast receiver see the changes done...
public class PhoneStateReceiver extends BroadcastReceiver {
#Override
public void onReceive(Context context, Intent intent) {
final Bundle bundle = intent.getExtras();
if(bundle != null && Constants.data) { /*changes done, get boolean from the Constants.data*/
showToast("hi i have recieve");
showToast(Constants.str); /*changes done*/
}
if (intent.getAction().equals("android.intent.action.PHONE_STATE")) {
String state = intent.getStringExtra(TelephonyManager.EXTRA_STATE);
Log.d(TAG,"PhoneStateReceiver**Call State=" + state);
if (state.equals(TelephonyManager.EXTRA_STATE_IDLE)) {
if(recieveCall){
}
Log.d(TAG,"PhoneStateReceiver**Idle");
} else if (state.equals(TelephonyManager.EXTRA_STATE_RINGING)) {
} else if (state.equals(TelephonyManager.EXTRA_STATE_OFFHOOK)) {
}
} else if (intent.getAction().equals("android.intent.action.NEW_OUTGOING_CALL")) {
// Outgoing call
String outgoingNumber = intent.getStringExtra(Intent.EXTRA_PHONE_NUMBER);
Log.d(TAG,"PhoneStateReceiver **Outgoing call " + outgoingNumber);
setResultData(null); // Kills the outgoing call
} else {
Log.d(TAG,"PhoneStateReceiver **unexpected intent.action=" + intent.getAction());
}
}
}
Hope this solved your problem of how to pass data
Although I was able to accomplish this task but in opinion the approach is not good,Since am creating instance of the Activity inside Broadcast Receiver. Is there any better way to accomplish it?
#Override
public void onReceive(Context context, Intent intent) {
String receivedIntent = intent.getAction();
MainActivity inst = MainActivity.instance();
setPref(context);
if(m_Accactive){
if (receivedIntent.equals(IntentManager.ACCELEROMETER_DATA_FILTER)) {
Log.d("Accel", "acc data");
recAcc = (AccelerometerClass) intent
.getSerializableExtra(Constants.ACC_DATA_KEY);
recData = recAcc;
if (inst != null) {
m_AccRate = inst.getM_AccFreq();
m_AccRetrieveTxtForm = FormatToString(recAcc);
inst.textViewSettings(inst.m_AcceleroReading, R.id.AccData,
m_AccRetrieveTxtForm);
}
}
}
I have this code to receive the caller number and do query in side case TelephonyManager.CALL_STATE_RINGING
I already get the caller number but when i want to do query in side the case the app will give me error i don't know why can any one help me please to solve the problem
this is my code
public class IncomingCallReciever extends BroadcastReceiver {
protected static final String TAG = "SWAJ";
private Context mContext;
private Intent mIntent;
#Override
public void onReceive(Context context, Intent intent) {
Log.d(TAG ," onCallStateChanged ");
mContext = context;
mIntent = intent;
TelephonyManager tm = (TelephonyManager) context.getSystemService(Context.TELEPHONY_SERVICE);
int events = PhoneStateListener.LISTEN_CALL_STATE;
tm.listen(phoneStateListener, events);
}
private final PhoneStateListener phoneStateListener = new PhoneStateListener() {
#Override
public void onCallStateChanged(int state, String incomingNumber) {
switch (state) {
case TelephonyManager.CALL_STATE_RINGING:
SilentMeDB databaseHelper = new SilentMeDB(mContext);
SQLiteDatabase db = databaseHelper.getReadableDatabase();
Cursor c = db.query("events",null,null, null, null, null, null);
c.moveToFirst();
while(!c.isAfterLast())
{
try
{
Log.d(TAG, "Message is " + c.getString(c.getColumnIndex("Message") ));
}
catch(Exception e)
{
Log.d("Exp", e.getMessage());
}
c.moveToNext();
} c.close();
break;
case TelephonyManager.CALL_STATE_OFFHOOK:
}
super.onCallStateChanged(state, incomingNumber);
}
};
}
I think you want to move query code up into the on receive method. I don't see any reason to be using a listener here. Besides, the moment your onReceive function ends that listener is going to go away and won't be listening anymore. In your onReceive you can check the Intent you get to see if the call state is ringing and then conditionally execute your code.