I've been stuck in a situation and i need some help over here. There are many articles on this topic here but none of them answered my question. I want to implement onBackPressed() in fragments and show dialog box which shows to exit the application or not. Any help would be appreciated.
LoginFragment.java
public class LoginFragment extends Fragment {
public static final String TAG = LoginFragment.class.getSimpleName();
private EditText mEtEmail;
private EditText mEtPassword;
private Button mBtLogin;
private TextView mTvRegister;
private TextView mTvForgotPassword;
private TextInputLayout mTiEmail;
private TextInputLayout mTiPassword;
private ProgressBar mProgressBar;
private CompositeSubscription mSubscriptions;
private SharedPreferences mSharedPreferences;
#NonNull
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.fragment_login,container,false);
mSubscriptions = new CompositeSubscription();
initViews(view);
initSharedPreferences();
return view;
}
private void initViews(View v) {
mEtEmail = v.findViewById(R.id.et_email);
mEtPassword = v.findViewById(R.id.et_password);
mBtLogin = v.findViewById(R.id.btn_login);
mTiEmail = v.findViewById(R.id.ti_email);
mTiPassword = v.findViewById(R.id.ti_password);
mProgressBar = v.findViewById(R.id.progress);
mTvRegister = v.findViewById(R.id.tv_register);
mTvForgotPassword = v.findViewById(R.id.tv_forgot_password);
mBtLogin.setOnClickListener(view -> login());
mTvRegister.setOnClickListener(view -> goToRegister());
mTvForgotPassword.setOnClickListener(view -> showDialog());
}
private void initSharedPreferences() {
mSharedPreferences = PreferenceManager.getDefaultSharedPreferences(getActivity());
}
private void login() {
setError();
String email = mEtEmail.getText().toString();
String password = mEtPassword.getText().toString();
int err = 0;
if (!validateEmail(email)) {
err++;
mTiEmail.setError("Email should be valid !");
}
if (!validateFields(password)) {
err++;
mTiPassword.setError("Password should not be empty !");
}
if (err == 0) {
loginProcess(email,password);
mProgressBar.setVisibility(View.VISIBLE);
} else {
showSnackBarMessage("Enter Valid Details !");
}
}
private void setError() {
mTiEmail.setError(null);
mTiPassword.setError(null);
}
private void loginProcess(String email, String password) {
mSubscriptions.add(NetworkUtil.getRetrofit(email, password).login()
.observeOn(AndroidSchedulers.mainThread())
.subscribeOn(Schedulers.io())
.subscribe(this::handleResponse,this::handleError));
}
private void handleResponse(Response response) {
mProgressBar.setVisibility(View.GONE);
SharedPreferences.Editor editor = mSharedPreferences.edit();
editor.putString(Constants.TOKEN,response.getToken());
editor.putString(Constants.EMAIL,response.getMessage());
editor.apply();
mEtEmail.setText(null);
mEtPassword.setText(null);
Intent intent = new Intent(getActivity(), HomeActivity.class);
startActivity(intent);
}
private void handleError(Throwable error) {
mProgressBar.setVisibility(View.GONE);
if (error instanceof HttpException) {
Gson gson = new GsonBuilder().create();
try {
String errorBody = ((HttpException) error).response().errorBody().string();
Response response = gson.fromJson(errorBody,Response.class);
showSnackBarMessage(response.getMessage());
} catch (IOException e) {
e.printStackTrace();
}
} else {
showSnackBarMessage("No Internet Connection!");
}
}
private void showSnackBarMessage(String message) {
if (getView() != null) {
Snackbar.make(getView(),message,Snackbar.LENGTH_SHORT).show();
}
}
private void goToRegister(){
FragmentTransaction ft = getFragmentManager().beginTransaction();
RegisterFragment fragment = new RegisterFragment();
ft.replace(R.id.fragmentFrame,fragment,RegisterFragment.TAG);
ft.addToBackStack(null).commit();
}
private void showDialog(){
ResetPasswordDialog fragment = new ResetPasswordDialog();
fragment.show(getFragmentManager(), ResetPasswordDialog.TAG);
}
#Override
public void onDestroy() {
super.onDestroy();
mSubscriptions.unsubscribe();
}
}
MainActivity.java
public class MainActivity extends AppCompatActivity implements ResetPasswordDialog.Listener {
public static final String TAG = MainActivity.class.getSimpleName();
private LoginFragment mLoginFragment;
private ResetPasswordDialog mResetPasswordDialog;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
if (savedInstanceState == null) {
loadFragment();
}
}
private void loadFragment() {
if (mLoginFragment == null) {
mLoginFragment = new LoginFragment();
}
getFragmentManager().beginTransaction().replace(R.id.fragmentFrame, mLoginFragment, LoginFragment.TAG).commit();
}
#Override
protected void onNewIntent(Intent intent) {
super.onNewIntent(intent);
String data = intent.getData().getLastPathSegment();
Log.d(TAG, "onNewIntent: " + data);
mResetPasswordDialog = (ResetPasswordDialog) getFragmentManager().findFragmentByTag(ResetPasswordDialog.TAG);
if (mResetPasswordDialog != null)
mResetPasswordDialog.setToken(data);
}
#Override
public void onPasswordReset(String message) {
showSnackBarMessage(message);
}
private void showSnackBarMessage(String message) {
Snackbar.make(findViewById(R.id.activity_main), message, Snackbar.LENGTH_SHORT).show();
}
}
In My Login Fragment, I want to show a dialog box "Do you want to exit the application or not". On Yes it dismiss the current fragment and end the activity otherwise it'll remain active. Help please!
You can even try this way
MainActivity.java
#Override
public void onBackPressed() {
if (getFragmentManager() != null && getFragmentManager().getBackStackEntryCount() >= 1) {
String fragmentTag = getFragmentManager().findFragmentById(R.id.frame_container).getTag();
if(fragmentTag.equals(LoginFragment.getTag())){
// show Dialog code
}else{
super.onBackPressed();
}
} else {
super.onBackPressed();
}
}
Add this code in your main activity so that when login fragment is added and you click backpress, then on first if the fragment is added to fragment transaction, then first it finds the fragment and check if its tag is equals to the login fragment tag. Then if both tag matches, then you can show your exit alert dialog.
Android team has prepared a new way of handling the back button pressed on Fragments for us, so you should check this out. It's called OnBackPressedDispatcher.
You need to register OnBackPressedCallback to the fragment where do you want to intercept back button pressed. You can do it like this inside of the Fragment:
#Override
public void onAttach(#NonNull Context context) {
super.onAttach(context);
OnBackPressedCallback callback = new OnBackPressedCallback(true) {
#Override
public void handleOnBackPressed() {
//show exit dialog
}
};
requireActivity().getOnBackPressedDispatcher().addCallback(this, callback);
}
Related
I have a problem. I want to use the method onNewIntent() in a fragment. I have fortunately received one really good answer ( Please have a look ). I tried to work with this code snipped, but unfortunately the NFC tag cannot be read. What is it that I am doing wrong?
I hope you can help me with this issue. I would be very thankful for every answer.
The new code was always inserted between the comment lines // NEW INTENT
UserFragmentGeldaufladen
public class UserFragmentGeldaufladen extends Fragment {
private Button btn_user_geldaufladen, btn_user_main_geldsendenAbort;
private EditText edittext_user_geldaufladen;
private Dialog epicDialog;
private NfcAdapter nfcAdapter;
private PendingIntent pendingIntent;
private boolean writeMode;
private IntentFilter writeTagFilters[];
private Context context;
private Tag myTag;
private interface RetrievalEventListener<T> {
abstract void onDataRetrieved(T t);
}
#Nullable
#Override
public View onCreateView(#NonNull LayoutInflater inflater, #Nullable ViewGroup container, #Nullable Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.fragment_user_geldaufladen, container, false);
btn_user_geldaufladen = view.findViewById(R.id.btn_user_geldaufladen);
edittext_user_geldaufladen = view.findViewById(R.id.edittext_user_geldaufladen);
context = view.getContext();
epicDialog = new Dialog(view.getContext());
nfcAdapter = NfcAdapter.getDefaultAdapter(view.getContext());
if (nfcAdapter == null) {
// Stop here, we definitely need NFC
Toast.makeText(view.getContext(), "This device doesn't support NFC.", Toast.LENGTH_LONG).show();
}
// NEW INTENT
Intent i = new Intent(context, UserHomeActivity.class);
i.addFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP);
//i.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); // -> this will be require, if you will be update your fragment from BroadcastReceiver or Service
startActivity(i);
// NEW INTENT
readFromIntent( getActivity().getIntent());
pendingIntent = PendingIntent.getActivity(context, 0, new Intent(context, getClass()).addFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP), 0);
IntentFilter tagDetected = new IntentFilter(NfcAdapter.ACTION_TAG_DISCOVERED);
tagDetected.addCategory(Intent.CATEGORY_DEFAULT);
btn_user_geldaufladen.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
transaction();
}
});
return view;
}
// NEW INTENT
#Override
public void onCreate(#Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
//get first time intent
Intent intent = getActivity().getIntent();
((UserHomeActivity)getActivity()).setOnNewIntentListener(new OnNewIntentListener() {
#Override
public void newIntent(Intent intent) {
readFromIntent(intent);
if (NfcAdapter.ACTION_TAG_DISCOVERED.equals(intent.getAction())) {
myTag = intent.getParcelableExtra(NfcAdapter.EXTRA_TAG);
}
}
});
}
// NEW INTENT
private void readFromIntent(Intent intent) {
String action = intent.getAction();
if (NfcAdapter.ACTION_TAG_DISCOVERED.equals(action)
|| NfcAdapter.ACTION_TECH_DISCOVERED.equals(action)
|| NfcAdapter.ACTION_NDEF_DISCOVERED.equals(action)) {
Parcelable[] rawMsgs = intent.getParcelableArrayExtra(NfcAdapter.EXTRA_NDEF_MESSAGES);
NdefMessage[] msgs = null;
if (rawMsgs != null) {
msgs = new NdefMessage[rawMsgs.length];
for (int i = 0; i < rawMsgs.length; i++) {
msgs[i] = (NdefMessage) rawMsgs[i];
}
}
buildTagViews(msgs);
}
}
private void buildTagViews(NdefMessage[] msgs) {
if (msgs == null || msgs.length == 0) return;
String text = "";
// String tagId = new String(msgs[0].getRecords()[0].getType());
byte[] payload = msgs[0].getRecords()[0].getPayload();
String textEncoding = ((payload[0] & 128) == 0) ? "UTF-8" : "UTF-16"; // Get the Text Encoding
int languageCodeLength = payload[0] & 0063; // Get the Language Code, e.g. "en"
// String languageCode = new String(payload, 1, languageCodeLength, "US-ASCII");
try {
// Get the Text
text = new String(payload, languageCodeLength + 1, payload.length - languageCodeLength - 1, textEncoding);
} catch (UnsupportedEncodingException e) {
Log.e("UnsupportedEncoding", e.toString());
}
System.out.println(text);
}
/***
* Initiates the transaction
*/
private void transaction() {
String amount_geldaufladen = String.valueOf(edittext_user_geldaufladen.getText());
if(!amount_geldaufladen.isEmpty() && Integer.parseInt(amount_geldaufladen) > 0) {
showWaitingPopup();
}
}
/***
* Shows that the user should confirm the payment
*/
private void showWaitingPopup() {
epicDialog.setContentView(R.layout.user_main_popup_waiting);
epicDialog.getWindow().setBackgroundDrawable(new ColorDrawable(Color.TRANSPARENT));
btn_user_main_geldsendenAbort = (Button) epicDialog.findViewById(R.id.btn_user_main_geldsendenAbort);
btn_user_main_geldsendenAbort.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
firebaseTransaction(new RetrievalEventListener<Integer>() {
#Override
public void onDataRetrieved(Integer integer) {
if(integer == 1) {
// do something
}
}
});
epicDialog.dismiss();
}
});
epicDialog.show();
}
/***
* Accesses the Firebase database and handles everything
*/
private void firebaseTransaction(final RetrievalEventListener<Integer> retrievalEventListener) {
// do Something
retrievalEventListener.onDataRetrieved(1);
}
/*
#Override
protected void onNewIntent(Intent intent) {
super.onNewIntent(intent);
setIntent(intent);
readFromIntent(intent);
if (NfcAdapter.ACTION_TAG_DISCOVERED.equals(intent.getAction())) {
myTag = intent.getParcelableExtra(NfcAdapter.EXTRA_TAG);
}
}
*/
#Override
public void onPause(){
super.onPause();
WriteModeOff();
}
#Override
public void onResume(){
super.onResume();
WriteModeOn();
}
/******************************************************************************
**********************************Enable Write********************************
******************************************************************************/
private void WriteModeOn(){
writeMode = true;
nfcAdapter.enableForegroundDispatch((Activity) context, pendingIntent, writeTagFilters, null);
}
/******************************************************************************
**********************************Disable Write*******************************
******************************************************************************/
private void WriteModeOff(){
writeMode = false;
nfcAdapter.disableForegroundDispatch((Activity) context);
}
}
UserHomeActivity
public class UserHomeActivity extends AppCompatActivity implements NavigationView.OnNavigationItemSelectedListener, UserOnFragmentBtnSelected {
Toolbar toolbar;
DrawerLayout drawer;
ActionBarDrawerToggle toggle;
NavigationView navigationView;
FragmentManager fragmentManager;
FragmentTransaction fragmentTransaction;
Fragment fragment;
String username;
// NEW INTENT
private OnNewIntentListener mOnNewIntentListener;
#Override
protected void onNewIntent(Intent intent) {
super.onNewIntent(intent);
if (mOnNewIntentListener != null) {
mOnNewIntentListener.newIntent(intent);
}
}
public void setOnNewIntentListener(OnNewIntentListener onNewIntentListener) {
this.mOnNewIntentListener = onNewIntentListener;
}
// NEW INTENT
OnNewIntentListener
public interface OnNewIntentListener {
void newIntent(Intent intent);
}
So, I've been using the Google's Friendlyeats example as guide. I changed it a bit in order to use Butterknife but had issues when trying to open a single doc (fragment) and show its content in the following activity.
I'm using a recyclerview to show the summarize data and then I want to show the full individual data on an activity. It's really not that much info, just four textviews.
Because of this, I decided to stick to the original example as much as I could to see what was up. Still same error. I can open the following activity but no data is being displayed.
I'm already three months behind lmao. please help!
here's the code:
MessageAdapter.java
#Override
public void onBindViewHolder(#NonNull ViewHolder holder, int position) {
holder.bind(getSnapshot(position), mListener);
}
static class ViewHolder extends RecyclerView.ViewHolder {
public ViewHolder(View itemView) {
super(itemView);
headerView = itemView.findViewById(R.id.message_item_header);
senderView = itemView.findViewById(R.id.message_item_sender);
dateView = itemView.findViewById(R.id.message_item_date);
imageView = itemView.findViewById(R.id.message_item_image);
actualMessageView = itemView.findViewById(R.id.actual_message);
}
public void bind(final DocumentSnapshot snapshot,
final OnMessageSelectedListener listener) {
Messages messages = snapshot.toObject(Messages.class);
imageView.setImageResource(R.drawable.logo_app_off);
headerView.setText(messages.getHeader());
senderView.setText(messages.getSender());
actualMessageView.setText(messages.getMessage());
dateView.setText(messages.getDate());
itemView.setOnClickListener(v -> {
if (listener != null) {
listener.onMessageSelectedListener(snapshot);
}
});
}
}
}
HomeFragment.java
#Override
public void onMessageSelectedListener(DocumentSnapshot message) {
Intent intent = new Intent(getActivity(), MessageDetailActivity.class);
intent.putExtra(KEY_MESSAGE_ID, message.getId());
startActivity(intent);
}
private void initFirestore() {
mFirestore = FirebaseFirestore.getInstance();
mQuery = mFirestore.collection("messages")
.orderBy("date", Query.Direction.DESCENDING)
.limit(LIMIT);
}
private void initRecyclerView() {
if (mQuery == null) {
Log.w(TAG, "No query, not initializing RecyclerView");
}
mAdapter = new MessageAdapter(mQuery, this) {
#Override
protected void onDataChanged() {
if (getItemCount() == 0) {
mMessagesRecycler.setVisibility(View.GONE);
mEmptyView.setVisibility(View.VISIBLE);
} else {
mMessagesRecycler.setVisibility(View.VISIBLE);
mEmptyView.setVisibility(View.GONE);
}
}
#Override
protected void onError(FirebaseFirestoreException e) {
Snackbar.make(view.findViewById(android.R.id.content),
"Error: check logs for info.", Snackbar.LENGTH_LONG).show();
}
};
mMessagesRecycler.setLayoutManager(new LinearLayoutManager(getActivity()));
mMessagesRecycler.setAdapter(mAdapter);
}
DetailMessageActivity.java
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_message_detail);
String messageId = getIntent().getExtras().getString(KEY_MESSAGE_ID);
if (messageId == null) {
throw new IllegalArgumentException("Must pass extra " + KEY_MESSAGE_ID);
}
mFirestore = FirebaseFirestore.getInstance();
mMessageRef = mFirestore.collection("messages").document(messageId);
}
#Override
public void onEvent(DocumentSnapshot snapshot, FirebaseFirestoreException e) {
if (e != null) {
Log.w(TAG, "message:onEvent", e);
return;
}
onMessageLoaded(snapshot.toObject(Messages.class));
}
private void onMessageLoaded(Messages message) {
mDetailedHeader.setText(message.getHeader());
mDetailedHeader.setText(message.getSender());
mDetailedMessage.setText(message.getMessage());
mDetailedDate.setText(message.getDate());
}
}
Is it possible in mapView to load a marker when the user clicks a button or submits a search in searchView. I am having trouble getting marker locations to show when the user submits data. When the user submits the info it pulls the lat and long but does not update the position from the view model immediately.
public class SearchFragment extends Fragment implements OnMapReadyCallback {
private static final String TAG = "SearchFragment";
private SearchViewModel searchViewModel;
private LatLng location;
private Marker marker;
//UI
private MapView mapView;
private SearchView searchView;
private TextView cityTv, countryTv, regionTv, ispTv, timezoneTv, postalTv, countryCallingCodeTv;
private static final String MAPVIEW_BUNDLE = "MAPVIEW_BUNDLE";
public View onCreateView(#NonNull LayoutInflater inflater,
ViewGroup container, final Bundle savedInstanceState) {
Log.d(TAG, "onCreateView: ");
final View view = inflater.inflate(R.layout.fragment_search, container, false);
searchView = view.findViewById(R.id.search_searchview);
cityTv = view.findViewById(R.id.city_input_textview);
countryTv = view.findViewById(R.id.country_input_textview);
regionTv = view.findViewById(R.id.region_input_textview);
ispTv = view.findViewById(R.id.isp_input_textview);
timezoneTv = view.findViewById(R.id.timezone_input_textview);
postalTv = view.findViewById(R.id.postal_input_textview);
countryCallingCodeTv = view.findViewById(R.id.countrycallingcode_input_textview);
Bundle mapViewBundle = null;
if (savedInstanceState != null) {
mapViewBundle = savedInstanceState.getBundle(MAPVIEW_BUNDLE);
}
mapView = view.findViewById(R.id.location_mapview);
mapView.onCreate(mapViewBundle);
searchViewModel = ViewModelProviders.of(this).get(SearchViewModel.class);
searchView.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(final View view) {
searchView.setIconified(false);
//returns result from search view
getSearchViewResults(view);
}
});
return view;
}
#Override
public void onSaveInstanceState(#NonNull Bundle outState) {
super.onSaveInstanceState(outState);
Bundle mapViewBundle = outState.getBundle(MAPVIEW_BUNDLE);
if (mapViewBundle == null) {
mapViewBundle = new Bundle();
outState.putBundle(MAPVIEW_BUNDLE, mapViewBundle);
}
mapView.onSaveInstanceState(mapViewBundle);
}
//retrieves the search results from searchView and passes information to searchviewmodel
public void getSearchViewResults(final View view) {
searchView.setOnQueryTextListener(new SearchView.OnQueryTextListener() {
#Override
public boolean onQueryTextSubmit(String query) {
Log.d(TAG, "onQueryTextSubmit: ");
//TODO: add input validation to make sure addres is correct
//TODO: if incorrect display toast message saying input is invalid
searchViewModel.getIpAddress(query);
//observer to observe data change and display search results in textview
observeSearchView();
mapView.getMapAsync(SearchFragment.this);
return false;
}
#Override
public boolean onQueryTextChange(String newText) {
return false;
}
});
}
private void observeSearchView() {
searchViewModel.getIpLocation().observe(SearchFragment.this, new Observer<IPLocation>() {
#Override
public void onChanged(IPLocation ipLocation) {
cityTv.setText(ipLocation.getCity());
countryTv.setText(ipLocation.getCountry());
regionTv.setText(ipLocation.getRegion());
ispTv.setText(ipLocation.getOrg());
timezoneTv.setText(ipLocation.getTimezone());
countryCallingCodeTv.setText(ipLocation.getCountryCallingCode());
postalTv.setText(ipLocation.getPostal());
location = new LatLng(ipLocation.getLatitude(), ipLocation.getLongitude());
// Toast.makeText(getContext(), "Lat: " + location, Toast.LENGTH_SHORT).show();
}
});
}
//displays the lat/lon of entered address
#Override
public void onMapReady(GoogleMap googleMap) {
Log.d(TAG, "onMapReady: ");
//test adds marker in sydney and moves the camera to location
if (searchViewModel.getResult()) {
try {
marker = googleMap.addMarker(new MarkerOptions().position(location).title("Location"));
marker.setPosition(location);
googleMap.moveCamera(CameraUpdateFactory.newLatLng(location));
googleMap.getMinZoomLevel();
} catch (Exception e) {
Toast.makeText(getContext(), "Exception: " + e, Toast.LENGTH_SHORT).show();
}
} else {
Toast.makeText(getContext(), "FALSE", Toast.LENGTH_SHORT).show();
}
}
#Override
public void onResume() {
Log.d(TAG, "onResume: map ");
super.onResume();
mapView.onResume();
}
#Override
public void onStart() {
Log.d(TAG, "onStart: map");
super.onStart();
mapView.onStart();
}
#Override
public void onStop() {
Log.d(TAG, "onStop: map");
super.onStop();
mapView.onStop();
}
#Override
public void onPause() {
Log.d(TAG, "onPause: map ");
super.onPause();
mapView.onPause();
}
#Override
public void onDestroy() {
Log.d(TAG, "onDestroy: map");
super.onDestroy();
mapView.onDestroy();
}
public class SearchViewModel extends ViewModel {
private static final String TAG = "SearchViewModel";
private Boolean result = false;
private String input;
private ArrayList<IPLocation> ipLocationsList;
private MutableLiveData<IPLocation> ipLocation;
private MutableLiveData<Double> latResult = new MutableLiveData<>();
private MutableLiveData<Double> lonResult = new MutableLiveData<>();
public SearchViewModel() {
Log.d(TAG, "SearchViewModel: ");
ipLocation = new MutableLiveData<>();
ipLocationsList = new ArrayList<>();
}
public void getIpAddress(String ipAdress) {
Log.d(TAG, "getInfo: Start");
Calendar calendar = Calendar.getInstance();
final Date dateNow = calendar.getTime();
final GetDataService[] getDataService = {RetrofitClientInstance.getRetrofit()
.create(GetDataService.class)};
Call<IPLocation> call = getDataService[0].getLocationByIP(ipAdress);
call.enqueue(new Callback<IPLocation>() {
#Override
public void onResponse(Call<IPLocation> call, Response<IPLocation> response) {
Log.d(TAG, "onResponse: Start");
ipLocation.setValue(new IPLocation(0, response.body().getIp(),
response.body().getCity(), response.body().getRegion(),
response.body().getRegionCode(), response.body().getCountry(), response.body().getCountryName(),
response.body().getContinentCode(), response.body().getInEu(), response.body().getPostal(),
response.body().getLatitude(), response.body().getLongitude(), response.body().getTimezone(),
response.body().getUtcOffset(), response.body().getCountryCallingCode(), response.body().getCurrency(),
response.body().getLanguages(), response.body().getAsn(), response.body().getOrg(), dateNow));
latResult.setValue(response.body().getLatitude());
lonResult.setValue(response.body().getLongitude());
setResult(true);
}
#Override
public void onFailure(Call<IPLocation> call, Throwable t) {
Log.d(TAG, "onFailure: Fail");
}
});
}
public Boolean getResult() {
return result;
}
public void setResult(Boolean result) {
this.result = result;
}
public MutableLiveData<IPLocation> getIpLocation() {
return ipLocation;
}
public MutableLiveData<Double> getLatResult() {
return latResult;
}
public void setLatResult(MutableLiveData<Double> latResult) {
this.latResult = latResult;
}
public MutableLiveData<Double> getLonResult() {
return lonResult;
}
public void setLonResult(MutableLiveData<Double> lonResult) {
this.lonResult = lonResult;
}
}
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<TextView
android:id="#+id/location_title_textview"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:text="#string/location_title"
android:textAlignment="center"
android:textSize="24sp" />
<com.google.android.gms.maps.MapView
android:id="#+id/location_mapview"
android:layout_width="match_parent"
android:layout_height="319dp" />
</LinearLayout>
Save your google map object globally after receiving object from onMapReady(GoogleMap googleMap) callback.
After making an API call and fetching the result, do something like this to your map
LatLng latlng = new LatLng(response.body().getLatitude(), response.body().getLongitude());
MarkerOptions markerOption = new MarkerOption();
markerOptions.setPosition(latlng);
markerOptions.setIcon(*PASS_YOUR_BITMAP_FOR_ICON_HERE*);
markerOptions.title("Location")
Marker marker = googleMap.addMarker(markerOption);
googleMap.moveCamera(CameraUpdateFactory.newLatLng(latlng));
In my android app, I want to display the localized price, for an In-App purchase, on a button.
I've tried following a guide to set up the In-App Billing (https://medium.com/#patpatchpatrick/adding-the-google-play-billing-library-to-your-application-fbeb9ec03151) to set up the billing itself, and it seems to work on a test account.
Although .setSku and .setType is now deprecated, and .setSkuDetails is now to be used, which from documentation is great, as there's plenty of options. However i can't seem to get any access to the SkuDetails class..
For a couple of weeks I've tried implementing In-App Billing, and looked at various articles and guides, but can't seem to find my way about it. I feel like i've tried everything and doesn't know where to turn next.
public class InAppBilling extends AppCompatActivity implements
PurchasesUpdatedListener {
private static final String TAG = "InAppBilling";
//In APP Produkter
static final String ITEM_SKU_ADREMOVAL = "remove_ads_salary1";
private Button mButton;
private Button back_Button;
private String mAdRemovalPrice;
private SharedPreferences mSharedPreferences;
private BillingClient mBillingClient;
#Override
protected void onCreate(#Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.inappbilling);
mBillingClient = BillingClient.newBuilder(InAppBilling.this).setListener(this).build();
mBillingClient.startConnection(new BillingClientStateListener() {
#Override
public void onBillingSetupFinished(int responseCode) {
if (responseCode == BillingClient.BillingResponse.OK){
List skuList = new ArrayList<>();
skuList.add(ITEM_SKU_ADREMOVAL);
SkuDetailsParams.Builder params = SkuDetailsParams.newBuilder();
params.setSkusList(skuList).setType(BillingClient.SkuType.INAPP);
mBillingClient.querySkuDetailsAsync(params.build(),
new SkuDetailsResponseListener() {
#Override
public void onSkuDetailsResponse(int responseCode, List<SkuDetails> skuDetailsList) {
//Processing the response if the code = OK, and skuDetailsList isn't = null(empty)
if (responseCode == BillingClient.BillingResponse.OK && skuDetailsList != null){
for (SkuDetails skuDetails : skuDetailsList){
String sku = skuDetails.getSku();
String price = skuDetails.getPrice();
if (ITEM_SKU_ADREMOVAL.equals(sku)){
mAdRemovalPrice = price;
}
}
}
}
});
}
}
#Override
public void onBillingServiceDisconnected() {
// IMPLEMENT RETRY POLICY - TRY TO RESTART ON NEXT REQUEST BY CALLING startConnection()
}
});
mButton = findViewById(R.id.buy_button);
mButton.setOnClickListener(new View.OnClickListener(){
#Override
public void onClick(View view){
BillingFlowParams flowParams = BillingFlowParams.newBuilder()
//THIS skuDetails gives the error 'Cannot resolve symbol
.setSkuDetails(skuDetails)
// .setSku(ITEM_SKU_ADREMOVAL)
// .setType(BillingClient.SkuType.INAPP)
.build();
int responseCode = mBillingClient.launchBillingFlow(InAppBilling.this, flowParams);
}
});
back_Button = findViewById(R.id.back_button);
back_Button.setOnClickListener(new View.OnClickListener(){
#Override
public void onClick(View view){
//Returnere til det fragment man kom fra
InAppBilling.super.onBackPressed();
}
});
}
Well, I'd love to gain access over SkuDetails, so I can use it's method getPrice(), to show localized prices, for my in-app.
Right now, I can't use getPrice().
Make your activity to implement the listeners, then you will be able to access everything more easily.
I reformatted your code to implement all your listeners, and it may have some minor mistakes, but I hope you get the idea.
Notice that I've also implemented the View.OnClickListener which makes the code more clear, yet you will need to assign at module level a variable for the skuDetails being passed to the builder, which I didn't do. Let me know if you have any questions.
public class InAppBilling extends AppCompatActivity implements
PurchasesUpdatedListener, SkuDetailsResponseListener,
BillingClientStateListener, View.OnClickListener
{
private static final String TAG = "InAppBilling";
//In APP Produkter
static final String ITEM_SKU_ADREMOVAL = "remove_ads_salary1";
private Button mButton;
private Button back_Button;
private String mAdRemovalPrice;
private SharedPreferences mSharedPreferences;
private BillingClient mBillingClient;
#Override
protected void onCreate(#Nullable Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.inappbilling);
mBillingClient = BillingClient.newBuilder(this).setListener(this).build();
mBillingClient.startConnection(this);
findViewById(R.id.buy_button).setOnClickListener(this);
findViewById(R.id.back_button).setOnClickListener(this);
}
#Override
public void onPurchasesUpdated(int responseCode, #Nullable List<Purchase> purchases)
{
}
#Override
public void onSkuDetailsResponse(int responseCode, List<SkuDetails> skuDetailsList)
{
if (responseCode == BillingClient.BillingResponse.OK && skuDetailsList != null)
{
for (SkuDetails skuDetails : skuDetailsList)
{
String sku = skuDetails.getSku();
String price = skuDetails.getPrice();
if (ITEM_SKU_ADREMOVAL.equals(sku))
{
mAdRemovalPrice = price;
}
}
}
}
#Override
public void onClick(View view)
{
if (view.getId() == R.id.back_button)
{
super.onBackPressed();
}
else if (view.getId() == R.id.buy_button)
{
BillingFlowParams flowParams = BillingFlowParams.newBuilder()
.setSkuDetails(skuDetails)
.build();
int responseCode = mBillingClient.launchBillingFlow(this, flowParams);
}
}
#Override
public void onBillingSetupFinished(int responseCode)
{
if (responseCode == BillingClient.BillingResponse.OK)
{
List skuList = new ArrayList<>();
skuList.add(ITEM_SKU_ADREMOVAL);
SkuDetailsParams.Builder params = SkuDetailsParams.newBuilder();
params.setSkusList(skuList).setType(BillingClient.SkuType.INAPP);
mBillingClient.querySkuDetailsAsync(params.build(), this);
}
}
#Override
public void onBillingServiceDisconnected()
{
// IMPLEMENT RETRY POLICY - TRY TO RESTART ON NEXT REQUEST BY CALLING startConnection()
}
}
I have a videoview and listview/gridview in my playvideo activity.
One video is already playing in the videoview. But now i want to play the other video which are showing in the listview/gridview how can i do that?
Playvideo Activity
public class playvideoactivity extends Activity {
GridViewWithHeaderAndFooter grid;
String videourl="http://www.quirksmode.org/html5/videos/big_buck_bunny.mp4";
private static final String url = "http://dakwf.org/api/bd_english.json";
private List<ChannelItem> chanellist = new ArrayList<ChannelItem>();
private static final String TAG = MainActivity.class.getSimpleName();
public static VideoView player;
public static ImageButton btnPlayPause;
private ImageView btnFullscreen;
private ProgressBar spinner;
private RelativeLayout mediaController;
private Handler btnHandler = new Handler();
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
spinner = (ProgressBar) findViewById(R.id.progressBar);
player=(VideoView) findViewById(R.id.player);
mediaController=(RelativeLayout) findViewById(R.id.media_controller);
spinner.setVisibility(View.VISIBLE);
mediaController.setVisibility(View.INVISIBLE);
btnPlayPause=(ImageButton) findViewById(R.id.btn_playpause);
btnFullscreen=(ImageView) findViewById(R.id.btn_fullscreen);
final CustomGridviewadapter customGridview= new CustomGridviewadapter(this,chanellist);
grid = (GridViewWithHeaderAndFooter) findViewById(R.id.grid_view);
setGridViewHeaderAndFooter();
grid.setAdapter(customGridview);
//----------- Creating volley request obj--------------------
JsonArrayRequest movieReq = new JsonArrayRequest(url,new Response.Listener<JSONArray>() {
#Override
public void onResponse(JSONArray response) {
Log.d(TAG, response.toString());
// Parsing json
for (int i = 0; i < response.length(); i++) {
try {
JSONObject obj = response.getJSONObject(i);
ChannelItem item = new ChannelItem();
item.setTitle(obj.getString("title"));
item.setThumbnailUrl(obj.getString("image"));
// adding movie to movies array
chanellist.add(item);
} catch (JSONException e) {
e.printStackTrace();
}
}
// notifying list adapter about data changes
// so that it renders the list view with updated data
customGridview.notifyDataSetChanged();
}
}, new Response.ErrorListener() {
#Override
public void onErrorResponse(VolleyError error) {
VolleyLog.d(TAG, "Error: " + error.getMessage());
}
});
// Adding request to request queue
AppController.getInstance().addToRequestQueue(movieReq);
//------------------- Mediacontroller Visiblity-------------------------------------
player.setOnTouchListener(new View.OnTouchListener()
{
public boolean onTouch(final View paramAnonymousView, MotionEvent paramAnonymousMotionEvent)
{
if (paramAnonymousMotionEvent.getAction() == 0){
if (MainActivity.this.mediaController.getVisibility() != View.INVISIBLE) {
}
MainActivity.this.mediaController.setVisibility(View.VISIBLE);
MainActivity.this.btnHandler.postDelayed(new Runnable(){
public void run(){
MainActivity.this.mediaController.setVisibility(View.INVISIBLE);
}
}, 2000L);
}
for (;;){
return true;
}
}
});
//------FullScreen Button -----
btnFullscreen.setOnClickListener(new View.OnClickListener(){
public void onClick(View paramAnonymousView) {
Intent i = new Intent(MainActivity.this, FullScreenView.class);
startActivity(i);
}
});
//------Play Pause Button ----------
btnPlayPause.setOnClickListener(new View.OnClickListener() {
public void onClick(View paramAnonymousView){
if ( (player != null) && (MainActivity.this.player.isPlaying()) ){
MainActivity.this.player.pause();
MainActivity.this.btnPlayPause.setBackgroundResource(R.drawable.btn_play);
return;
}
MainActivity.this.player.start();
MainActivity.this.btnPlayPause.setBackgroundResource(R.drawable.btn_pause);
return;
}
});
//----------------------------------------
try {
MediaController mController = new MediaController(MainActivity.this);
mController.setAnchorView(player);
Uri video = Uri.parse(videourl);
player.setMediaController(mController);
player.setVideoURI(video);
} catch (Exception e) {
Log.e("Error", e.getMessage());
e.printStackTrace();
}
player.setMediaController(null);
player.requestFocus();
player.setOnPreparedListener(new MediaPlayer.OnPreparedListener() {
#Override
public void onPrepared(MediaPlayer arg0) {
player.start();
hidespinner();
}
});
}
// ------------ Header Gridview ----------------
#SuppressLint({"InflateParams", "SetTextI18n"})
private void setGridViewHeaderAndFooter() {
LayoutInflater layoutInflater = LayoutInflater.from(this);
View headerView = layoutInflater.inflate(R.layout.grid_header, null, false);
//locate views
TextView headerText = (TextView)headerView.findViewById(R.id.textViewheader);
headerText.setText("Suggestion");
headerView.setOnClickListener(onClickListener(0));
grid.addHeaderView(headerView);
}
private View.OnClickListener onClickListener(final int i) {
return new View.OnClickListener() {
#Override
public void onClick(View v) {
if (i == 0) {
// Toast.makeText(MainActivity.this, "Header Clicked!", Toast.LENGTH_SHORT).show();
} else {
// Toast.makeText(MainActivity.this, "Footer Clicked!", Toast.LENGTH_SHORT).show();
}
}
};
}
#Override
public void onDestroy() {
super.onDestroy();
hidespinner();
}
private void hidespinner() {
if (spinner != null) {
spinner.setVisibility(View.INVISIBLE);
spinner = null;
}
}
}
When opening starting the app you need to get the data and store on a variable or into database.
Create a ChannelList type List (List<ChannelList>) and store ChannelList data into it.
List<ChannelList> list = new ArrayList<>(); // containing all data
You can store Title, VideoUrl, iconUrl and add it to the list.
When clicking on a List Item you will get the position by using setOnItemClickListener.
And then use the position to get the clicked ChannelList position.
Suppose your list type variable is channelList.
listView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
#Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
ChannelList channelList= list.get(position);
// now you have all data of clicked ChannelList
// do whatever you like
//channelList.getVideoUrl(); etc as your getter method
}
}
});
For more about List, you can check it Here