I am working on a project where I have 3 tabs. The first tab is used to write information to NFC tag where the other 2 tabs are used to read the information from the NFC tag. However, I am facing a problem with OnNewIntent() method. As I understood correctly from reading online is that this method is used only in activities and not in fragments. I have looked at similar questions and answers but I don't fully understand what needs to be done to avoid this issue in my situation.
Here is my code for the first tab where I write some data to NFC tag:
public class Home extends Fragment {
NfcAdapter nfcAdapter;
Button writebtn;
Tag tag;
EditText txtName, txtCountry, txtID;
public void onViewCreated(View view, Bundle savedInstanceState) {
super.onViewCreated(view,savedInstanceState);
nfcAdapter = NfcAdapter.getDefaultAdapter(getContext());
txtName = (EditText)view.findViewById(R.id.personName);
txtCountry= (EditText)view.findViewById(R.id.personCountry);
txtID= (EditText)view.findViewById(R.id.personID);
writebtn=(Button)view.findViewById(R.id.nfcWriteBtn);
}
#Nullable
#Override
public View onCreateView(LayoutInflater inflater, #Nullable ViewGroup container, Bundle savedInstanceState) {
View v= inflater.inflate(R.layout.home, container,false);
return v;
}
#Override
public void onResume() {
super.onResume();
if(nfcAdapter !=null){
enableForegroundDispatchSystem();
}
}
#Override
public void onPause() {
super.onPause();
disableForegroundDispatchSystem();
}
protected void onNewIntent(final Intent intent) {
// super.onNewIntent(intent);
getActivity().getIntent();
if (intent.hasExtra(NfcAdapter.EXTRA_TAG)) {
Toast.makeText(getContext(), "NFC tag discovered!", Toast.LENGTH_SHORT).show();
tag = intent.getParcelableExtra(NfcAdapter.EXTRA_TAG);
writebtn.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
NdefMessage ndefMessage = createNdefMessage(txtName.getText().toString(), txtCountry.getText().toString(),txtID.getText().toString());
writeNdefMessage(tag, ndefMessage);
}
});
}
}
onNewIntent(Intent intent) belongs to Activity you cannot have it in fragment. What you can do is pass the data to your fragment whenever onNewIntent(Intent intent) get called in Activity. To achieve this You need to override onNewIntent() in Activity and notify the fragments about intent . Do not use getIntent() use the intent which is in argument.
#Override
protected void onNewIntent(Intent intent) {
super.onNewIntent(intent);
// Notify fragment about the new intent
}
And your Fragments method should look like .
protected void onNewIntent( Intent intent) {
if (intent.hasExtra(NfcAdapter.EXTRA_TAG)) {
Toast.makeText(getContext(), "NFC tag discovered!", Toast.LENGTH_SHORT).show();
tag = intent.getParcelableExtra(NfcAdapter.EXTRA_TAG);
writebtn.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
NdefMessage ndefMessage = createNdefMessage(txtName.getText().toString(), txtCountry.getText().toString(),txtID.getText().toString());
writeNdefMessage(tag, ndefMessage);
}
});
}
Related
I want to get results from BottomSheetFragment. I tried to do it through getActivity().setResult(Activity.RESULT_OK, null); inside
#Override
public void onDismiss(DialogInterface dialog) {
getActivity().setResult(Activity.RESULT_OK, null);
super.onDismiss(dialog);
}
but activity's method onActivityResult not called. What am I doing wrong?
#Override
public void onActivityResult(int requestCode, int resultCode, Intent data) {
Toast.makeText(this, requestCode, Toast.LENGTH_SHORT).show();
super.onActivityResult(requestCode, resultCode, data);
}
Dialog start method
BottomSheetDialogFragment bottomSheetFragment = new BottomSheetDialogFragment();
Bundle bundle = new Bundle();
bottomSheetFragment.setArguments(bundle);
bottomSheetFragment.show(getSupportFragmentManager(), bottomSheetFragment.getTag());
onActivityResult() is used for getting a result from another Activity.
More on this: https://developer.android.com/training/basics/intents/result
If you want to send some data from Fragment to Activity, you can do it either by defining an interface or call a method in the Activity by casting it to the specific Activity.
class MainActivity extends AppCompatActivity {
#Override
protected void onCreate(#Nullable Bundle savedInstanceState) {
YourBottomSheetDialogFragment bottomSheetFragment = new YourBottomSheetDialogFragment();
Bundle bundle = new Bundle();
bottomSheetFragment.setArguments(bundle);
bottomSheetFragment.show(getSupportFragmentManager(), bottomSheetFragment.getTag());
}
public void setResultFromFragment(String data) {
...
}
}
/**
* Calling Activity's method from Fragment
*/
class YourBottomSheetDialogFragment extends BottomSheetDialogFragment {
#Override
public void onCreate(#Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
((MainActivity) getActivity()).setResultFromFragment("");
}
}
I decided to implement the interface as suggested to me by DEVV911
interface OnFinishedListener {
void onFinished(ArrayList<TestCard> acceptList, ArrayList<TestCard> rejectList);
void onFailure(Throwable t);
}
add it into dialog's construction method
private TestActivityContract.OnFinishedListener onFinishedListener;
BottomSheetFragment(TestActivityContract.OnFinishedListener onFinishedListener) {
this.onFinishedListener = onFinishedListener;
}
And call the onFinished method in onDismiss
#Override
public void onDismiss(DialogInterface dialog) {
super.onDismiss(dialog);
onFinishedListener.onFinished(acceptList, rejectList);
}
In my project i use viewPager for show some fragments.
In one of fragments i want click on button.
I write below codes but when click on button not call onClickListener and not show Toast for me!
My codes in fragment :
#Override
public void setUserVisibleHint(boolean isVisibleToUser) {
super.setUserVisibleHint(isVisibleToUser);
if (isVisibleToUser){
Handler handler = new Handler();
handler.postDelayed(new Runnable() {
#Override
public void run() {
list_item = getActivity().findViewById(R.id.list_item);
list_item.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
if (clickFlag) {
AuctionTodayListAdapter adapter = new AuctionTodayListAdapter(getActivity(), R.layout.list_item_auction_large_new, Constants.auction.getToday());
list.setAdapter(adapter);
clickFlag = false;
list_item.setImageResource(R.drawable.list_icon);
Toast.makeText(context, ""+clickFlag, Toast.LENGTH_SHORT).show();
} else {
AuctionTodayListAdapter adapter = new AuctionTodayListAdapter(getActivity(), R.layout.list_item_auction_normal_soon, Constants.auction.getToday());
list.setAdapter(adapter);
clickFlag = true;
list_item.setImageResource(R.drawable.list);
Toast.makeText(context, ""+clickFlag, Toast.LENGTH_SHORT).show();
}
}
});
}
}, 50);
}
}
How can i fix this issue?
Why are you overriding setUserVisibleHint to set up a click listener?
UPDATE:
setUserVisibleHint has nothing to do with toolbar buttons ... that method is for you to call to let the system know the fragment is not visible. It's not normally called by the system, which is why your toast is never shown.
If the button you're trying to find is a toolbar item, you need to interact with it using the onCreateOptionsMenu and onOptionsItemSelected methods instead.
This is the sort of thing one does in onCreateView:
#Override
View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View view = // inflate view from layout resource
list_item = getActivity().findViewById(R.id.list_item); // Get toolbar item
list_item.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
// Do you click stuff
}
}
}
Then, if you only want to interact with this button when this fragment is active, you can show and hide it in onStart() and onStop, respectively.
#Override
public void onStart() {
super.onStart();
list_item.setVisibility(View.VISIBLE);
}
#Override
public void onStop() {
super.onStop();
list_item.setVisibility(View.GONE);
}
I have custom DialogFragment which called from another fragment:
final CustomCalendarDialogFragment newFragment = new CustomCalendarDialogFragment("CHOOSE_WEEK");
button.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
if (newFragment.isAdded()){
newFragment.getDialog().show();
} else {
newFragment.show(getFragmentManager(), "CUSTOM_CALENDAR");
}
}
});
In CustomCalendarDialogFragment when pressed "OK":
getDialog().hide();
After pressed on "OK" DialogFragment is hide, but when I unlock screen DialogFragment is displayed.
How to eliminate it?
You can track the state of showing/hiding the dialog in the tag attribute of the fragment view.
Initially set it as true (equivalent to shown) in onCreateView()
#Nullable
#org.jetbrains.annotations.Nullable
#Override
public View onCreateView(#NonNull LayoutInflater inflater, #Nullable #org.jetbrains.annotations.Nullable ViewGroup container, #Nullable #org.jetbrains.annotations.Nullable Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.bottom_sheet, container, false);
view.setTag(true);
return view
}
And whenever you show/hide it set it to true/false:
final CustomCalendarDialogFragment newFragment = new CustomCalendarDialogFragment("CHOOSE_WEEK");
button.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
if (newFragment.isAdded()){
newFragment.getDialog().show();
} else {
newFragment.show(getFragmentManager(), "CUSTOM_CALENDAR");
newFragment.requireView().setTag(true);
}
}
});
And set newFragment.requireView().setTag(false); when you call getDialog().hide();
And when the app goes to the background, check that tag on onResume() to see if you want to keep the dialog shown or hide it:
#Override
protected void onResume() {
super.onResume();
Object tag = newFragment.requireView().getTag();
if (tag instanceof Boolean){
if ((!(boolean)tag))
newFragment.getDialog().hide();
}
}
I am trying to return some data when a user clicks back from the Activity.
I am calling startActivityForResult from the adapter, but when I actually press back from the Activity, onActivityResult never seems to be called
Code is trimmed down for example
Fragment1
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
View mainView = inflater.inflate(R.layout.grid_view, container, false);
return mainView;
}
#Override
public void onActivityCreated(#Nullable Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
mAdapter = new Adapter(this.getActivity(), new ArrayList<Item>());
mGridView = (StaggeredGridView) getView().findViewById(R.id.grid_view);
mGridView.setAdapter(mAdapter);
}
#Override
public void onActivityResult(int requestCode, int resultCode, Intent data) {
Log.w(TAG, "in activity result");
if (requestCode == 1 && resultCode == Activity.RESULT_OK) {
}
Adapter
public Adapter(Context context, List<Item> objects) {
super(context, -1, objects);
this.context = context;
addAll(objects);
}
#Override
public View getView(int position, View convertView, ViewGroup parent) {
View view = convertView;
if (view == null) {
LayoutInflater inflater = (LayoutInflater) context.getSystemService(Activity.LAYOUT_INFLATER_SERVICE);
view = inflater.inflate(R.layout.grid_view_item, parent, false);
}
View recommendationLayout = view.findViewById(R.id.recommendation_layout);
recommendationLayout.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
Intent intent = new Intent(getContext(), Activity.class);
Bundle extras = new Bundle();
extras.putBoolean("denyEditPermission", true);
intent.putExtras(extras);
((Activity) context).((Activity) context).startActivityForResult(intent, 1);(intent, 1);
}
});
return view;
Activity
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.detailed_view);
Intent intent = getIntent();
Bundle extras = intent.getExtras();
denyEditPermission = extras.getBoolean("denyEditPermission");
}
#Override
public void onBackPressed() {
Intent intent = new Intent();
intent.putExtra("denyEditPermission", denyEditPermission);
setResult(RESULT_OK, intent);
finish();
}
Since you use activity context to start the activity, you will get onActivityResult callback in activity, not in fragment. To get callback in fragment, you need to use fragment context/start activity in fagment itself. I would suggest interface approach to fix the issue here.Create an interface and implement it in your fragment and when the recommendationLayout is clicked, call the interface method from adapter so that you can handle the click event in fragment itself.
Something like,
Create an interface file -
public interface RecommendationClickListener {
public void onRecommendationClicked();
}
Fragment:
public class MyFragment extends Fragment implements RecommendationClickListener{
...
...
...
#Override
public void onRecommendationClicked() {
Intent intent = new Intent(getActivity(), NextActivity.class);
Bundle extras = new Bundle();
extras.putBoolean("denyEditPermission", true);
intent.putExtras(extras);
startActivityForResult(intent, 1);
}
#Override
public void onActivityCreated(#Nullable Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
mAdapter = new Adapter(this.getActivity(), new ArrayList<Item>());
mAdapter.setRecommendationClickListener(this);
mGridView = (StaggeredGridView) getView().findViewById(R.id.grid_view);
mGridView.setAdapter(mAdapter);
}
Adapter:
private RecommendationClickListener mRecommendationClickListener;
public void setRecommendationClickListener(RecommendationClickListener recommendationClickListener) {
this.mRecommendationClickListener = recommendationClickListener;
}
View recommendationLayout = view.findViewById(R.id.recommendation_layout);
recommendationLayout.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
if (mRecommendationClickListener != null) {
mRecommendationClickListener.onRecommendationClicked();
}
}
});
The Broadcast solution is as follows:
In Fragment
Declare on top of the class
public final static String START_ACT = "com.yourcompanyname.appname.START_ACT";
private Radio radio;
On the createView initiate and register the receiver
//Initiate our receiver
radio = new Radio();
//Activate our recevier
getActivity().getApplicationContext().registerReceiver(radio, new IntentFilter(START_ACT));
Also in the fragment, create the receiver class and the mothod which calls the Activity
/**
* Receiver Class
* This setup checks for the incoming intent action to be able to
* attach more messages to one receiver.
*/
private class Radio extends BroadcastReceiver{
#Override
public void onReceive(Context context, Intent intent) {
if (intent.getAction().equals(START_ACT)){
getDataFromActivity();
}
}
}
public void getDataFromActivity(){
Intent intent = new Intent(getActivity(), Activity.class);
Bundle extras = new Bundle();
extras.putBoolean("denyEditPermission", true);
intent.putExtras(extras);
startActivityForResult(intent, 1);
}
After from anywhere in the application send message to our radio
context.sendBroadcast(new Intent(Fragment1.START_ACT));
In my App I have a MainActivity, which makes use of different fragments. One of these fragments is kind of a detail fragment, where I want to capture some serials by scanning a QR code. Currently, I am trying to use the IntentIntegrator. I am able to scan the code successfully, but after that, my App is not returning correctly. It just displays my MainActivity, but there is no Toast.
I also tried to put a onActivityResult() in the fragment and a super.onActivityResult()in the activities onActivityResult() but it is always the same behaviour. It just jumps into the MainActivity and nothing futher happens.
Can somebody exlain to me, where I made the mistakes? I want to scan the barcode and get the results in my fragment class.
Here is my MainActivity Code:
public class MainActivity extends Activity {
private Button startenButton, ansehenButton, abmeldenButton;
private FrameLayout fragmentFrame;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
fragmentFrame = (FrameLayout) findViewById(R.id.frameLayout);
startenButton = (Button) findViewById(R.id.buttonPruefungStart);
startenButton.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
FragmentTransaction transaction = getFragmentManager().beginTransaction();
if (fragmentFrame.getChildCount() < 1) {
transaction.add(R.id.frameLayout, new PruefungStartenFragment());
} else {
transaction.replace(R.id.frameLayout, new PruefungStartenFragment());
}
transaction.commit();
}
});
}
public void scan() {
IntentIntegrator integrator = new IntentIntegrator(this);
integrator.initiateScan();
}
#Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
IntentResult scanResult = IntentIntegrator.parseActivityResult(requestCode, resultCode, data);
if (scanResult != null) {
Toast.makeText(this, scanResult.getContents(), Toast.LENGTH_LONG).show();
}
}
}
And here is my PruefungStartenFragment Code:
public class PruefungStartenFragment extends Fragment {
private TextView datum, ort, pruefer, bedienerdisplay, scanner, fingerprintscanner, quittungsdrucker, barcodeleser,
webcam, kundendisplay, terminal;
private Button scanButton, startButton;
public static PruefungStartenFragment newInstance(String code) {
Bundle args = new Bundle();
args.putSerializable("code", code);
PruefungStartenFragment fragment = new PruefungStartenFragment();
fragment.setArguments(args);
return fragment;
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View v = inflater.inflate(R.layout.pruefung_starten_fragment, container, false);
scanButton = (Button) v.findViewById(R.id.buttonScan);
scanButton.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
((MainActivity)getActivity()).scan();
}
});
return v;
}
}
I figured out my problem... In my manifest I had a android:noHistory="true" in my MainActivity. This prevents the scanning activity in the barcode scanner to pass the result to my MainActivity, because there is no activity on the stack, where it could pass results to.