How to access a button from an Activity in a fragment? - android

So I'm in a bit of a dilemma here,
I have a button in my DashboardFragment which can only be referenced within that class, and I need that button to enable bluetooth, which is done in a separate activity. I'd prefer not to have the Bluetooth code in my fragment class since the bluetooth will be referenced from multiple fragments. The issue is when I try to reference the Activity button from the Fragment class, I get a null object reference.
Here is my DashboardFragment class:
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
}
public View onCreateView(#NonNull LayoutInflater inflater,
ViewGroup container, Bundle savedInstanceState) {
View root = inflater.inflate(R.layout.fragment_dashboard, container, false);
return root;
}
#Override
public void onViewCreated(View view, #Nullable Bundle savedInstanceState) {
connButton = (Button) getView().findViewById(R.id.button2);
connectionActivity = new ConnectionActivity();
connectionActivity.initView(connButton);
}
And my activity:
public class ConnectionActivity extends AppCompatActivity {
private static final String TAG = ConnectionActivity.class.getSimpleName();
BluetoothAdapter mBluetoothAdapter;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
}
public final BroadcastReceiver mBroadcastReceiver1 = new BroadcastReceiver() {
#Override
public void onReceive(Context context, Intent intent) {
final String action = intent.getAction();
if (action.equals(mBluetoothAdapter.ACTION_STATE_CHANGED)) {
final int state = intent.getIntExtra(BluetoothAdapter.EXTRA_STATE,
mBluetoothAdapter.ERROR);
//Use for when implementing states
switch (state) {
case BluetoothAdapter.STATE_OFF:
/*MainActivity.MyArrayAdapter adapter = (MainActivity.MyArrayAdapter) deviceSpinner.getAdapter();
if (adapter != null) {
adapter.clear();
adapter.notifyDataSetChanged();
}*/
Log.d(TAG, "STATE OFF");
break;
case BluetoothAdapter.STATE_TURNING_OFF:
Log.d(TAG,"STATE TURNING OFF");
break;
case BluetoothAdapter.STATE_ON:
//populateDeviceSpinner();
Log.d(TAG,"I'm ON!");
break;
case BluetoothAdapter.STATE_TURNING_ON:
Log.d(TAG,"Turning On...");
}
}
}
};
public void initView(Button connButton) {
mBluetoothAdapter = BluetoothAdapter.getDefaultAdapter();
connButton.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
enableDisableBT();
}
});
}
public void enableDisableBT() {
if (mBluetoothAdapter == null) {
Log.d(TAG, "Device does not have BLuetooth capabilites");
}
if (!mBluetoothAdapter.isEnabled()) {
Intent enableBTIntent = new Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE);
startActivity(enableBTIntent);
IntentFilter filter = new IntentFilter(BluetoothAdapter.ACTION_STATE_CHANGED);
registerReceiver(mBroadcastReceiver1, filter);
}
if (mBluetoothAdapter.isEnabled()) {
mBluetoothAdapter.disable();
IntentFilter filter = new IntentFilter(BluetoothAdapter.ACTION_STATE_CHANGED);
registerReceiver(mBroadcastReceiver1, filter);
}
}
}

Just add the reference in onViewCreated of DashboardFragment to
((ConnectionActivity) getActivity()).initView(connButton)

Related

Android Broadcast in one Fragment

I'm building my own VoIP app. Originally use Activity and BroadcastReceiver and it works fine, now I want to convert them to Fragment for my drawer.
Because BroadcastReceiver cannot use by Fragment, so I find some methods on stackoverflow but still not work...
All the code below is in the same file
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
V = inflater.inflate(R.layout.dial, container, false);
filter = new IntentFilter();
filter.addAction("android.SipDemo.INCOMING_CALL");
LocalBroadcastManager.getInstance(getActivity()).registerReceiver(callReceiver, filter);
getActivity().getWindow().addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
initializeManager();
// Inflate the layout for this fragment
return V;
}
private final BroadcastReceiver callReceiver = new BroadcastReceiver()
{
#Override
public void onReceive(Context context, Intent intent)
{
SipAudioCall incomingCall = null;
try {
SipAudioCall.Listener listener = new SipAudioCall.Listener() {
#Override
public void onRinging(SipAudioCall call, SipProfile caller) {
try {
call.answerCall(30);
} catch (Exception e) {
e.printStackTrace();
}
}
public void onCallEnded(SipAudioCall call) {
endMessage();
}
};
incomingCall = manager.takeAudioCall(intent, listener);
updateStatus("call incoming");
call = incomingCall;
call.answerCall(30);
call.startAudio();
call.setSpeakerMode(isSpeakerClicked);
} catch (Exception e) {
if (incomingCall != null) {
incomingCall.close();
}
}
}
};
In your Fragment :
Call registerBroadcast() in your onCreateView
private void registerBroadcast() {
LocalBroadcastManager.getInstance(getActivity()).registerReceiver(addCallReceiver,
new IntentFilter(getString(R.string.broadcast_add_call)));
}
BroadcastReceiver addCallReceiver= new BroadcastReceiver() {
#Override
public void onReceive(Context context, Intent intent) {
// perform actions
}
};
From where you want to trigger receiver :
LocalBroadcastManager.getInstance(mContext).sendBroadcast(new Intent(getString(R.string.broadcast_add_call)));

Bluetooth BroadcastReceiver retuns null

I'm learning to code for Android, my first project uses bluetooth so I thought I'd start there. Basically I'm trying to scan for the other available bluetooth device with the press of a button, and display its name in a textview.
I register a BroadcastReceiver (mReceiver) with an ACTION_FOUND filter. I know I'm starting discovery correctly since other devices can see me, but I can't get their names. Debugging through AS seems to show that my instance for mReceiver is null.
public class MainActivity extends AppCompatActivity {
private Scanner_Bluetooth mainBLScanner;
public BroadcastReceiver mReceiver;
public int DISCOVERY_REQUEST = 1;
public static final String[] runtimePermissions = {};
public static final int LOCATION_PERMISSION_IDENTIFIER = 1;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Button buttonConnect = (Button) findViewById(R.id.buttonBT);
final TextView tv_name =(TextView)findViewById(R.id.tv_name);
mainBLScanner = new Scanner_Bluetooth(this, 5000, -75);
IntentFilter filter = new IntentFilter(BluetoothDevice.ACTION_FOUND);
mReceiver = new BroadcastReceiver(getApplicationContext());
registerReceiver(mReceiver, filter);
View.OnClickListener listener = new View.OnClickListener() {
#Override
public void onClick(View view) {
mainBLScanner.Start();
tv_name.setText(mReceiver.getDeviceName());
}
};
buttonConnect.setOnClickListener(listener);
}
#Override
protected void onDestroy() {
unregisterReceiver(mReceiver);
super.onDestroy();
}
#Override
protected void onStop() {
unregisterReceiver(mReceiver);
super.onStop();
}
And this is how I implemented BroadcastReceiver
public class BroadcastReceiver extends android.content.BroadcastReceiver {
private String deviceName = "DUMMY";
private String deviceHardwareAddress;
Context activityContext;
private static final String TAG = "BroadcastReceiver";
public BroadcastReceiver(Context activityContext) {
this.activityContext = activityContext;
}
public String getDeviceName(){
return deviceName;
}
public String getAddress(){
return deviceHardwareAddress;
}
//this detects when bluetooth is on/off
#Override
public void onReceive(Context context, Intent intent) {
final String sAction = intent.getAction();
Log.d(TAG, "start onReceive: " + sAction);
if (sAction.equals(BluetoothAdapter.ACTION_STATE_CHANGED)) {
final int state = intent.getIntExtra(BluetoothAdapter.EXTRA_STATE, BluetoothAdapter.ERROR);
switch (state) {
case BluetoothAdapter.STATE_OFF:
Toast.makeText(context, "Bluetooth is off", Toast.LENGTH_LONG).show();
break;
case BluetoothAdapter.STATE_TURNING_OFF:
Toast.makeText(context, "Bluetooth is turning off", Toast.LENGTH_LONG).show();
break;
case BluetoothAdapter.STATE_ON:
Toast.makeText(context, "Bluetooth is on", Toast.LENGTH_LONG).show();
break;
case BluetoothAdapter.STATE_TURNING_ON:
Toast.makeText(context, "Bluetooth is turning on", Toast.LENGTH_LONG).show();
break;
default:
break;
}
if (BluetoothDevice.ACTION_FOUND.equals(sAction)) {
Log.d(TAG, " Action_Found");
BluetoothDevice device = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);
Toast.makeText(context,"Device Found!!",Toast.LENGTH_LONG).show();
this.deviceName = device.getName();
this.deviceHardwareAddress = device.getAddress(); // MAC address
}
}
}}
In my manifest I have both Bluetooth and BluetoothAdmin permissions. Also Coarse & Fine access.

My Broadcastreceiver seem to detect that a call ended, still doesn't do that it should do. Does anybody see the flaws in my code?

I would like to make two calls in a row in an android app. Upon clicking button the app calls the first number. I created the broadcastreceiver below, that detects when the first call ends. It should write out that "First call ended" and then call the second number. It does not seem working. Can anybody spot the mistake in my code?
public class MainActivity extends AppCompatActivity {
public void calling(String phone) {
Intent callIntent = new Intent(Intent.ACTION_CALL)
.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
callIntent.setData(Uri.parse("tel:" + phone));
callIntent.putExtra("com.android.phone.extra.slot", 1);
startActivity(callIntent);
Intent intent = new Intent(this, CallReciever.class);
PendingIntent pendingIntent = PendingIntent.getBroadcast(this.getApplicationContext(), 234324243 , intent, 0);
startActivity(callIntent);
}
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Button b = (Button) this.findViewById(R.id.CallButton);
b.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
calling("+36309577686");
}
});
}
public class CallReciever extends BroadcastReceiver {
private Context mContext;
private CustomPhoneStateListener mPhoneListener;
private String incoming_nr;
private int prev_state;
#Override
public void onReceive(Context context, Intent intent) {
mContext = context;
if (mPhoneListener == null) {
mPhoneListener = new CustomPhoneStateListener();
// TelephonyManager object
TelephonyManager telephony = (TelephonyManager) context.getSystemService(Context.TELEPHONY_SERVICE);
// Register our listener with TelephonyManager
telephony.listen(mPhoneListener, PhoneStateListener.LISTEN_CALL_STATE);
}
}
/* Custom PhoneStateListener */
class CustomPhoneStateListener extends PhoneStateListener {
#Override
public void onCallStateChanged(int state, String incomingNumber) {
if (!TextUtils.isEmpty(incomingNumber)) {
incoming_nr = incomingNumber;
}
switch (state) {
case TelephonyManager.CALL_STATE_RINGING:
prev_state = state;
break;
case TelephonyManager.CALL_STATE_OFFHOOK:
prev_state = state;
break;
case TelephonyManager.CALL_STATE_IDLE:
if ((prev_state == TelephonyManager.CALL_STATE_OFFHOOK)) {
// A call has now ended
//it writes out the call end, but does not call. why?
Toast.makeText(mContext, "Call End", Toast.LENGTH_SHORT).show();
calling("+36303853440");
prev_state = state;
}
else if ((prev_state == TelephonyManager.CALL_STATE_RINGING)) {
// Rejected or Missed call
Toast.makeText(mContext, "Rejected Call", Toast.LENGTH_SHORT).show();
prev_state = state;
}
break;
}
}
}
}
}
You are not registering the CallReciever anywhere. Try this
Button b = (Button) this.findViewById(R.id.CallButton);
b.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
calling("+36309577686");
registerReceiver(new CallReceiver());
}
});
Then unregister the receiver on broadcast is received

Broadcast Receiver from Service to Fragment not working properly

I've implemented a Broadcast Receiver to pass data each second from Service that is running a CountDownTimer with the time remaining to the Fragment.
The problem is that Fragment is not receiving data properly or better to say that is receiving it only when I press some search button, hide the keyboard or something else in the activity.
Here is my Service Class:
CountDownTimer timer = new CountDownTimer(number, 1000) {
#Override
public void onTick(long millisUntilFinished) {
timeLeft = millisUntilFinished;
normalTime = String.format(
"%02d:%02d:%02d",
TimeUnit.MILLISECONDS.toHours(timeLeft),
TimeUnit.MILLISECONDS.toMinutes(timeLeft) -
TimeUnit.HOURS.toMinutes(TimeUnit.MILLISECONDS.toHours(timeLeft)),
TimeUnit.MILLISECONDS.toSeconds(timeLeft) -
TimeUnit.MINUTES.toSeconds(TimeUnit.MILLISECONDS.toMinutes(timeLeft)));
Intent timerInfoIntent = new Intent(TIME_INFO);
timerInfoIntent.putExtra("VALUE", normalTime);
LocalBroadcastManager.getInstance(NotificationService.this).sendBroadcast(timerInfoIntent);
}
Here is my Fragment that is supposed to receive the data and update the item of a list view.
In onCreateView I register a receiver:
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
mTimerStatusReceiver = new TimerStatusReceiver();
LocalBroadcastManager.getInstance(getActivity()).registerReceiver(
mTimerStatusReceiver, new IntentFilter(NotificationService.TIME_INFO));
...
}
Do the same on onResume:
#Override
public void onResume() {
super.onResume();
LocalBroadcastManager.getInstance(getActivity()).registerReceiver(
mTimerStatusReceiver, new IntentFilter(NotificationService.TIME_INFO));
...
}
Unregister it onPause:
#Override
public void onPause() {
super.onPause();
LocalBroadcastManager.getInstance(getActivity()).unregisterReceiver(mTimerStatusReceiver);
}
TimerStatesReceiver class:
private class TimerStatusReceiver extends BroadcastReceiver {
#Override
public void onReceive(Context context, Intent intent) {
if (intent != null && intent.getAction().equals(NotificationService.TIME_INFO)) {
if (!IS_ALREADY_EXECUTED) {
modelTimer = new ModelTimer();
if (intent.hasExtra("VALUE")) {
modelTimer.setexpirationTime(intent.getStringExtra("VALUE"));
}
listOfTimers.add(modelTimer);
mAdapter = new ListViewAdapter(getActivity(), listOfTimers);
mListView.setAdapter(mAdapter);
IS_ALREADY_EXECUTED = true;
}else{
for (ModelTimer timer: listOfTimers){
View v = mListView.getChildAt(timerPosition.get(timer.getId()));
timer.setexpirationTime(intent.getStringExtra("VALUE"));
timer.setName(intent.getStringExtra("NAME_FOOD"));
if (v == null) return;
TextView time = (TextView) v.findViewById(R.id.active_timer_timeLeft);
time.setText(timer.expirationTime);
}
mAdapter.notifyDataSetChanged();
}

How to keep Base Activity running?

I have an activity named MainActivity.
In which I have started another activity (ContentDetails)
public void onItemClick(AdapterView<?> adapterView, View view, int position, long id) {
Uri contactUri = ContentUris.withAppendedId(People.CONTENT_URI, id);
Intent intent = new Intent(this, ContactDetails.class);
intent.setData(contactUri);
startActivity(intent);
}
And in ContactDetails.java I have written code to make a phone call.
but when I end call. It finishes all application instead of redirecting to base activity
following is the code of ContactDetails.java
public class ContactDetails extends Activity{
TextView nameField = null;
TextView phoneField = null;
TextView idField = null;
final Context context = this;
private Button button;
/**
* Called when the activity is first created.
*/
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.details);
idField = (TextView) findViewById(R.id.contact_id);
nameField = (TextView) findViewById(R.id.contact_name);
phoneField = (TextView) findViewById(R.id.contact_phone);
button = (Button) findViewById(R.id.call_button);
// add PhoneStateListener
PhoneCallListener phoneListener = new PhoneCallListener();
TelephonyManager telephonyManager;
telephonyManager = (TelephonyManager) this.getSystemService(Context.TELEPHONY_SERVICE);
telephonyManager.listen(phoneListener,PhoneStateListener.LISTEN_CALL_STATE);
// add button listener
button.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View arg0) {
Intent callIntent = new Intent(Intent.ACTION_CALL);
callIntent.setData(Uri.parse("tel:03577899456"));
startActivity(callIntent);
}
});
}
#Override
protected void onStart() {
super.onStart();
Cursor cursor = managedQuery(getIntent().getData(), null, null, null, null);
cursor.moveToFirst();
//idField.setText(cursor.getString(cursor.getColumnIndex(People._ID)));
nameField.setText(cursor.getString(cursor.getColumnIndex(People.DISPLAY_NAME)));
phoneField.setText(cursor.getString(cursor.getColumnIndex(People.NAME)));
}
private class PhoneCallListener extends PhoneStateListener {
private boolean isPhoneCalling = false;
String LOG_TAG = "LOGGING 123";
#Override
public void onCallStateChanged(int state, String incomingNumber) {
if (TelephonyManager.CALL_STATE_RINGING == state) {
// phone ringing
Log.i(LOG_TAG, "RINGING, number: " + incomingNumber);
}
if (TelephonyManager.CALL_STATE_OFFHOOK == state) {
// active
Log.i(LOG_TAG, "OFFHOOK");
isPhoneCalling = true;
}
if (TelephonyManager.CALL_STATE_IDLE == state) {
// run when class initial and phone call ended, need detect flag
// from CALL_STATE_OFFHOOK
Log.i(LOG_TAG, "IDLE");
if (isPhoneCalling) {
Log.i(LOG_TAG, "restart app");
// restart app
try{
// Intent intentAndroid = new Intent().setClass(this, ContactList.class);
Intent i = getBaseContext().getPackageManager()
.getLaunchIntentForPackage(getBaseContext().getPackageName());
i.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
startActivity(i);
}catch (Exception e) {
// TODO: handle exception
}
isPhoneCalling = false;
}
}
}
}
}
Actually, I think you have to use
startActivityForResult(callIntent, <RESULT_OK>);
instead of
startActivity(callIntent);
And override onActivityResult() in your ContactDetails Activity.
Try this and let me know what happen..
Also from your code I suggest you to don't use of Flag i.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP); As its clear the current Activities state Task.

Categories

Resources