package org.marcinzelent.liberavem;
import android.content.Context;
import android.net.Uri;
import android.os.Bundle;
import android.support.v4.app.Fragment;
import android.text.Html;
import android.text.Spanned;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.TextView;
import org.jetbrains.annotations.Nullable;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
/**
* A simple {@link Fragment} subclass.
* Activities that contain this fragment must implement the
* {@link AboutFragment.OnFragmentInteractionListener} interface
* to handle interaction events.
* Use the {@link AboutFragment#newInstance} factory method to
* create an instance of this fragment.
*/
public class AboutFragment extends Fragment {
// TODO: Rename parameter arguments, choose names that match
// the fragment initialization parameters, e.g. ARG_ITEM_NUMBER
private static final String ARG_PARAM1 = "param1";
private static final String ARG_PARAM2 = "param2";
// TODO: Rename and change types of parameters
private String mParam1;
private String mParam2;
private OnFragmentInteractionListener mListener;
public AboutFragment() {
// Required empty public constructor
}
/**
* Use this factory method to create a new instance of
* this fragment using the provided parameters.
*
* @param param1 Parameter 1.
* @param param2 Parameter 2.
* @return A new instance of fragment AboutFragment.
*/
// TODO: Rename and change types and number of parameters
public static AboutFragment newInstance(String param1, String param2) {
AboutFragment fragment = new AboutFragment();
Bundle args = new Bundle();
args.putString(ARG_PARAM1, param1);
args.putString(ARG_PARAM2, param2);
fragment.setArguments(args);
return fragment;
}
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
if (getArguments() != null) {
mParam1 = getArguments().getString(ARG_PARAM1);
mParam2 = getArguments().getString(ARG_PARAM2);
}
((MainActivity) getActivity()).setActionBarTitle("About");
}
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
// Inflate the layout for this fragment
return inflater.inflate(R.layout.fragment_about, container, false);
}
@Override
public void onViewCreated(View view, @Nullable Bundle savedInstanceState) {
InputStream inputStream = this.getResources().openRawResource(R.raw.gpl_3);
InputStreamReader inputreader = new InputStreamReader(inputStream);
BufferedReader buffreader = new BufferedReader(inputreader);
String line;
StringBuilder text = new StringBuilder();
try {
while (( line = buffreader.readLine()) != null) {
text.append(line);
text.append('\n');
}
} catch (IOException e) { }
Spanned license = Html.fromHtml(text.toString());
TextView aboutLicense = view.findViewById(R.id.about_license);
aboutLicense.setText(license);
}
// TODO: Rename method, update argument and hook method into UI event
public void onButtonPressed(Uri uri) {
if (mListener != null) {
mListener.onFragmentInteraction(uri);
}
}
@Override
public void onAttach(Context context) {
super.onAttach(context);
if (context instanceof OnFragmentInteractionListener) {
mListener = (OnFragmentInteractionListener) context;
} else {
throw new RuntimeException(context.toString()
+ " must implement OnFragmentInteractionListener");
}
}
@Override
public void onDetach() {
super.onDetach();
mListener = null;
}
/**
* This interface must be implemented by activities that contain this
* fragment to allow an interaction in this fragment to be communicated
* to the activity and potentially other fragments contained in that
* activity.
*
* See the Android Training lesson Communicating with Other Fragments for more information.
*/
public interface OnFragmentInteractionListener {
// TODO: Update argument type and name
void onFragmentInteraction(Uri uri);
}
}
X-Content-Type-Options: nosniff
Content-Security-Policy: default-src 'none'
Content-Type: text/plain; charset=UTF-8
Content-Length: 3067
Content-Disposition: inline; filename="AllObservationsFragment.java"
Last-Modified: Wed, 02 Jul 2025 15:06:55 GMT
Expires: Wed, 02 Jul 2025 15:11:55 GMT
ETag: "b54227c6f78e96da77a2504b18157837e24ad77b"
package org.marcinzelent.liberavem;
import android.content.Intent;
import android.os.Bundle;
import android.support.v4.app.Fragment;
import android.support.v4.widget.SwipeRefreshLayout;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.AdapterView;
import android.widget.ArrayAdapter;
import android.widget.ListView;
import android.widget.Toast;
import com.android.volley.Request;
import com.android.volley.RequestQueue;
import com.android.volley.Response;
import com.android.volley.VolleyError;
import com.android.volley.toolbox.StringRequest;
import com.android.volley.toolbox.Volley;
import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
import org.jetbrains.annotations.Nullable;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Locale;
import java.util.TimeZone;
/**
* A simple {@link Fragment} subclass.
*/
public class AllObservationsFragment extends Fragment {
public AllObservationsFragment() {
// Required empty public constructor
}
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View rootView = inflater.inflate(R.layout.observations_list, container, false);
return rootView;
}
@Override
public void onViewCreated(View view, @Nullable Bundle savedInstanceState) {
final SwipeRefreshLayout sfl = view.findViewById(R.id.swiperefresh);
sfl.setOnRefreshListener(
new SwipeRefreshLayout.OnRefreshListener() {
@Override
public void onRefresh() {
DataKeeper.getInstance().downloadData(getActivity());
sfl.setRefreshing(false);
}
}
);
DataKeeper.getInstance().addFragment(this);
DataKeeper.getInstance().downloadData(getActivity());
}
public void populateList(final Observation[] observations, final Bird[] birds) {
final ListView observationsListView = getView().findViewById(R.id.observations_list_view);
observationsListView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
@Override
public void onItemClick(AdapterView> arg0, View arg1, int position, long arg3) {
Intent detailsIntent = new Intent(getActivity(), ObservationDetailsActivity.class);
detailsIntent.putExtra("Observation", observations[position]);
String photoUrl = "";
for (Bird bird : birds)
if (bird.getId() == observations[position].getBirdId())
photoUrl = bird.getPhotoUrl();
detailsIntent.putExtra("Photo", photoUrl);
startActivity(detailsIntent);
}
});
final ObservationsListAdapter adapter = new ObservationsListAdapter(getActivity(), observations, birds);
observationsListView.setAdapter(adapter);
}
}
X-Content-Type-Options: nosniff
Content-Security-Policy: default-src 'none'
Content-Type: text/plain; charset=UTF-8
Content-Length: 3000
Content-Disposition: inline; filename="AppCompatPreferenceActivity.java"
Last-Modified: Wed, 02 Jul 2025 15:06:55 GMT
Expires: Wed, 02 Jul 2025 15:11:55 GMT
ETag: "f63b0b5b1faed8476f19a0b10c615a081b107db0"
package org.marcinzelent.liberavem;
import android.content.res.Configuration;
import android.os.Bundle;
import android.preference.PreferenceActivity;
import android.support.annotation.LayoutRes;
import android.support.annotation.Nullable;
import android.support.v7.app.ActionBar;
import android.support.v7.app.AppCompatDelegate;
import android.support.v7.widget.Toolbar;
import android.view.MenuInflater;
import android.view.View;
import android.view.ViewGroup;
/**
* A {@link android.preference.PreferenceActivity} which implements and proxies the necessary calls
* to be used with AppCompat.
*/
public abstract class AppCompatPreferenceActivity extends PreferenceActivity {
private AppCompatDelegate mDelegate;
@Override
protected void onCreate(Bundle savedInstanceState) {
getDelegate().installViewFactory();
getDelegate().onCreate(savedInstanceState);
super.onCreate(savedInstanceState);
}
@Override
protected void onPostCreate(Bundle savedInstanceState) {
super.onPostCreate(savedInstanceState);
getDelegate().onPostCreate(savedInstanceState);
}
public ActionBar getSupportActionBar() {
return getDelegate().getSupportActionBar();
}
public void setSupportActionBar(@Nullable Toolbar toolbar) {
getDelegate().setSupportActionBar(toolbar);
}
@Override
public MenuInflater getMenuInflater() {
return getDelegate().getMenuInflater();
}
@Override
public void setContentView(@LayoutRes int layoutResID) {
getDelegate().setContentView(layoutResID);
}
@Override
public void setContentView(View view) {
getDelegate().setContentView(view);
}
@Override
public void setContentView(View view, ViewGroup.LayoutParams params) {
getDelegate().setContentView(view, params);
}
@Override
public void addContentView(View view, ViewGroup.LayoutParams params) {
getDelegate().addContentView(view, params);
}
@Override
protected void onPostResume() {
super.onPostResume();
getDelegate().onPostResume();
}
@Override
protected void onTitleChanged(CharSequence title, int color) {
super.onTitleChanged(title, color);
getDelegate().setTitle(title);
}
@Override
public void onConfigurationChanged(Configuration newConfig) {
super.onConfigurationChanged(newConfig);
getDelegate().onConfigurationChanged(newConfig);
}
@Override
protected void onStop() {
super.onStop();
getDelegate().onStop();
}
@Override
protected void onDestroy() {
super.onDestroy();
getDelegate().onDestroy();
}
public void invalidateOptionsMenu() {
getDelegate().invalidateOptionsMenu();
}
private AppCompatDelegate getDelegate() {
if (mDelegate == null) {
mDelegate = AppCompatDelegate.create(this, null);
}
return mDelegate;
}
}
X-Content-Type-Options: nosniff
Content-Security-Policy: default-src 'none'
Content-Type: text/plain; charset=UTF-8
Content-Length: 4041
Content-Disposition: inline; filename="AtlasFragment.java"
Last-Modified: Wed, 02 Jul 2025 15:06:55 GMT
Expires: Wed, 02 Jul 2025 15:11:55 GMT
ETag: "f59ff6bec351a4e7ab0f818ade1299ec38fdf90c"
package org.marcinzelent.liberavem;
import android.content.Context;
import android.net.Uri;
import android.os.Bundle;
import android.support.v4.app.Fragment;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.GridView;
import org.jetbrains.annotations.Nullable;
/**
* A simple {@link Fragment} subclass.
* Activities that contain this fragment must implement the
* {@link AtlasFragment.OnFragmentInteractionListener} interface
* to handle interaction events.
* Use the {@link AtlasFragment#newInstance} factory method to
* create an instance of this fragment.
*/
public class AtlasFragment extends Fragment {
// TODO: Rename parameter arguments, choose names that match
// the fragment initialization parameters, e.g. ARG_ITEM_NUMBER
private static final String ARG_PARAM1 = "param1";
private static final String ARG_PARAM2 = "param2";
// TODO: Rename and change types of parameters
private String mParam1;
private String mParam2;
private OnFragmentInteractionListener mListener;
public AtlasFragment() {
// Required empty public constructor
}
/**
* Use this factory method to create a new instance of
* this fragment using the provided parameters.
*
* @param param1 Parameter 1.
* @param param2 Parameter 2.
* @return A new instance of fragment AtlasFragment.
*/
// TODO: Rename and change types and number of parameters
public static AtlasFragment newInstance(String param1, String param2) {
AtlasFragment fragment = new AtlasFragment();
Bundle args = new Bundle();
args.putString(ARG_PARAM1, param1);
args.putString(ARG_PARAM2, param2);
fragment.setArguments(args);
return fragment;
}
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
if (getArguments() != null) {
mParam1 = getArguments().getString(ARG_PARAM1);
mParam2 = getArguments().getString(ARG_PARAM2);
}
((MainActivity) getActivity()).setActionBarTitle("Atlas");
}
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
// Inflate the layout for this fragment
return inflater.inflate(R.layout.fragment_atlas, container, false);
}
// TODO: Rename method, update argument and hook method into UI event
public void onButtonPressed(Uri uri) {
if (mListener != null) {
mListener.onFragmentInteraction(uri);
}
}
@Override
public void onViewCreated(View view, @Nullable Bundle savedInstanceState) {
GridView atlasGrid = view.findViewById(R.id.atlas_grid);
atlasGrid.setAdapter(new AtlasGridAdapter(getActivity(), DataKeeper.getInstance().getBirds()));
}
@Override
public void onAttach(Context context) {
super.onAttach(context);
if (context instanceof OnFragmentInteractionListener) {
mListener = (OnFragmentInteractionListener) context;
} else {
throw new RuntimeException(context.toString()
+ " must implement OnFragmentInteractionListener");
}
}
@Override
public void onDetach() {
super.onDetach();
mListener = null;
}
/**
* This interface must be implemented by activities that contain this
* fragment to allow an interaction in this fragment to be communicated
* to the activity and potentially other fragments contained in that
* activity.
*
* See the Android Training lesson Communicating with Other Fragments for more information.
*/
public interface OnFragmentInteractionListener {
// TODO: Update argument type and name
void onFragmentInteraction(Uri uri);
}
}
X-Content-Type-Options: nosniff
Content-Security-Policy: default-src 'none'
Content-Type: text/plain; charset=UTF-8
Content-Length: 1825
Content-Disposition: inline; filename="AtlasGridAdapter.java"
Last-Modified: Wed, 02 Jul 2025 15:06:55 GMT
Expires: Wed, 02 Jul 2025 15:11:55 GMT
ETag: "0aa1ca5c7b27d6e1349ceab4646c6df59905618a"
package org.marcinzelent.liberavem;
import android.content.Context;
import android.support.v7.widget.RecyclerView;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.BaseAdapter;
import android.widget.ImageView;
import android.widget.TextView;
import com.squareup.picasso.Picasso;
public class AtlasGridAdapter extends BaseAdapter {
private Context mContext;
private Bird[] birds;
public AtlasGridAdapter(Context c, Bird[] b) {
mContext = c;
birds = b;
}
public int getCount() {
return birds.length;
}
public Object getItem(int position) {
return null;
}
public long getItemId(int position) {
return 0;
}
// create a new ImageView for each item referenced by the Adapter
public View getView(int position, View convertView, ViewGroup parent) {
ViewHolder viewHolder;
final View result;
if (convertView == null) {
viewHolder = new ViewHolder();
LayoutInflater inflater = LayoutInflater.from(mContext);
convertView = inflater.inflate(R.layout.atlas_grid_item, parent, false);
viewHolder.photo = convertView.findViewById(R.id.atlas_photo);
viewHolder.name = convertView.findViewById(R.id.atlas_name);
result = convertView;
convertView.setTag(viewHolder);
} else {
viewHolder = (ViewHolder) convertView.getTag();
result = convertView;
}
Picasso.get().load(birds[position].getPhotoUrl()).into(viewHolder.photo);
viewHolder.name.setText(birds[position].getNameEnglish());
return convertView;
}
private static class ViewHolder {
ImageView photo;
TextView name;
}
}
X-Content-Type-Options: nosniff
Content-Security-Policy: default-src 'none'
Content-Type: text/plain; charset=UTF-8
Content-Length: 1142
Content-Disposition: inline; filename="Bird.java"
Last-Modified: Wed, 02 Jul 2025 15:06:55 GMT
Expires: Wed, 02 Jul 2025 15:11:55 GMT
ETag: "a94faf32f97ec8043572ec9c5c520f00b8165ca9"
package org.marcinzelent.liberavem;
import com.google.gson.annotations.SerializedName;
import java.io.Serializable;
public class Bird implements Serializable {
@SerializedName("Id")
private int id;
@SerializedName("Created")
private String created;
@SerializedName("NameEnglish")
private String nameEnglish;
@SerializedName("NameDanish")
private String nameDanish;
@SerializedName("PhotoUrl")
private String photoUrl;
public Bird(int id, String created, String nameEnglish, String nameDanish, String photoUrl) {
this.id = id;
this.created = created;
this.nameEnglish = nameEnglish;
this.nameDanish = nameDanish;
this.photoUrl = photoUrl;
}
public int getId() {
return id;
}
public String getCreated() {
return created;
}
public String getNameEnglish() {
return nameEnglish;
}
public String getNameDanish() {
return nameDanish;
}
public String getPhotoUrl() {
return photoUrl;
}
@Override
public String toString() {
return getNameEnglish();
}
}
X-Content-Type-Options: nosniff
Content-Security-Policy: default-src 'none'
Content-Type: text/plain; charset=UTF-8
Content-Length: 352
Content-Disposition: inline; filename="BirdPickerActivity.java"
Last-Modified: Wed, 02 Jul 2025 15:06:55 GMT
Expires: Wed, 02 Jul 2025 15:11:55 GMT
ETag: "15c38cf8685cfe9707e17860a3616361ac6065c3"
package org.marcinzelent.liberavem;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
public class BirdPickerActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_bird_picker);
}
}
X-Content-Type-Options: nosniff
Content-Security-Policy: default-src 'none'
Content-Type: text/plain; charset=UTF-8
Content-Length: 1929
Content-Disposition: inline; filename="BirdsListAdapter.java"
Last-Modified: Wed, 02 Jul 2025 15:06:55 GMT
Expires: Wed, 02 Jul 2025 15:11:55 GMT
ETag: "68896c00a6f2d645e9b5a5cd9a291597cdc413da"
package org.marcinzelent.liberavem;
import android.content.Context;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ArrayAdapter;
import android.widget.ImageView;
import android.widget.TextView;
import com.squareup.picasso.Picasso;
public class BirdsListAdapter extends ArrayAdapter {
private final Bird[] birds;
private Context mContext;
public BirdsListAdapter(Context context, Bird[] birds){
super(context, R.layout.observations_list_item);
this.mContext = context;
this.birds = birds;
}
@Override
public View getDropDownView(int position, @Nullable View convertView, @NonNull ViewGroup parent) {
return getView(position, convertView, parent);
}
@Override
public int getCount() {
return birds.length;
}
@NonNull
@Override
public View getView(int position, @Nullable View convertView, @NonNull ViewGroup parent) {
ViewHolder mViewHolder = new ViewHolder();
if (convertView == null) {
LayoutInflater mInflater = (LayoutInflater) mContext.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
convertView = mInflater.inflate(R.layout.birds_list_item, parent, false);
mViewHolder.name = convertView.findViewById(R.id.bli_name);
mViewHolder.photo = convertView.findViewById(R.id.bli_photo);
convertView.setTag(mViewHolder);
} else {
mViewHolder = (ViewHolder) convertView.getTag();
}
mViewHolder.name.setText(birds[position].getNameEnglish());
Picasso.get().load(birds[position].getPhotoUrl()).into(mViewHolder.photo);
return convertView;
}
private static class ViewHolder {
TextView name;
ImageView photo;
}
}X-Content-Type-Options: nosniff
Content-Security-Policy: default-src 'none'
Content-Type: text/plain; charset=UTF-8
Content-Length: 4749
Content-Disposition: inline; filename="DataKeeper.java"
Last-Modified: Wed, 02 Jul 2025 15:06:55 GMT
Expires: Wed, 02 Jul 2025 15:11:55 GMT
ETag: "172713d8a244e5f14383beaa9c2e87e45a034b85"
package org.marcinzelent.liberavem;
import android.app.Activity;
import android.app.Fragment;
import android.widget.Toast;
import com.android.volley.Request;
import com.android.volley.Response;
import com.android.volley.VolleyError;
import com.android.volley.toolbox.StringRequest;
import com.android.volley.toolbox.Volley;
import com.google.firebase.auth.FirebaseAuth;
import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Locale;
public class DataKeeper {
private static final DataKeeper instance = new DataKeeper();
public static DataKeeper getInstance() {
return instance;
}
private DataKeeper() {
}
private List fragments = new ArrayList();
private Bird[] birds;
private Observation[] observations;
public Bird[] getBirds() {
return birds;
}
public void setBirds(Bird[] birds) {
this.birds = birds;
}
public Observation[] getObservations() {
return observations;
}
public void setObservations(Observation[] observations) {
this.observations = observations;
}
public void downloadData(final Activity activity) {
if (birds == null) downloadBirds(activity);
downloadObservations(activity);
}
private void downloadBirds(final Activity activity) {
String birdsUrl = "http://birdobservationservice.azurewebsites.net/Service1.svc/birds";
final StringRequest birdsRequest = new StringRequest(Request.Method.GET, birdsUrl, new Response.Listener() {
@Override
public void onResponse(String response) {
Gson gson = new GsonBuilder().create();
birds = gson.fromJson(response, Bird[].class);
callPopulator(activity);
}
}, new com.android.volley.Response.ErrorListener() {
@Override
public void onErrorResponse(VolleyError error) {
Toast.makeText(activity, "Couldn't connect to the database!", Toast.LENGTH_LONG).show();
}
});
Volley.newRequestQueue(activity).add(birdsRequest);
}
private void downloadObservations(final Activity activity) {
String observationsUrl = "http://birdobservationservice.azurewebsites.net/Service1.svc/observations";
final StringRequest observationsRequest = new StringRequest(Request.Method.GET, observationsUrl, new Response.Listener() {
@Override
public void onResponse(String response) {
Gson gson = new GsonBuilder().create();
observations = gson.fromJson(response, Observation[].class);
for (Observation o : observations) {
int p = o.getCreated().indexOf('+');
long epoch = Long.parseLong(o.getCreated().substring(6, p));
Date date = new Date(epoch);
String formatted = new SimpleDateFormat("dd.MM.yyyy HH:mm", Locale.ENGLISH).format(date);
o.setCreated(formatted);
}
callPopulator(activity);
}
}, new com.android.volley.Response.ErrorListener() {
@Override
public void onErrorResponse(VolleyError error) {
Toast.makeText(activity, "Couldn't connect to the database!", Toast.LENGTH_LONG).show();
}
});
Volley.newRequestQueue(activity).add(observationsRequest);
}
public void addFragment(Object fragment) {
fragments.add(fragment);
}
public void clearFragments() {
fragments.clear();
}
private void callPopulator(Activity activity) {
if (birds != null && observations != null) {
for(Object fragment : fragments) {
if (fragment.getClass() == AllObservationsFragment.class)
((AllObservationsFragment) fragment).populateList(observations, birds);
else {
List myObservationsList = new ArrayList<>();
for (Observation o : observations) {
String uid = FirebaseAuth.getInstance().getCurrentUser().getUid();
if (o.getUserId().equals(uid)) myObservationsList.add(o);
}
Observation[] myObservations = new Observation[myObservationsList.size()];
myObservations = myObservationsList.toArray(myObservations);
((MyObservationsFragment) fragment).populateList(myObservations, birds);
}
}
}
}
}
X-Content-Type-Options: nosniff
Content-Security-Policy: default-src 'none'
Content-Type: text/plain; charset=UTF-8
Content-Length: 4444
Content-Disposition: inline; filename="LoginActivity.java"
Last-Modified: Wed, 02 Jul 2025 15:06:55 GMT
Expires: Wed, 02 Jul 2025 15:11:55 GMT
ETag: "354e786c8d44c30abf66354381eafc8337022c91"
package org.marcinzelent.liberavem;
import android.content.Intent;
import android.os.Bundle;
import android.support.annotation.NonNull;
import android.support.v7.app.AppCompatActivity;
import android.support.v7.widget.Toolbar;
import android.text.TextUtils;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;
import android.widget.ProgressBar;
import android.widget.Toast;
import com.google.android.gms.tasks.OnCompleteListener;
import com.google.android.gms.tasks.Task;
import com.google.firebase.auth.AuthResult;
import com.google.firebase.auth.FirebaseAuth;
public class LoginActivity extends AppCompatActivity {
private EditText inputEmail, inputPassword;
private FirebaseAuth auth;
private ProgressBar progressBar;
private Button btnSignup, btnLogin, btnReset;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
//Get Firebase auth instance
auth = FirebaseAuth.getInstance();
if (auth.getCurrentUser() != null) {
startActivity(new Intent(LoginActivity.this, MainActivity.class));
finish();
}
// set the view now
setContentView(R.layout.activity_login);
inputEmail = findViewById(R.id.email);
inputPassword = findViewById(R.id.password);
progressBar = findViewById(R.id.progressBar);
btnSignup = findViewById(R.id.btn_signup);
btnLogin = findViewById(R.id.btn_login);
btnReset = findViewById(R.id.btn_reset_password);
//Get Firebase auth instance
auth = FirebaseAuth.getInstance();
btnSignup.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
startActivity(new Intent(LoginActivity.this, SignupActivity.class));
}
});
btnReset.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
startActivity(new Intent(LoginActivity.this, ResetPasswordActivity.class));
}
});
btnLogin.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
String email = inputEmail.getText().toString();
final String password = inputPassword.getText().toString();
if (TextUtils.isEmpty(email)) {
Toast.makeText(getApplicationContext(), "Enter email address!", Toast.LENGTH_SHORT).show();
return;
}
if (TextUtils.isEmpty(password)) {
Toast.makeText(getApplicationContext(), "Enter password!", Toast.LENGTH_SHORT).show();
return;
}
progressBar.setVisibility(View.VISIBLE);
//authenticate user
auth.signInWithEmailAndPassword(email, password)
.addOnCompleteListener(LoginActivity.this, new OnCompleteListener() {
@Override
public void onComplete(@NonNull Task task) {
// If sign in fails, display a message to the user. If sign in succeeds
// the auth state listener will be notified and logic to handle the
// signed in user can be handled in the listener.
progressBar.setVisibility(View.GONE);
if (!task.isSuccessful()) {
// there was an error
if (password.length() < 6) {
inputPassword.setError(getString(R.string.minimum_password));
} else {
Toast.makeText(LoginActivity.this, getString(R.string.auth_failed), Toast.LENGTH_LONG).show();
}
} else {
Intent intent = new Intent(LoginActivity.this, MainActivity.class);
startActivity(intent);
finish();
}
}
});
}
});
}
}X-Content-Type-Options: nosniff
Content-Security-Policy: default-src 'none'
Content-Type: text/plain; charset=UTF-8
Content-Length: 5530
Content-Disposition: inline; filename="MainActivity.java"
Last-Modified: Wed, 02 Jul 2025 15:06:55 GMT
Expires: Wed, 02 Jul 2025 15:11:55 GMT
ETag: "37545b6c873394c1558d3a46b9243c9e0e4e0a0b"
package org.marcinzelent.liberavem;
import android.content.Intent;
import android.net.Uri;
import android.os.Bundle;
import android.support.annotation.NonNull;
import android.support.design.widget.FloatingActionButton;
import android.support.design.widget.Snackbar;
import android.support.v4.app.Fragment;
import android.support.v4.app.FragmentManager;
import android.support.v4.app.FragmentTransaction;
import android.support.v4.widget.SwipeRefreshLayout;
import android.view.View;
import android.support.design.widget.NavigationView;
import android.support.v4.view.GravityCompat;
import android.support.v4.widget.DrawerLayout;
import android.support.v7.app.ActionBarDrawerToggle;
import android.support.v7.app.AppCompatActivity;
import android.support.v7.widget.Toolbar;
import android.view.Menu;
import android.view.MenuItem;
import android.widget.AdapterView;
import android.widget.ListView;
import android.widget.Toast;
import com.android.volley.Request;
import com.android.volley.Response;
import com.android.volley.VolleyError;
import com.android.volley.toolbox.StringRequest;
import com.google.firebase.auth.FirebaseAuth;
import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
import java.util.List;
public class MainActivity extends AppCompatActivity
implements NavigationView.OnNavigationItemSelectedListener,
ObservationsFragment.OnFragmentInteractionListener,
AtlasFragment.OnFragmentInteractionListener,
AboutFragment.OnFragmentInteractionListener {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Toolbar toolbar = findViewById(R.id.toolbar);
setSupportActionBar(toolbar);
if (savedInstanceState ==null) {
Fragment fragment = null;
Class fragmentClass = null;
fragmentClass = ObservationsFragment.class;
try {
fragment = (Fragment) fragmentClass.newInstance();
} catch (Exception e) {
e.printStackTrace();
}
FragmentManager fragmentManager = getSupportFragmentManager();
fragmentManager.beginTransaction().replace(R.id.flContent, fragment).commit();
}
DrawerLayout drawer = findViewById(R.id.drawer_layout);
ActionBarDrawerToggle toggle = new ActionBarDrawerToggle(
this, drawer, toolbar, R.string.navigation_drawer_open, R.string.navigation_drawer_close);
drawer.addDrawerListener(toggle);
toggle.syncState();
NavigationView navigationView = findViewById(R.id.nav_view);
navigationView.getMenu().getItem(0).setChecked(true);
navigationView.setNavigationItemSelectedListener(this);
}
@Override
public void onBackPressed() {
DrawerLayout drawer = findViewById(R.id.drawer_layout);
if (drawer.isDrawerOpen(GravityCompat.START)) {
drawer.closeDrawer(GravityCompat.START);
} else {
super.onBackPressed();
}
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.main, menu);
return true;
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
// Handle action bar item clicks here. The action bar will
// automatically handle clicks on the Home/Up button, so long
// as you specify a parent activity in AndroidManifest.xml.
int id = item.getItemId();
//noinspection SimplifiableIfStatement
//if (id == R.id.action_search) {
// return true;
//}
return super.onOptionsItemSelected(item);
}
@SuppressWarnings("StatementWithEmptyBody")
@Override
public boolean onNavigationItemSelected(@NonNull MenuItem item) {
// Handle navigation view item clicks here.
int id = item.getItemId();
Fragment fragment = null;
Class fragmentClass = null;
if (id == R.id.nav_observations) {
fragmentClass = ObservationsFragment.class;
} else if (id == R.id.nav_atlas) {
fragmentClass = AtlasFragment.class;
} else if (id == R.id.nav_settings) {
Intent settingsIntent = new Intent(this, SettingsActivity.class);
startActivity(settingsIntent);
} else if (id == R.id.nav_about) {
fragmentClass = AboutFragment.class;
} else if (id == R.id.nav_signout) {
FirebaseAuth auth = FirebaseAuth.getInstance();
auth.signOut();
finish();
Intent intent = new Intent(this, LoginActivity.class);
startActivity(intent);
}
if (fragmentClass != null) {
try {
fragment = (Fragment) fragmentClass.newInstance();
} catch (Exception e) {
e.printStackTrace();
}
FragmentManager fragmentManager = getSupportFragmentManager();
fragmentManager.beginTransaction().replace(R.id.flContent, fragment).commit();
}
DrawerLayout drawer = findViewById(R.id.drawer_layout);
drawer.closeDrawer(GravityCompat.START);
return true;
}
@Override
public void onFragmentInteraction(Uri uri) {
}
public void setActionBarTitle(String title) {
getSupportActionBar().setTitle(title);
}
}
X-Content-Type-Options: nosniff
Content-Security-Policy: default-src 'none'
Content-Type: text/plain; charset=UTF-8
Content-Length: 2589
Content-Disposition: inline; filename="MyObservationsFragment.java"
Last-Modified: Wed, 02 Jul 2025 15:06:55 GMT
Expires: Wed, 02 Jul 2025 15:11:55 GMT
ETag: "c3656e98c51c0e42aaebd56dfe1717a0ab9fa0ad"
package org.marcinzelent.liberavem;
import android.content.Intent;
import android.os.Bundle;
import android.support.v4.app.Fragment;
import android.support.v4.widget.SwipeRefreshLayout;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.AdapterView;
import android.widget.ArrayAdapter;
import android.widget.ListView;
import android.widget.TextView;
import org.jetbrains.annotations.Nullable;
import java.util.ArrayList;
/**
* A simple {@link Fragment} subclass.
*/
public class MyObservationsFragment extends Fragment {
public MyObservationsFragment() {
// Required empty public constructor
}
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View rootView = inflater.inflate(R.layout.observations_list, container, false);
return rootView;
}
@Override
public void onViewCreated(View view, @Nullable Bundle savedInstanceState) {
final SwipeRefreshLayout sfl = view.findViewById(R.id.swiperefresh);
sfl.setOnRefreshListener(
new SwipeRefreshLayout.OnRefreshListener() {
@Override
public void onRefresh() {
DataKeeper.getInstance().downloadData(getActivity());
sfl.setRefreshing(false);
}
}
);
DataKeeper.getInstance().addFragment(this);
}
public void populateList(final Observation[] observations, final Bird[] birds) {
final ListView observationsListView = getView().findViewById(R.id.observations_list_view);
observationsListView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
@Override
public void onItemClick(AdapterView> arg0, View arg1, int position, long arg3) {
Intent detailsIntent = new Intent(getActivity(), ObservationDetailsActivity.class);
detailsIntent.putExtra("Observation", observations[position]);
String photoUrl = "";
for (Bird bird : birds)
if (bird.getId() == observations[position].getBirdId())
photoUrl = bird.getPhotoUrl();
detailsIntent.putExtra("Photo", photoUrl);
startActivity(detailsIntent);
}
});
final ObservationsListAdapter adapter = new ObservationsListAdapter(getActivity(), observations, birds);
observationsListView.setAdapter(adapter);
}
}
X-Content-Type-Options: nosniff
Content-Security-Policy: default-src 'none'
Content-Type: text/plain; charset=UTF-8
Content-Length: 8124
Content-Disposition: inline; filename="NewObservationActivity.java"
Last-Modified: Wed, 02 Jul 2025 15:06:55 GMT
Expires: Wed, 02 Jul 2025 15:11:55 GMT
ETag: "b331c01fb29d20de827bb118ed8a88d0dd930140"
package org.marcinzelent.liberavem;
import android.Manifest;
import android.content.Context;
import android.content.pm.PackageManager;
import android.location.Location;
import android.location.LocationListener;
import android.location.LocationManager;
import android.os.Bundle;
import android.provider.ContactsContract;
import android.support.v4.app.ActivityCompat;
import android.support.v7.app.AppCompatActivity;
import android.support.v7.widget.Toolbar;
import android.view.View;
import android.widget.AdapterView;
import android.widget.ArrayAdapter;
import android.widget.Button;
import android.widget.EditText;
import android.widget.Spinner;
import android.widget.Toast;
import com.android.volley.AuthFailureError;
import com.android.volley.NetworkResponse;
import com.android.volley.Request;
import com.android.volley.Response;
import com.android.volley.VolleyError;
import com.android.volley.VolleyLog;
import com.android.volley.toolbox.HttpHeaderParser;
import com.android.volley.toolbox.StringRequest;
import com.android.volley.toolbox.Volley;
import com.google.firebase.auth.FirebaseAuth;
import org.json.JSONException;
import org.json.JSONObject;
import java.io.UnsupportedEncodingException;
import java.util.Calendar;
public class NewObservationActivity extends AppCompatActivity {
private Bird selectedBird;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_new_observation);
getSupportActionBar().setDisplayHomeAsUpEnabled(true);
Button cancelButton = findViewById(R.id.new_cancel);
cancelButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
finish();
}
});
Button button = findViewById(R.id.new_add);
button.setOnClickListener(new Button.OnClickListener() {
public void onClick(View view) {
postNewObservation();
}
});
Spinner newBirdSpinner = findViewById(R.id.new_birds);
BirdsListAdapter adapter = new BirdsListAdapter(this, DataKeeper.getInstance().getBirds());
newBirdSpinner.setAdapter(adapter);
newBirdSpinner.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
@Override
public void onItemSelected(AdapterView> adapterView, View view, int i, long l) {
selectedBird = DataKeeper.getInstance().getBirds()[i];
}
@Override
public void onNothingSelected(AdapterView> adapterView) {
}
});
// Acquire a reference to the system Location Manager
LocationManager locationManager = (LocationManager) this.getSystemService(Context.LOCATION_SERVICE);
// Define a listener that responds to location updates
LocationListener locationListener = new LocationListener() {
public void onLocationChanged(Location location) {
// Called when a new location is found by the network location provider.
((EditText)findViewById(R.id.new_longitude)).setText(String.valueOf(location.getLongitude()));
((EditText)findViewById(R.id.new_latitude)).setText(String.valueOf(location.getLatitude()));
}
public void onStatusChanged(String provider, int status, Bundle extras) {
}
public void onProviderEnabled(String provider) {
}
public void onProviderDisabled(String provider) {
}
};
// Register the listener with the Location Manager to receive location updates
if (ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED
&& ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED) {
// TODO: Consider calling
// ActivityCompat#requestPermissions
// here to request the missing permissions, and then overriding
// public void onRequestPermissionsResult(int requestCode, String[] permissions,
// int[] grantResults)
// to handle the case where the user grants the permission. See the documentation
// for ActivityCompat#requestPermissions for more details.
return;
}
locationManager.requestLocationUpdates(LocationManager.NETWORK_PROVIDER, 0, 0, locationListener);
}
@Override
public boolean onSupportNavigateUp(){
finish();
return true;
}
public void postNewObservation() {
try {
JSONObject jsonBody = new JSONObject();
jsonBody.put("BirdId", selectedBird.getId());
jsonBody.put("Comment", ((EditText)findViewById(R.id.new_comment)).getText());
jsonBody.put("Created", "/Date(" + System.currentTimeMillis() + "+0000)/");
jsonBody.put("Id", "0");
jsonBody.put("Latitude", ((EditText)findViewById(R.id.new_latitude)).getText());
jsonBody.put("Longitude", ((EditText)findViewById(R.id.new_longitude)).getText());
jsonBody.put("Placename", ((EditText)findViewById(R.id.new_place)).getText());
jsonBody.put("Population", ((EditText)findViewById(R.id.new_population)).getText());
jsonBody.put("UserId", FirebaseAuth.getInstance().getCurrentUser().getUid());
jsonBody.put("NameDanish", selectedBird.getNameDanish());
jsonBody.put("NameEnglish", selectedBird.getNameEnglish());
final String requestBody = jsonBody.toString();
String url = "http://birdobservationservice.azurewebsites.net/Service1.svc/observations";
StringRequest request = new StringRequest(Request.Method.POST, url,
new Response.Listener() {
@Override
public void onResponse(String response) {
Toast.makeText(getBaseContext(), "Successfully added activity to the database!", Toast.LENGTH_LONG).show();
NewObservationActivity.this.finish();
DataKeeper.getInstance().downloadData(NewObservationActivity.this);
}
},
new Response.ErrorListener() {
@Override
public void onErrorResponse(VolleyError error) {
Toast.makeText(getBaseContext(), "Couldn't add observation to the database!", Toast.LENGTH_LONG).show();
}
}) {
@Override
public String getBodyContentType() {
return "application/json; charset=utf-8";
}
@Override
public byte[] getBody() {
try {
return requestBody == null ? null : requestBody.getBytes("utf-8");
} catch (UnsupportedEncodingException uee) {
VolleyLog.wtf("Unsupported Encoding while trying to get the bytes of %s using %s", requestBody, "utf-8");
return null;
}
}
@Override
protected Response parseNetworkResponse(NetworkResponse response) {
String responseString = "";
if (response != null) {
responseString = String.valueOf(response.statusCode);
// can get more details such as response.headers
}
return Response.success(responseString, HttpHeaderParser.parseCacheHeaders(response));
}
};
Volley.newRequestQueue(getBaseContext()).add(request);
}
catch (JSONException e) {
e.printStackTrace();
}
}
}
X-Content-Type-Options: nosniff
Content-Security-Policy: default-src 'none'
Content-Type: text/plain; charset=UTF-8
Content-Length: 3011
Content-Disposition: inline; filename="Observation.java"
Last-Modified: Wed, 02 Jul 2025 15:06:55 GMT
Expires: Wed, 02 Jul 2025 15:11:55 GMT
ETag: "1aca80bfbdda3a78174d0a97ce554a844ab83213"
package org.marcinzelent.liberavem;
import com.google.gson.annotations.SerializedName;
import java.io.Serializable;
public class Observation implements Serializable {
@SerializedName("BirdId")
private int birdId;
@SerializedName("Comment")
private String comment;
@SerializedName("Created")
private String created;
@SerializedName("Id")
private int id;
@SerializedName("Latitude")
private double latitude;
@SerializedName("Longitude")
private double longitude;
@SerializedName("Placename")
private String placeName;
@SerializedName("Population")
private int population;
@SerializedName("UserId")
private String userId;
@SerializedName("NameDanish")
private String nameDanish;
@SerializedName("NameEnglish")
private String nameEnglish;
public Observation(int id, String created, double latitude, double longitude, String placeName,
String comment, String userId, int birdId, String nameEnglish,
String nameDanish, int population) {
this.birdId = birdId;
this.comment = comment;
this.created = created;
this.id = id;
this.latitude = latitude;
this.longitude = longitude;
this.placeName = placeName;
this.population = population;
this.userId = userId;
this.nameDanish = nameDanish;
this.nameEnglish = nameEnglish;
}
public int getBirdId() {
return birdId;
}
public void setBirdId(int birdId) {
this.birdId = birdId;
}
public String getComment() {
return comment;
}
public void setComment(String comment) {
this.comment = comment;
}
public String getCreated() {
return created;
}
public void setCreated(String created) {
this.created = created;
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public double getLatitude() {
return latitude;
}
public void setLatitude(double latitude) {
this.latitude = latitude;
}
public double getLongitude() {
return longitude;
}
public void setLongitude(double longitude) {
this.longitude = longitude;
}
public String getPlaceName() {
return placeName;
}
public void setPlaceName(String placeName) {
this.placeName = placeName;
}
public int getPopulation() {
return population;
}
public void setPopulation(int population) {
this.population = population;
}
public String getUserId() {
return userId;
}
public void setUserId(String userId) {
this.userId = userId;
}
public String getNameDanish() {
return nameDanish;
}
public String getNameEnglish() {
return nameEnglish;
}
public void setNameEnglish(String nameEnglish) {
this.nameEnglish = nameEnglish;
}
}
X-Content-Type-Options: nosniff
Content-Security-Policy: default-src 'none'
Content-Type: text/plain; charset=UTF-8
Content-Length: 2136
Content-Disposition: inline; filename="ObservationDetailsActivity.java"
Last-Modified: Wed, 02 Jul 2025 15:06:55 GMT
Expires: Wed, 02 Jul 2025 15:11:55 GMT
ETag: "373fda6b4514316193b6019656c64a574829f96a"
package org.marcinzelent.liberavem;
import android.content.Intent;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.support.v7.widget.Toolbar;
import android.widget.TextView;
import com.squareup.picasso.Picasso;
public class ObservationDetailsActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_observation_details);
getSupportActionBar().setDisplayHomeAsUpEnabled(true);
Intent intent = getIntent();
Observation observation = (Observation) intent.getSerializableExtra("Observation");
String photoUrl = (String) intent.getSerializableExtra("Photo");
SquareImageView detailsPhoto = findViewById(R.id.details_photo);
Picasso.get().load(photoUrl).into(detailsPhoto);
TextView detailsName = findViewById(R.id.details_name);
detailsName.setText(observation.getNameEnglish());
TextView detailsCreated = findViewById(R.id.details_created);
detailsCreated.setText(observation.getCreated());
TextView detailsUser = findViewById(R.id.details_user);
detailsUser.setText(observation.getUserId());
TextView detailsPopulation = findViewById(R.id.details_population);
detailsPopulation.setText(String.valueOf(observation.getPopulation()));
TextView detailsPlacename = findViewById(R.id.details_placename);
detailsPlacename.setText(observation.getPlaceName());
TextView detailsLongitude = findViewById(R.id.details_longitude);
detailsLongitude.setText(String.valueOf(observation.getLongitude()));
TextView detailsLatitude = findViewById(R.id.details_latitude);
detailsLatitude.setText(String.valueOf(observation.getLatitude()));
TextView detailsComment = findViewById(R.id.details_comment);
if(observation.getComment() != null) detailsComment.setText(observation.getComment());
}
@Override
public boolean onSupportNavigateUp(){
finish();
return true;
}
}
X-Content-Type-Options: nosniff
Content-Security-Policy: default-src 'none'
Content-Type: text/plain; charset=UTF-8
Content-Length: 5115
Content-Disposition: inline; filename="ObservationsFragment.java"
Last-Modified: Wed, 02 Jul 2025 15:06:55 GMT
Expires: Wed, 02 Jul 2025 15:11:55 GMT
ETag: "02e55125d9143ec90419e30382a0b92245e17822"
package org.marcinzelent.liberavem;
import android.content.Context;
import android.content.Intent;
import android.net.Uri;
import android.os.Bundle;
import android.support.annotation.Nullable;
import android.support.design.widget.FloatingActionButton;
import android.support.design.widget.Snackbar;
import android.support.design.widget.TabLayout;
import android.support.v4.app.Fragment;
import android.support.v4.view.ViewPager;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
/**
* A simple {@link Fragment} subclass.
* Activities that contain this fragment must implement the
* {@link ObservationsFragment.OnFragmentInteractionListener} interface
* to handle interaction events.
* Use the {@link ObservationsFragment#newInstance} factory method to
* create an instance of this fragment.
*/
public class ObservationsFragment extends Fragment {
// TODO: Rename parameter arguments, choose names that match
// the fragment initialization parameters, e.g. ARG_ITEM_NUMBER
private static final String ARG_PARAM1 = "param1";
private static final String ARG_PARAM2 = "param2";
// TODO: Rename and change types of parameters
private String mParam1;
private String mParam2;
private OnFragmentInteractionListener mListener;
public ObservationsFragment() {
// Required empty public constructor
}
/**
* Use this factory method to create a new instance of
* this fragment using the provided parameters.
*
* @param param1 Parameter 1.
* @param param2 Parameter 2.
* @return A new instance of fragment ObservationsFragment.
*/
// TODO: Rename and change types and number of parameters
public static ObservationsFragment newInstance(String param1, String param2) {
ObservationsFragment fragment = new ObservationsFragment();
Bundle args = new Bundle();
args.putString(ARG_PARAM1, param1);
args.putString(ARG_PARAM2, param2);
fragment.setArguments(args);
return fragment;
}
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
if (getArguments() != null) {
mParam1 = getArguments().getString(ARG_PARAM1);
mParam2 = getArguments().getString(ARG_PARAM2);
}
((MainActivity) getActivity()).setActionBarTitle("Observations");
DataKeeper.getInstance().clearFragments();
}
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
// Inflate the layout for this fragment
return inflater.inflate(R.layout.fragment_observations, container, false);
}
// TODO: Rename method, update argument and hook method into UI event
public void onButtonPressed(Uri uri) {
if (mListener != null) {
mListener.onFragmentInteraction(uri);
}
}
@Override
public void onViewCreated(View view, @Nullable Bundle savedInstanceState) {
// Find the view pager that will allow the user to swipe between fragments
ViewPager viewPager = view.findViewById(R.id.viewpager);
// Create an adapter that knows which fragment should be shown on each page
ViewPagerAdapter adapter = new ViewPagerAdapter(getContext(), getChildFragmentManager());
// Set the adapter onto the view pager
viewPager.setAdapter(adapter);
// Give the TabLayout the ViewPager
TabLayout tabLayout = view.findViewById(R.id.sliding_tabs);
tabLayout.setupWithViewPager(viewPager);
FloatingActionButton fab = view.findViewById(R.id.fab);
fab.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
Intent intent = new Intent(getActivity(), NewObservationActivity.class);
startActivity(intent);
}
});
}
@Override
public void onAttach(Context context) {
super.onAttach(context);
if (context instanceof OnFragmentInteractionListener) {
mListener = (OnFragmentInteractionListener) context;
} else {
throw new RuntimeException(context.toString()
+ " must implement OnFragmentInteractionListener");
}
}
@Override
public void onDetach() {
super.onDetach();
mListener = null;
}
/**
* This interface must be implemented by activities that contain this
* fragment to allow an interaction in this fragment to be communicated
* to the activity and potentially other fragments contained in that
* activity.
*
* See the Android Training lesson Communicating with Other Fragments for more information.
*/
public interface OnFragmentInteractionListener {
// TODO: Update argument type and name
void onFragmentInteraction(Uri uri);
}
}
X-Content-Type-Options: nosniff
Content-Security-Policy: default-src 'none'
Content-Type: text/plain; charset=UTF-8
Content-Length: 2441
Content-Disposition: inline; filename="ObservationsListAdapter.java"
Last-Modified: Wed, 02 Jul 2025 15:06:55 GMT
Expires: Wed, 02 Jul 2025 15:11:55 GMT
ETag: "b28e1628cfe8d15f3f839a7ded90d51397bad77a"
package org.marcinzelent.liberavem;
import android.content.Context;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.BaseAdapter;
import android.widget.ImageView;
import android.widget.TextView;
import com.squareup.picasso.Picasso;
public class ObservationsListAdapter extends BaseAdapter {
private Context context;
private final Observation[] observations;
private final Bird[] birds;
public ObservationsListAdapter(Context context, Observation[] observations, Bird[] birds){
//super(context, R.layout.single_list_app_item, utilsArrayList);
this.context = context;
this.observations = observations;
this.birds = birds;
}
@Override
public int getCount() {
return observations.length;
}
@Override
public Object getItem(int i) {
return i;
}
@Override
public long getItemId(int i) {
return i;
}
@NonNull
@Override
public View getView(int position, @Nullable View convertView, @NonNull ViewGroup parent) {
ViewHolder viewHolder;
final View result;
if (convertView == null) {
viewHolder = new ViewHolder();
LayoutInflater inflater = LayoutInflater.from(context);
convertView = inflater.inflate(R.layout.observations_list_item, parent, false);
viewHolder.name = convertView.findViewById(R.id.oli_name);
viewHolder.date = convertView.findViewById(R.id.oli_date);
viewHolder.photo = convertView.findViewById(R.id.oli_photo);
result = convertView;
convertView.setTag(viewHolder);
} else {
viewHolder = (ViewHolder) convertView.getTag();
result = convertView;
}
viewHolder.name.setText(observations[position].getNameEnglish());
viewHolder.date.setText(observations[position].getCreated());
String photoUrl = "";
for (Bird bird : birds)
if (bird.getId() == observations[position].getBirdId())
photoUrl = bird.getPhotoUrl();
Picasso.get().load(photoUrl).into(viewHolder.photo);
return convertView;
}
private static class ViewHolder {
TextView name;
TextView date;
ImageView photo;
}
}X-Content-Type-Options: nosniff
Content-Security-Policy: default-src 'none'
Content-Type: text/plain; charset=UTF-8
Content-Length: 2610
Content-Disposition: inline; filename="ResetPasswordActivity.java"
Last-Modified: Wed, 02 Jul 2025 15:06:55 GMT
Expires: Wed, 02 Jul 2025 15:11:55 GMT
ETag: "225730e4ec0b7866311351f541006327b0c5f3c0"
package org.marcinzelent.liberavem;
import android.os.Bundle;
import android.support.annotation.NonNull;
import android.support.v7.app.AppCompatActivity;
import android.text.TextUtils;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;
import android.widget.ProgressBar;
import android.widget.Toast;
import com.google.android.gms.tasks.OnCompleteListener;
import com.google.android.gms.tasks.Task;
import com.google.firebase.auth.FirebaseAuth;
public class ResetPasswordActivity extends AppCompatActivity {
private EditText inputEmail;
private Button btnReset, btnBack;
private FirebaseAuth auth;
private ProgressBar progressBar;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_reset_password);
inputEmail = findViewById(R.id.email);
btnReset = findViewById(R.id.btn_reset_password);
btnBack = findViewById(R.id.btn_back);
progressBar = findViewById(R.id.progressBar);
auth = FirebaseAuth.getInstance();
btnBack.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
finish();
}
});
btnReset.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
String email = inputEmail.getText().toString().trim();
if (TextUtils.isEmpty(email)) {
Toast.makeText(getApplication(), "Enter your registered email id", Toast.LENGTH_SHORT).show();
return;
}
progressBar.setVisibility(View.VISIBLE);
auth.sendPasswordResetEmail(email)
.addOnCompleteListener(new OnCompleteListener() {
@Override
public void onComplete(@NonNull Task task) {
if (task.isSuccessful()) {
Toast.makeText(ResetPasswordActivity.this, "We have sent you instructions to reset your password!", Toast.LENGTH_SHORT).show();
} else {
Toast.makeText(ResetPasswordActivity.this, "Failed to send reset email!", Toast.LENGTH_SHORT).show();
}
progressBar.setVisibility(View.GONE);
}
});
}
});
}
}X-Content-Type-Options: nosniff
Content-Security-Policy: default-src 'none'
Content-Type: text/plain; charset=UTF-8
Content-Length: 10085
Content-Disposition: inline; filename="SettingsActivity.java"
Last-Modified: Wed, 02 Jul 2025 15:06:55 GMT
Expires: Wed, 02 Jul 2025 15:11:55 GMT
ETag: "519ebfd0ece4fcfffc76aa29ace88ea97093bca8"
package org.marcinzelent.liberavem;
import android.annotation.TargetApi;
import android.content.Context;
import android.content.Intent;
import android.content.res.Configuration;
import android.media.Ringtone;
import android.media.RingtoneManager;
import android.net.Uri;
import android.os.Build;
import android.os.Bundle;
import android.preference.ListPreference;
import android.preference.Preference;
import android.preference.PreferenceActivity;
import android.support.v7.app.ActionBar;
import android.preference.PreferenceFragment;
import android.preference.PreferenceManager;
import android.preference.RingtonePreference;
import android.text.TextUtils;
import android.view.MenuItem;
import java.util.List;
/**
* A {@link PreferenceActivity} that presents a set of application settings. On
* handset devices, settings are presented as a single list. On tablets,
* settings are split by category, with category headers shown to the left of
* the list of settings.
*
* See
* Android Design: Settings for design guidelines and the Settings
* API Guide for more information on developing a Settings UI.
*/
public class SettingsActivity extends AppCompatPreferenceActivity {
/**
* A preference value change listener that updates the preference's summary
* to reflect its new value.
*/
private static Preference.OnPreferenceChangeListener sBindPreferenceSummaryToValueListener = new Preference.OnPreferenceChangeListener() {
@Override
public boolean onPreferenceChange(Preference preference, Object value) {
String stringValue = value.toString();
if (preference instanceof ListPreference) {
// For list preferences, look up the correct display value in
// the preference's 'entries' list.
ListPreference listPreference = (ListPreference) preference;
int index = listPreference.findIndexOfValue(stringValue);
// Set the summary to reflect the new value.
preference.setSummary(
index >= 0
? listPreference.getEntries()[index]
: null);
} else if (preference instanceof RingtonePreference) {
// For ringtone preferences, look up the correct display value
// using RingtoneManager.
if (TextUtils.isEmpty(stringValue)) {
// Empty values correspond to 'silent' (no ringtone).
preference.setSummary(R.string.pref_ringtone_silent);
} else {
Ringtone ringtone = RingtoneManager.getRingtone(
preference.getContext(), Uri.parse(stringValue));
if (ringtone == null) {
// Clear the summary if there was a lookup error.
preference.setSummary(null);
} else {
// Set the summary to reflect the new ringtone display
// name.
String name = ringtone.getTitle(preference.getContext());
preference.setSummary(name);
}
}
} else {
// For all other preferences, set the summary to the value's
// simple string representation.
preference.setSummary(stringValue);
}
return true;
}
};
/**
* Helper method to determine if the device has an extra-large screen. For
* example, 10" tablets are extra-large.
*/
private static boolean isXLargeTablet(Context context) {
return (context.getResources().getConfiguration().screenLayout
& Configuration.SCREENLAYOUT_SIZE_MASK) >= Configuration.SCREENLAYOUT_SIZE_XLARGE;
}
/**
* Binds a preference's summary to its value. More specifically, when the
* preference's value is changed, its summary (line of text below the
* preference title) is updated to reflect the value. The summary is also
* immediately updated upon calling this method. The exact display format is
* dependent on the type of preference.
*
* @see #sBindPreferenceSummaryToValueListener
*/
private static void bindPreferenceSummaryToValue(Preference preference) {
// Set the listener to watch for value changes.
preference.setOnPreferenceChangeListener(sBindPreferenceSummaryToValueListener);
// Trigger the listener immediately with the preference's
// current value.
sBindPreferenceSummaryToValueListener.onPreferenceChange(preference,
PreferenceManager
.getDefaultSharedPreferences(preference.getContext())
.getString(preference.getKey(), ""));
}
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setupActionBar();
}
/**
* Set up the {@link android.app.ActionBar}, if the API is available.
*/
private void setupActionBar() {
ActionBar actionBar = getSupportActionBar();
if (actionBar != null) {
// Show the Up button in the action bar.
actionBar.setDisplayHomeAsUpEnabled(true);
}
}
/**
* {@inheritDoc}
*/
@Override
public boolean onIsMultiPane() {
return isXLargeTablet(this);
}
/**
* {@inheritDoc}
*/
@Override
@TargetApi(Build.VERSION_CODES.HONEYCOMB)
public void onBuildHeaders(List target) {
loadHeadersFromResource(R.xml.pref_headers, target);
}
/**
* This method stops fragment injection in malicious applications.
* Make sure to deny any unknown fragments here.
*/
protected boolean isValidFragment(String fragmentName) {
return PreferenceFragment.class.getName().equals(fragmentName)
|| GeneralPreferenceFragment.class.getName().equals(fragmentName)
|| DataSyncPreferenceFragment.class.getName().equals(fragmentName)
|| NotificationPreferenceFragment.class.getName().equals(fragmentName);
}
/**
* This fragment shows general preferences only. It is used when the
* activity is showing a two-pane settings UI.
*/
@TargetApi(Build.VERSION_CODES.HONEYCOMB)
public static class GeneralPreferenceFragment extends PreferenceFragment {
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
addPreferencesFromResource(R.xml.pref_general);
setHasOptionsMenu(true);
// Bind the summaries of EditText/List/Dialog/Ringtone preferences
// to their values. When their values change, their summaries are
// updated to reflect the new value, per the Android Design
// guidelines.
bindPreferenceSummaryToValue(findPreference("example_text"));
bindPreferenceSummaryToValue(findPreference("example_list"));
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
int id = item.getItemId();
if (id == android.R.id.home) {
startActivity(new Intent(getActivity(), SettingsActivity.class));
return true;
}
return super.onOptionsItemSelected(item);
}
}
/**
* This fragment shows notification preferences only. It is used when the
* activity is showing a two-pane settings UI.
*/
@TargetApi(Build.VERSION_CODES.HONEYCOMB)
public static class NotificationPreferenceFragment extends PreferenceFragment {
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
addPreferencesFromResource(R.xml.pref_notification);
setHasOptionsMenu(true);
// Bind the summaries of EditText/List/Dialog/Ringtone preferences
// to their values. When their values change, their summaries are
// updated to reflect the new value, per the Android Design
// guidelines.
bindPreferenceSummaryToValue(findPreference("notifications_new_message_ringtone"));
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
int id = item.getItemId();
if (id == android.R.id.home) {
startActivity(new Intent(getActivity(), SettingsActivity.class));
return true;
}
return super.onOptionsItemSelected(item);
}
}
/**
* This fragment shows data and sync preferences only. It is used when the
* activity is showing a two-pane settings UI.
*/
@TargetApi(Build.VERSION_CODES.HONEYCOMB)
public static class DataSyncPreferenceFragment extends PreferenceFragment {
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
addPreferencesFromResource(R.xml.pref_data_sync);
setHasOptionsMenu(true);
// Bind the summaries of EditText/List/Dialog/Ringtone preferences
// to their values. When their values change, their summaries are
// updated to reflect the new value, per the Android Design
// guidelines.
bindPreferenceSummaryToValue(findPreference("sync_frequency"));
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
int id = item.getItemId();
if (id == android.R.id.home) {
startActivity(new Intent(getActivity(), SettingsActivity.class));
return true;
}
return super.onOptionsItemSelected(item);
}
}
}
X-Content-Type-Options: nosniff
Content-Security-Policy: default-src 'none'
Content-Type: text/plain; charset=UTF-8
Content-Length: 4323
Content-Disposition: inline; filename="SignupActivity.java"
Last-Modified: Wed, 02 Jul 2025 15:06:55 GMT
Expires: Wed, 02 Jul 2025 15:11:55 GMT
ETag: "305f3bcb4b1c604f267e0b8f5e040cbb52e29f57"
package org.marcinzelent.liberavem;
import android.content.Intent;
import android.os.Bundle;
import android.support.annotation.NonNull;
import android.support.v7.app.AppCompatActivity;
import android.text.TextUtils;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;
import android.widget.ProgressBar;
import android.widget.Toast;
import com.google.android.gms.tasks.OnCompleteListener;
import com.google.android.gms.tasks.Task;
import com.google.firebase.auth.AuthResult;
import com.google.firebase.auth.FirebaseAuth;
public class SignupActivity extends AppCompatActivity {
private EditText inputEmail, inputPassword;
private Button btnSignIn, btnSignUp, btnResetPassword;
private ProgressBar progressBar;
private FirebaseAuth auth;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_signup);
//Get Firebase auth instance
auth = FirebaseAuth.getInstance();
btnSignIn = findViewById(R.id.sign_in_button);
btnSignUp = findViewById(R.id.sign_up_button);
inputEmail = findViewById(R.id.email);
inputPassword = findViewById(R.id.password);
progressBar = findViewById(R.id.progressBar);
btnResetPassword = findViewById(R.id.btn_reset_password);
btnResetPassword.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
startActivity(new Intent(SignupActivity.this, ResetPasswordActivity.class));
}
});
btnSignIn.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
finish();
}
});
btnSignUp.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
String email = inputEmail.getText().toString().trim();
String password = inputPassword.getText().toString().trim();
if (TextUtils.isEmpty(email)) {
Toast.makeText(getApplicationContext(), "Enter email address!", Toast.LENGTH_SHORT).show();
return;
}
if (TextUtils.isEmpty(password)) {
Toast.makeText(getApplicationContext(), "Enter password!", Toast.LENGTH_SHORT).show();
return;
}
if (password.length() < 6) {
Toast.makeText(getApplicationContext(), "Password too short, enter minimum 6 characters!", Toast.LENGTH_SHORT).show();
return;
}
progressBar.setVisibility(View.VISIBLE);
//create user
auth.createUserWithEmailAndPassword(email, password)
.addOnCompleteListener(SignupActivity.this, new OnCompleteListener() {
@Override
public void onComplete(@NonNull Task task) {
Toast.makeText(SignupActivity.this, "createUserWithEmail:onComplete:" + task.isSuccessful(), Toast.LENGTH_SHORT).show();
progressBar.setVisibility(View.GONE);
// If sign in fails, display a message to the user. If sign in succeeds
// the auth state listener will be notified and logic to handle the
// signed in user can be handled in the listener.
if (!task.isSuccessful()) {
Toast.makeText(SignupActivity.this, "Authentication failed." + task.getException(),
Toast.LENGTH_SHORT).show();
} else {
startActivity(new Intent(SignupActivity.this, MainActivity.class));
finish();
}
}
});
}
});
}
@Override
protected void onResume() {
super.onResume();
progressBar.setVisibility(View.GONE);
}
}
X-Content-Type-Options: nosniff
Content-Security-Policy: default-src 'none'
Content-Type: text/plain; charset=UTF-8
Content-Length: 744
Content-Disposition: inline; filename="SquareImageView.java"
Last-Modified: Wed, 02 Jul 2025 15:06:55 GMT
Expires: Wed, 02 Jul 2025 15:11:55 GMT
ETag: "ed5dbb7e028d5ba80b1fc50b8ec304605d803d82"
package org.marcinzelent.liberavem;
import android.content.Context;
import android.util.AttributeSet;
public class SquareImageView extends android.support.v7.widget.AppCompatImageView {
public SquareImageView(Context context) {
super(context);
}
public SquareImageView(Context context, AttributeSet attrs) {
super(context, attrs);
}
public SquareImageView(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
}
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
int width = getMeasuredWidth();
setMeasuredDimension(width, width);
}
}
X-Content-Type-Options: nosniff
Content-Security-Policy: default-src 'none'
Content-Type: text/plain; charset=UTF-8
Content-Length: 1239
Content-Disposition: inline; filename="ViewPagerAdapter.java"
Last-Modified: Wed, 02 Jul 2025 15:06:55 GMT
Expires: Wed, 02 Jul 2025 15:11:55 GMT
ETag: "8c20fc9dbe33b08e920b5f1e19eb3774ccb5fb86"
package org.marcinzelent.liberavem;
import android.content.Context;
import android.support.v4.app.Fragment;
import android.support.v4.app.FragmentManager;
import android.support.v4.app.FragmentPagerAdapter;
public class ViewPagerAdapter extends FragmentPagerAdapter {
private Context mContext;
public ViewPagerAdapter(Context context, FragmentManager fm) {
super(fm);
mContext = context;
}
// This determines the fragment for each tab
@Override
public Fragment getItem(int position) {
if (position == 0) {
return new MyObservationsFragment();
} else {
return new AllObservationsFragment();
}
}
// This determines the number of tabs
@Override
public int getCount() {
return 2;
}
// This determines the title for each tab
@Override
public CharSequence getPageTitle(int position) {
// Generate title based on item position
switch (position) {
case 0:
return mContext.getString(R.string.my_observations);
case 1:
return mContext.getString(R.string.all_observations);
default:
return null;
}
}
}