iam fairly new to android development, so what iam trying to make is app that can show pdf from url,
I want to show progress bar while pdf file is loading from web(some pdf files are big over 15mb) How can i do that?
iam using com.github.barteksc.pdfviewer.PDFView to show pdf from web
here is my pdf show activity
private PDFView mPDFview;
private String mStoreId;
private FirebaseDatabase mFirebaseDatabase;
private DatabaseReference mReference;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_flyer);
mFirebaseDatabase = FirebaseDatabase.getInstance();
mReference = mFirebaseDatabase.getReference("Store");
if (getIntent()!=null)
{
mStoreId = getIntent().getStringExtra("StoreId");
}
if (!mStoreId.isEmpty())
{
getUrlStoreFlyer(mStoreId);
}
}
private void getUrlStoreFlyer(String storeId) {
mReference.child(storeId).addValueEventListener(new ValueEventListener()
{
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
Store storeChain = dataSnapshot.getValue(Store.class);
String pdfUrl = storeChain.getFlyerPDF().toString();
mPDFview = findViewById(R.id.flyer_pdfView);
new RetrievePDFStream().execute(pdfUrl);
}
#Override
public void onCancelled(DatabaseError databaseError) {
}
});
}
class RetrievePDFStream extends AsyncTask<String, Void, InputStream>
{
#Override
protected InputStream doInBackground(String... strings)
{
InputStream inputStream = null;
try{
URL url = new URL(strings[0]);
HttpURLConnection urlConnection = (HttpURLConnection)url.openConnection();
if (urlConnection.getResponseCode()==200)
{
inputStream = new BufferedInputStream(urlConnection.getInputStream());
}
}
catch (IOException e)
{
return null;
}
return inputStream;
}
#Override
protected void onPostExecute(InputStream inputStream) {
mPDFview.fromStream(inputStream).load();
}
}
#Override
public void onBackPressed() {
finish();
overridePendingTransition(0, 0);
}
}
Here is my xml
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context="com.test.FlyerActivity">
<ProgressBar
android:layout_width="50dp"
android:layout_height="50dp"
android:layout_alignParentBottom="true"
android:layout_centerHorizontal="true"
android:layout_marginBottom="150dp"
android:id="#+id/progressBar2" />
<com.github.barteksc.pdfviewer.PDFView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:id="#+id/flyer_pdfView"/>
enter code here
</RelativeLayout>
Here is what i used and worked perfect:
#Override
protected void onPostExecute(InputStream inputStream) {
mPDFview.fromStream(inputStream).onLoad(new OnLoadCompleteListener() {
#Override
public void loadComplete(int nbPages) {
ProgressBar progressBar = (ProgressBar) findViewById(R.id.progressBar2);
progressBar.setVisibility(View.GONE);
}
}).load();
}
private PDFView mPDFview;
private String mStoreId;
//add progressbar
private ProgressBar progressBar;
private FirebaseDatabase mFirebaseDatabase;
private DatabaseReference mReference;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_flyer);
//initialize
progressBar = (ProgressBar) findViewById(R.id.progressBar);
mFirebaseDatabase = FirebaseDatabase.getInstance();
mReference = mFirebaseDatabase.getReference("Store");
if (getIntent()!=null)
{
mStoreId = getIntent().getStringExtra("StoreId");
}
if (!mStoreId.isEmpty())
{
getUrlStoreFlyer(mStoreId);
}
}
private void getUrlStoreFlyer(String storeId) {
mReference.child(storeId).addValueEventListener(new ValueEventListener()
{
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
Store storeChain = dataSnapshot.getValue(Store.class);
String pdfUrl = storeChain.getFlyerPDF().toString();
mPDFview = findViewById(R.id.flyer_pdfView);
new RetrievePDFStream().execute(pdfUrl);
}
#Override
public void onCancelled(DatabaseError databaseError) {
}
});
}
class RetrievePDFStream extends AsyncTask<String, Void, InputStream>
{
#Override
protected void onPExecute(InputStream inputStream) {
progressBar.setVisibility(View.VISIBLE);
}
#Override
protected InputStream doInBackground(String... strings)
{
InputStream inputStream = null;
try{
URL url = new URL(strings[0]);
HttpURLConnection urlConnection = (HttpURLConnection)url.openConnection();
if (urlConnection.getResponseCode()==200)
{
inputStream = new BufferedInputStream(urlConnection.getInputStream());
}
}
catch (IOException e)
{
return null;
}
return inputStream;
}
#Override
protected void onPostExecute(InputStream inputStream) {
mPDFview.fromStream(inputStream).load();
progressBar.setVisibility(View.GONE);
}
}
#Override
public void onBackPressed() {
finish();
overridePendingTransition(0, 0);
progressBar.setVisibility(View.GONE);
}
}
Since you are using a library to load PDF from input stream, here is how it can be done.
Just before you execute the Async Task make the progress bar visible and PDFView invisible.
progressBar = findViewById(R.id.progressBar2);
mPDFview = findViewById(R.id.flyer_pdfView);
progressBar.setVisibility(View.VISIBLE);
mPDFview.setVisibility(View.INVISIBLE);
new RetrievePDFStream().execute(pdfUrl);
In onPostExecute() of the AsyncTask is where you do the UI operation after the Network call is complete. So here, you ll have to make the PDFView visible and progressBar invisible, but also since you are making a network operation and then streaming that to PDFView, PDFView will also take time to stream the content. I looked up the library that you are using and I believe it has a function called onLoad(onLoadCompleteListener), you can use this function along with the fromStream() to make the progress bar invisible and pdfView visible.
#Override
protected void onPostExecute(InputStream inputStream) {
mPDFview.fromStream(inputStream).onLoad(this).load();
}
#Override
public void loadComplete(int nbPages) {
progressBar.setVisibilitiy(INVISIBLE);
mPDFView.setVisibility(VISIBLE);
}
Alternatively, Since you are using a library that can actually load PDF from an URI,you need not use Async Task at all.
Just call PDFView.fromUri(uri).onLoad(this).load();
Related
help guys how to display image without using a button, I tried to put it on create but not working and I tried to make it as a function but still not working,but when in button (on click) it show image. I want to show the image without clicking the button.
I want to load the image without clicking the button, so when the user come the image automatically load without push of a button.
public class MainActivity extends AppCompatActivity {
TextView textViewdatashow;
EditText editTextvalue;
ImageView imageView;
Button buttonfetch;
String url ;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
textViewdatashow = (TextView) findViewById(R.id.tvshowdata);
editTextvalue = (EditText) findViewById(R.id.etvalue);
imageView = (ImageView) findViewById(R.id.image);
buttonfetch = (Button) findViewById(R.id.buttonfetchdata);
buttonfetch.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
String id = editTextvalue.getText().toString();
url = "https://PASTE_YOUR_IMAGE_URL"+id+".jpg";
getData();
}
});
}
private void getData() {
String id = editTextvalue.getText().toString().trim();
if (id.equals("")) {
Toast.makeText(this, "Check Detail!", Toast.LENGTH_LONG).show();
return;
}
String url = Config.DATA_URL + editTextvalue.getText().toString().trim();
StringRequest stringRequest = new StringRequest(url, new Response.Listener<String>() {
#Override
public void onResponse(String response) {
showJSONS(response);
}
},
new Response.ErrorListener() {
#Override
public void onErrorResponse(VolleyError error) {
Toast.makeText(MainActivity.this, error.getMessage().toString(), Toast.LENGTH_LONG).show();
}
});
RequestQueue requestQueue = Volley.newRequestQueue(this);
requestQueue.add(stringRequest);
}
private void showJSONS(String response) {
String name = "";
try {
JSONObject jsonObject = new JSONObject(response);
JSONArray result = jsonObject.getJSONArray(Config.JSON_ARRAY);
JSONObject collegeData = result.getJSONObject(0);
name = collegeData.getString(Config.KEY_NAME);
} catch (JSONException e) {
e.printStackTrace();
}
textViewdatashow.setText("" + name);
ImageRetriveWithPicasso();
}
private void ImageRetriveWithPicasso() {
Picasso.get()
.load(url)
.placeholder(R.drawable.imageholder)
.into(imageView);
}
}
Put this code inside on create view
final Handler myHandler = new
Handler(Looper.getMainLooper());
new Thread(new Runnable() {
#Override
public void run() {
myHandler.post(new Runnable() {
#Override
public void run() {
getData()
}
});
}
})).start();
}
I'm new to android studio and I'm trying to create a simple weather app using OpenWeatherMap API. I am using OkHttp library to perform a GET request. All it does is take an input throught EditText and update the TextView on button click using a Button.
But the problem is, the TextView updates after two clicks on the Button. I want to update it right after the first click. So, how do I go over this?
Here is my code:
public class MainActivity extends AppCompatActivity {
private EditText cityName;
private TextView weatherData;
private TextView hiddenText;
private Button getBtn;
public String s = "";
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
weatherData = (TextView)findViewById(R.id.weatherText);
getBtn = (Button)findViewById(R.id.getData);
cityName = (EditText)findViewById(R.id.cityName);
getBtn.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
getWeatherData(cityName.getText().toString());
weatherData.setText(s);
}
});
}
public void getWeatherData(String cityText){
String url = "https://api.openweathermap.org/data/2.5/weather?q=" + cityText + "&appid=ba45ceb57328448f7wd666hdc6d57aaf";
OkHttpClient client = new OkHttpClient();
final Request request = new Request.Builder().url(url).build();
client.newCall(request).enqueue(new Callback() {
#Override
public void onFailure(Call call, IOException e) {
MainActivity.this.runOnUiThread(new Runnable() {
#Override
public void run() {
s = "Something went wrong!";
}
});
}
#Override
public void onResponse(Call call, final Response response) throws IOException {
if(response.isSuccessful()){
MainActivity.this.runOnUiThread(new Runnable() {
#Override
public void run() {
try{
s = response.body().string();
}
catch (IOException ioe){
s = "Error while getting JSON.";
}
}
});
}
}
});
}
}
I know that I can update the TextView in onResponse itself but I wanna know if it is possible to update it through onClickListener. If it's not possible, which method should I use? Any help would be appreciated.
you have to update text value in server response call back
public class MainActivity extends AppCompatActivity {
private EditText cityName;
private TextView weatherData;
private TextView hiddenText;
private Button getBtn;
public String s = "";
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
weatherData = (TextView)findViewById(R.id.weatherText);
getBtn = (Button)findViewById(R.id.getData);
cityName = (EditText)findViewById(R.id.cityName);
getBtn.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
getWeatherData(cityName.getText().toString());
}
});
}
public void getWeatherData(String cityText){
String url = "https://api.openweathermap.org/data/2.5/weather?q=" + cityText + "&appid=ba45ceb57328448f7wd666hdc6d57aaf";
OkHttpClient client = new OkHttpClient();
final Request request = new Request.Builder().url(url).build();
client.newCall(request).enqueue(new Callback() {
#Override
public void onFailure(Call call, IOException e) {
MainActivity.this.runOnUiThread(new Runnable() {
#Override
public void run() {
s = "Something went wrong!";
}
});
}
#Override
public void onResponse(Call call, final Response response) throws IOException {
if(response.isSuccessful()){
MainActivity.this.runOnUiThread(new Runnable() {
#Override
public void run() {
try{
s = response.body().string();
weatherData.setText(s);
}
catch (IOException ioe){
s = "Error while getting JSON.";
}
}
});
}
}
});
}
}
You are setting data on edit text on click after calling GET Request.
Update the textview with the data , once you get the response.
public class MainActivity extends AppCompatActivity {
private EditText cityName;
private TextView weatherData;
private TextView hiddenText;
private Button getBtn;
public String s = "";
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
weatherData = (TextView)findViewById(R.id.weatherText);
getBtn = (Button)findViewById(R.id.getData);
cityName = (EditText)findViewById(R.id.cityName);
getBtn.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
getWeatherData(cityName.getText().toString());
}
});
}
public void getWeatherData(String cityText){
String url = "https://api.openweathermap.org/data/2.5/weather?q=" + cityText + "&appid=ba45ceb57328448f7wd666hdc6d57aaf";
OkHttpClient client = new OkHttpClient();
final Request request = new Request.Builder().url(url).build();
client.newCall(request).enqueue(new Callback() {
#Override
public void onFailure(Call call, IOException e) {
MainActivity.this.runOnUiThread(new Runnable() {
#Override
public void run() {
s = "Something went wrong!";
}
});
}
#Override
public void onResponse(Call call, final Response response) throws IOException {
if(response.isSuccessful()){
MainActivity.this.runOnUiThread(new Runnable() {
#Override
public void run() {
try{
s = response.body().string();
weatherData.setText(s);
}
catch (IOException ioe){
s = "Error while getting JSON.";
}
}
});
}
}
});
}
}
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);
}
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));
I keep a school project dealing with a ListView filled with images hosted on a server.
When someone selects an image from the list, this is shown by "original" size in another layout and even here everything went well.
But also ask when the image display have the option to save it to the SD Card and that's the part I can not do.
This is the code I did:
public class MainActivity extends AppCompatActivity {
private ListView listView;
private ProgressDialog progressDialog;
ArrayList asuntos=new ArrayList();
ArrayList imagen=new ArrayList();
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Toolbar toolBar = (Toolbar) findViewById(R.id.toolbar);
setSupportActionBar(toolBar);
listView=(ListView) findViewById(R.id.list);
progressDialog = new ProgressDialog(this);
progressDialog.setCancelable(false);
lista o=new lista();
o.obtenerAvisos();
}
public class lista {
public void obtenerAvisos() {
asuntos.clear();
imagen.clear();
String tag_string_req = "req_data";
progressDialog.setMessage("Conectando...");
showDialog();
StringRequest strReq = new StringRequest(Request.Method.POST, AppURLs.URL, new Response.Listener<String>() {
public void onResponse(String response) {
hideDialog();
try {
JSONArray jsonArray = new JSONArray(response);
for (int i = 0; i < jsonArray.length(); i++) {
asuntos.add(jsonArray.getJSONObject(i).getString("asunto"));
imagen.add(jsonArray.getJSONObject(i).getString("publicacion"));
}
listView.setAdapter(new ImagenAdaptador(getApplicationContext()));
} catch (JSONException e) {
e.printStackTrace();
}
}
}, new Response.ErrorListener() {
public void onErrorResponse(VolleyError error) {
Toast.makeText(getApplicationContext(), error.getMessage(), Toast.LENGTH_LONG).show();
hideDialog();
}
}) {
protected Map<String, String> getParams() {
Map<String, String> params = new HashMap<String, String>();
params.put("tag", "data");
return params;
}
};
AppController.getInstance().addToRequestQueue(strReq, tag_string_req);
}
}
private void showDialog() {
if (!progressDialog.isShowing())
progressDialog.show();
}
private void hideDialog() {
if (progressDialog.isShowing())
progressDialog.dismiss();
}
public class ImagenAdaptador extends BaseAdapter {
Context ctx;
LayoutInflater layoutInflater;
SmartImageView smartImageView;
TextView tvasunto;
public ImagenAdaptador(Context applicationContext) {
this.ctx=applicationContext;
layoutInflater=(LayoutInflater)ctx.getSystemService(LAYOUT_INFLATER_SERVICE);
}
public int getCount() {
return imagen.size();
}
public Object getItem(int position) {
return position;
}
public long getItemId(int position) {
return position;
}
public View getView(int position, View convertView, ViewGroup parent) {
ViewGroup viewGroup=(ViewGroup) layoutInflater.inflate(R.layout.activity_main_items,null);
smartImageView=(SmartImageView)viewGroup.findViewById(R.id.imagen1);
tvasunto=(TextView) viewGroup.findViewById(R.id.tvAsunto);
final String urlfinal="http://192.168.43.45/InfoTec/publicaciones/"+imagen.get(position).toString();
Rect rect=new Rect(smartImageView.getLeft(), smartImageView.getTop(), smartImageView.getRight(), smartImageView.getBottom());
smartImageView.setImageUrl(urlfinal, rect);
tvasunto.setText(asuntos.get(position).toString());
listView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
Intent intent = new Intent(MainActivity.this, Visor.class);
intent.putExtra("arg", asuntos.get(position).toString());
intent.putExtra("arg2",imagen.get(position).toString());
startActivity(intent);
}
});
return viewGroup;
}
}
}
This part works, but this class is the problem:
public class Visor extends AppCompatActivity {
TextView tvasunto2;
SmartImageView smartImageView2;
Button descarga;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_visor);
String original=getIntent().getStringExtra("arg");
String imgOriginal=getIntent().getStringExtra("arg2");
tvasunto2=(TextView) findViewById(R.id.tvAsunto2);
smartImageView2=(SmartImageView) findViewById(R.id.imagen2);
descarga=(Button) this.findViewById(R.id.button);
tvasunto2.setText(original);
String url="http://192.168.43.45/InfoTec/publicaciones/"+imgOriginal;
Rect rect=new Rect(smartImageView2.getLeft(), smartImageView2.getTop(), smartImageView2.getRight(), smartImageView2.getBottom());
smartImageView2.setImageUrl(url,rect);
descarga.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
}
});
}
}
If the selected image is displayed, but not now how to handle the data in the event the download button.
What would be the solution?
First, you need to get your Bitmap. You can already have it as an object Bitmap, or you can try to get it from the ImageView such as:
BitmapDrawable drawable = (BitmapDrawable) mImageView1.getDrawable();
Bitmap bitmap = drawable.getBitmap();
Then you must get to directory (a File object) from SD Card such as:
File sdCardDirectory = Environment.getExternalStorageDirectory();
Next, create your specific file for image storage:
File image = new File(sdCardDirectory, "test.png");
After that, you just have to write the Bitmap thanks to its method compress such as:
boolean success = false;
// Encode the file as a PNG image.
FileOutputStream outStream;
try {
outStream = new FileOutputStream(image);
bitmap.compress(Bitmap.CompressFormat.PNG, 100, outStream);
/* 100 to keep full quality of the image */
outStream.flush();
outStream.close();
success = true;
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
Finally, just deal with the boolean result if needed. Such as:
if (success) {
Toast.makeText(getApplicationContext(), "Image saved with success",
Toast.LENGTH_LONG).show();
} else {
Toast.makeText(getApplicationContext(),
"Error during image saving", Toast.LENGTH_LONG).show();
}
Don't forget to add the following permission in your Manifest:
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
It will be better to create a Dialog to let the user select where they want the photo to be store at. Remember there are a ton of android devices and they might vary.