I have an app that works fine on older Android versions, however, on later (Android 11> onwards) whilst the camera(take photo) function works fine, and permissions are OK I can't use the PhotoPicker function, it just shows blank picker , before crashing out of the app completely - in older devices the photo gallery of the device displays correctly and allows you to select a photo to use.
Here is the onCreate for the
PhotoPickerActivity.java
public void onCreate(Bundle bundle) {
super.onCreate(bundle);
requestWindowFeature(1);
getWindow().setFlags(1024, 1024);
boolean booleanExtra = getIntent().getBooleanExtra(PhotoPicker.EXTRA_SHOW_CAMERA, true);
boolean booleanExtra2 = getIntent().getBooleanExtra(PhotoPicker.EXTRA_SHOW_GIF, false);
boolean booleanExtra3 = getIntent().getBooleanExtra(PhotoPicker.EXTRA_PREVIEW_ENABLED, true);
this.forwardMain = getIntent().getBooleanExtra(PhotoPicker.MAIN_ACTIVITY, false);
setShowGif(booleanExtra2);
setContentView(R.layout.__picker_activity_photo_picker);
setSupportActionBar((Toolbar) findViewById(R.id.toolbar));
setTitle(getResources().getString(R.string.tap_to_select));
ActionBar supportActionBar = getSupportActionBar();
supportActionBar.setDisplayHomeAsUpEnabled(true);
// if (Build.VERSION.SDK_INT >= 21) {
supportActionBar.setElevation(25.0f);
// }
this.maxCount = getIntent().getIntExtra(PhotoPicker.EXTRA_MAX_COUNT, 9);
int intExtra = getIntent().getIntExtra(PhotoPicker.EXTRA_GRID_COLUMN, 3);
this.originalPhotos = getIntent().getStringArrayListExtra(PhotoPicker.EXTRA_ORIGINAL_PHOTOS);
this.pickerFragment = (PhotoPickerFragment) getSupportFragmentManager().findFragmentByTag("tag");
if (this.pickerFragment == null) {
this.pickerFragment = PhotoPickerFragment.newInstance(booleanExtra, booleanExtra2, booleanExtra3, intExtra, this.maxCount, this.originalPhotos);
getSupportFragmentManager().beginTransaction().replace(R.id.container, this.pickerFragment, "tag").commit();
getSupportFragmentManager().executePendingTransactions();
}
this.pickerFragment.getPhotoGridAdapter().setOnItemCheckListener(new OnItemCheckListener() {
#Override
public final boolean onItemCheck(int i, Photo photo, int i2) {
return PhotoPickerActivity.this.lambda$onCreate$0$PhotoPickerActivity(i, photo, i2);
}
});
}
We also have PhotoPicker.java
public class PhotoPicker {
public static final int DEFAULT_COLUMN_NUMBER = 3;
public static final int DEFAULT_MAX_COUNT = 9;
public static final String EXTRA_GRID_COLUMN = "column";
public static final String EXTRA_MAX_COUNT = "MAX_COUNT";
public static final String EXTRA_ORIGINAL_PHOTOS = "ORIGINAL_PHOTOS";
public static final String EXTRA_PREVIEW_ENABLED = "PREVIEW_ENABLED";
public static final String EXTRA_SHOW_CAMERA = "SHOW_CAMERA";
public static final String EXTRA_SHOW_GIF = "SHOW_GIF";
public static final String KEY_SELECTED_PHOTOS = "SELECTED_PHOTOS";
public static final String MAIN_ACTIVITY = "MAIN_ACTIVITY";
public static final int REQUEST_CODE = 233;
public static PhotoPickerBuilder builder() {
return new PhotoPickerBuilder();
}
public static class PhotoPickerBuilder {
private Intent mPickerIntent = new Intent();
private Bundle mPickerOptionsBundle = new Bundle();
public void start(Activity activity, int i) {
if (PermissionsUtils.checkReadStoragePermission(activity)) {
activity.startActivityForResult(getIntent(activity), i);
}
}
public void start(Context context, Fragment fragment, int i) {
if (PermissionsUtils.checkReadStoragePermission(fragment.getActivity())) {
fragment.startActivityForResult(getIntent(context), i);
}
}
public void start(Context context, Fragment fragment) {
if (PermissionsUtils.checkReadStoragePermission(fragment.getActivity())) {
fragment.startActivityForResult(getIntent(context), PhotoPicker.REQUEST_CODE);
}
}
public Intent getIntent(Context context) {
this.mPickerIntent.setClass(context, PhotoPickerActivity.class);
this.mPickerIntent.putExtras(this.mPickerOptionsBundle);
return this.mPickerIntent;
}
public void start(Activity activity) {
start(activity, PhotoPicker.REQUEST_CODE);
}
public PhotoPickerBuilder setPhotoCount(int i) {
this.mPickerOptionsBundle.putInt(PhotoPicker.EXTRA_MAX_COUNT, i);
return this;
}
public PhotoPickerBuilder setGridColumnCount(int i) {
this.mPickerOptionsBundle.putInt(PhotoPicker.EXTRA_GRID_COLUMN, i);
return this;
}
public PhotoPickerBuilder setShowGif(boolean z) {
this.mPickerOptionsBundle.putBoolean(PhotoPicker.EXTRA_SHOW_GIF, z);
return this;
}
public PhotoPickerBuilder setShowCamera(boolean z) {
this.mPickerOptionsBundle.putBoolean(PhotoPicker.EXTRA_SHOW_CAMERA, z);
return this;
}
public PhotoPickerBuilder setSelected(ArrayList<String> arrayList) {
this.mPickerOptionsBundle.putStringArrayList(PhotoPicker.EXTRA_ORIGINAL_PHOTOS, arrayList);
return this;
}
public PhotoPickerBuilder setForwardMain(boolean z) {
this.mPickerOptionsBundle.putBoolean(PhotoPicker.MAIN_ACTIVITY, z);
return this;
}
public PhotoPickerBuilder setPreviewEnabled(boolean z) {
this.mPickerOptionsBundle.putBoolean(PhotoPicker.EXTRA_PREVIEW_ENABLED, z);
return this;
}
}
}
In the AndroidManifest.xml the permissions for Camera are there, and on runtime are checked, and permission is granted.
I want to create a game with a qestion and the question is randomly but there is a lot of repetition of questions. I want that the question can appear only once. There is the code of all activity for my game
public class Activity extends AppCompatActivity {
private TextView mQuestionTextViewVe;
private QuestionBankVe mQuestionBankVe;
private QuestionVeriter mCurrentQuestionVe;
private Button mbackButton;
private ArrayList<String> arrayList;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_veriter);
System.out.println("veriterActivity::onCreate()");
mQuestionBankVe = this.generateQuestions();
mQuestionTextViewVe = findViewById(R.id.activity_veriter_question_text);
mCurrentQuestionVe = mQuestionBankVe.getQuestion();
this.displayQuestion(mCurrentQuestionVe);
private void displayQuestion(final QuestionVeriter question) {
mQuestionTextViewVe.setText(question.getQuestion());
}
private QuestionBankVe generateQuestions() {
QuestionVeriter question1 = new QuestionVeriter("Question");
QuestionVeriter question2 = new QuestionVeriter("Question");
QuestionVeriter question3 = new QuestionVeriter("Question");
return new QuestionBankVe(Arrays.asList( question1,
question2
question3
));
}
}
public class QuestionBankVe {
private List<QuestionVeriter> mQuestionListVe;
private int mNextQuestionIndexVe;
public QuestionBankVe(List<QuestionVeriter> questionListVe) {
mQuestionListVe = questionListVe;
// Shuffle the question list
Collections.shuffle(mQuestionListVe);
mNextQuestionIndexVe = 0;
}
public QuestionVeriter getQuestion() {
// Ensure we loop over the questions
if (mNextQuestionIndexVe == mQuestionListVe.size()) {
mNextQuestionIndexVe = 0;
}
// Please note the post-incrementation
return mQuestionListVe.get(mNextQuestionIndexVe++);
}
}
public class QuestionVeriter {
private String mQuestionVe;
public QuestionVeriter(String question) {
this.setQuestion(question);
}
public String getQuestion() {
return mQuestionVe;
}
public void setQuestion(String question) {
mQuestionVe = question;
}
#Override
public String toString() {
return "Question{" +
"mQuestion='" + mQuestionVe + '\'' +
'}';
}
}
I am trying to test my code by using Mockito
static class SongAdapterPresenter implements SortedSongSelectionContract.SongAdapterContract.Presenter {
private List<Song> songs;
private final Presenter sortedSongSelectionPresenter;
private final SortedSongSelectionContract.SongAdapterContract.Adapter adapter;
private SortedSongSelectionContract.SongAdapterContract.SongView selectedSongView;
private Song selectedSong;
SongAdapterPresenter(SortedSongSelectionContract.SongAdapterContract.Adapter adapter, SortedSongSelectionContract.Presenter sortedSongSelectionPresenter) {
this.adapter = adapter;
this.sortedSongSelectionPresenter = sortedSongSelectionPresenter;
}
#Override
public int getItemCount() {
return songs != null ? songs.size() : 0;
}
#Override
public void onBindView(SortedSongSelectionContract.SongAdapterContract.SongView songView, int position) {
Song song = songs.get(position);
songView.setTitle(song.getName());
songView.setArtists(song.getArtists());
List<Genre> genres = song.getGenres();
int size = genres.size();
StringBuilder builder = new StringBuilder();
for (int i = 0; i < size; i++) {
builder.append(genres.get(i).getName()).append(",");
}
int length = builder.length();
if (length > 0) {
builder.deleteCharAt(length - 1);
}
songView.setGenres(builder.toString());
songView.showPlayIcon(true);
boolean select = isSongEqual(song);
if (select) {
selectedSongView = songView;
}
songView.showSelectionUi(select);
}
#Override
public void onItemClicked(SortedSongSelectionContract.SongAdapterContract.SongView songView, int position) {
Song song = songs.get(position);
if (isSongEqual(song)) {
return;
}
deSelect(song);
selectedSongView = songView;
selectedSongView.showSelectionUi(true);
selectedSong = songs.get(position);
sortedSongSelectionPresenter.getBus().post(new BusEvents.SongSelected(selectedSong));
}
#Override
public void setSongs(List<Song> songs) {
this.songs = songs;
adapter.refresh();
}
#Override
public void deSelect(Song song) {
if (!isSongEqual(song)) {
if (selectedSongView != null) {
selectedSongView.showSelectionUi(false);
}
selectedSong = null;
selectedSongView = null;
}
}
private boolean isSongEqual(Song song) {
return !(song == null || selectedSong == null) && (song == selectedSong || selectedSong.getId().equals(song.getId()));
}
}
//endregion
//region Instance methods
private void processEvent(Object event) {
if (event instanceof BusEvents.SongSelected) {
deSelect(((BusEvents.SongSelected) event).getSong());
}
}
//endregion
}
I want to write test for onBindView
Following is my Test Class
RunWith(PowerMockRunner.class)
#PrepareForTest(Log.class)
public class SongAdapterPresenterTest {
private SortedSongSelectionPresenter.SongAdapterPresenter songAdapterPresenter;
#Mock
private SortedSongSelectionContract.SongAdapterContract.Adapter adapter;
#Mock
private SortedSongSelectionContract.Presenter presenter;
#Mock
private SortedSongSelectionContract.SongAdapterContract.SongView songView;
private Song song;
private List<Song> songList;
#Before
public void setUp() {
song = new Song("1", "A", "B");
songList = new ArrayList<>(1);
songList.add(song);
songAdapterPresenter = new SortedSongSelectionPresenter.SongAdapterPresenter(adapter, presenter);
}
#Test
public void getItemCountWithSongListNotNull_returnSongListSize() {
songAdapterPresenter.setSongs(songList);
Assert.assertEquals(songList.size(), songAdapterPresenter.getItemCount());
}
#Test
public void getItemCountWithSongListNull_returnIsZero(){
songAdapterPresenter.setSongs(null);
Assert.assertEquals(0, songAdapterPresenter.getItemCount());
}
#Test
public void testonBindView() {
songAdapterPresenter.onBindView(songView, 1);
verify(songView).showSelectionUi(true);
}
#Test
public void deSelect_SongRemoved(){
songAdapterPresenter.deSelect(song);
verify(songView).showSelectionUi(false);
}
}
I have created Mock Object of View and object of my PresenterAdapter class. I am not getting what causes the error.
I keep getting NullPointer when i execute my onBindView Test
Any help would be greatly appreciated.
You never call setSongs and that's why you get a NullPointerException.
Also note that your songList has only one element.
Change your code to:
#Test
public void testonBindView() {
songAdapterPresenter.setSongs(songList);
songAdapterPresenter.onBindView(songView, 0);
verify(songView).showSelectionUi(true);
}
Im new to Android Developement and currently working on an app that should give me the time between first time clicking a button and second time clicking the button and add it to a currently selected customer.
Current Status of App:
I established a connection to da mySql Database using Volley and a local webservice.
It works to insert my customers and time stamps to the table, but when loading times for a specific customer i get a strange result in one case. I tried debugging it but the app keeps crashing on debugging without a message. When not debugging it doesnt crash but shows weird data.
To the problem:
In my main activity called "ZeitErfassen" i have a button to get an overview of all customers display in a ListView.
I create the Listview with a custom ArrayAdapter because i want to pass my objects to the next Activity where my customers are displayed.
So onCreate of the overview of customers i create a new arraylist and fill it with all customers from my database. this list i pass to my customadapter and then set it as my adapter of the Listview.
Now, when i click on an item, i call a php script and pass the customer_id to the query to fetch all times from database where customer_id = customer_id.
Now the part where i get "strange" data...
1.(Source:ZeitErfassen;Destination:AddCustomer) I create a new customer,example xyz, in the app, data gets passed to the database.
2.(Source:ZeitErfassen;Destination:DisplayCustomer) I call my overview for all customers where the ListView is filled with data as described above. At the end ob the List I see the customer i just created,xyz.
3.Go back to Main Activity(ZeitErfassen)
4.(Source:ZeitErfassen;Destination:DisplayCustomer)I open the overview for all customers again, and it shows my last created user two times! so last entry, xyz, entry before last, xyz!
After that, i can open the view as many times as i want, the customer never gets duplicated again!
The debugger stopps after step 2.
Now when i click on the new customers, it calls the script to fetch the times by customer_id.
One of the xyz entrys display the correct times from database.
The second one, i just found out, display the times where customer_id="". In the database the value for "" is 0.
I have no clue where the second customer suddenly appears from and debugging didnt help me either -.-
When i close the app an open it again, there ist just one entry for the user that was visible twice before closing the app. It doesnt duplicate on opening view...
Here is my code..
Main Activity ZeitErfassen
public class ZeitErfassen extends AppCompatActivity {
public static LinkedList<Kunde> kunden = new LinkedList<Kunde>();
boolean running = false;
long startTime,endTime,totalTime;
private SharedPreferences app_preferences;
private SharedPreferences.Editor editor;
private TextView displayTime;
public Button startEndButton;
private ArrayAdapter<String> adapter;
private Spinner spinner;
public static Kunde selectedCustomer;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_zeit_erfassen);
//Einstellungen laden
app_preferences = getApplicationContext().getSharedPreferences("MyPref", MODE_PRIVATE);
startTime= app_preferences.getLong("startTime", 0);
endTime = app_preferences.getLong("endTime", 0);
running = app_preferences.getBoolean("running", false);
displayTime = (TextView)findViewById(R.id.zeit_bei_Kunde);
displayTime.setText((CharSequence) app_preferences.getString("zeitAnzeige", "Zeit bei Kunde"));
startEndButton = (Button)findViewById(R.id.start_Timer);
startEndButton.setText((CharSequence) app_preferences.getString("timerButton", "Start Timer"));
DatabaseHelper.customerFromDatabaseToList(this);
editor = app_preferences.edit();
editor.commit();
}
public void onDestroy() {
super.onDestroy();
editor.putLong("startTime", startTime);
editor.putString("zeitAnzeige", (String) displayTime.getText());
editor.putString("timerButton", (String) startEndButton.getText());
editor.putLong("endTime", endTime);
editor.putLong("totalTime", totalTime);
editor.putBoolean("running", app_preferences.getBoolean("running", false));
editor.commit();
this.finish();
}
public void onResume() {
super.onResume();
// saveCustomers();
// createDropDown();
}
public void startTimer(View view) {
editor = app_preferences.edit();
if(running == false) {
startTime = getTime();
running = true;
editor.putLong("startTime", startTime);
startEndButton.setText("End Timer");
displayTime.setText("Zeitstoppung läuft");
editor.putString("zeitAnzeige", (String) displayTime.getText());
editor.putString("timerButton", (String) startEndButton.getText());
editor.putBoolean("running", true);
editor.commit();
} else {
setSelectedCustomer();
endTime = getTime();
editor.putLong("endTime",endTime);
totalTime = endTime - startTime;
editor.putLong("totalTime", totalTime);
displayTime.setText(formatTime(totalTime));
editor.putString("zeitAnzeige", (String) displayTime.getText());
startEndButton.setText("Start Timer");
editor.putString("timerButton", (String) startEndButton.getText());
running = false;
editor.putBoolean("running", false);
editor.commit();
DatabaseHelper.timeToDatabase(String.valueOf(selectedCustomer.getId()),formatTime(totalTime),this);
// selectedCustomer.saveTimeToCustomer(selectedCustomer, formatTimeForCustomer(totalTime));
}
}
public String formatTime(Long totalTime) {
int hours = (int) ((totalTime / (1000*60*60)) % 24);
int minutes = (int) ((totalTime / (1000*60)) % 60);
int seconds = (int) (totalTime / 1000) % 60;
String time = (String.valueOf(hours) + ":" + String.valueOf(minutes) + ":" + String.valueOf(seconds));
return time;
}
public String formatTimeForCustomer(Long totalTime) {
StringBuilder time = new StringBuilder();
Calendar cal = Calendar.getInstance();
int year = cal.get(Calendar.YEAR);
int month = cal.get(Calendar.MONTH);
int day = cal.get(Calendar.DAY_OF_MONTH);
time.append((String.valueOf(year) + "." + String.valueOf(month) + "." + String.valueOf(day))).append(formatTime(totalTime));
return time.toString();
}
public void neuerKunde(View view) {
Intent intent = new Intent(this, AddKunde.class);
startActivity(intent);
}
public void kundenÜbersicht(View view) {
// setSelectedCustomer();
Intent intent = new Intent(this, DisplayCustomer.class);
startActivity(intent);
}
public long getTime() {
long millis = System.currentTimeMillis();
return millis;
}
public void setSelectedCustomer() {
if(kunden.size() > 0) {
if (spinner.getSelectedItem().toString() != null) {
String tempCustomer = spinner.getSelectedItem().toString();
for (Kunde k : kunden) {
if (k.getName().equals(tempCustomer)) {
selectedCustomer = k;
}
}
}
}
}
public void createDropDown() {
/*File file = new File(this.getFilesDir(),"kunden.ser"); NOT USED BECAUSE DATABASE WORKS
if(file.exists()) {
Kunde.importFromFile(this);
}*/
if (kunden.size() > 0) {
spinner = (Spinner) findViewById(R.id.chooseCustomer);
// Create an ArrayAdapter using the string array and a default spinner layout
adapter = new ArrayAdapter<String>(this, android.R.layout.simple_spinner_item, DisplayCustomer.namesOfCustomers());
// Specify the layout to use when the list of choices appears
adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
// Apply the adapter to the spinner
spinner.setAdapter(adapter);
}
}
}
DisplayCustomer(Where all customers are displayed with data from Database)
public class DisplayCustomer extends AppCompatActivity {
CustomerAdapter customerAdapter;
public ArrayAdapter<String> adapterCustomerView;
private ListView listCustomerView;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_display_customer);
Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
setSupportActionBar(toolbar);
getSupportActionBar().setDisplayHomeAsUpEnabled(true);
ArrayList<Kunde> customerList = getCustomerObjects();
customerAdapter = new CustomerAdapter(this,customerList);
listCustomerView = (ListView)findViewById(R.id.list_View_Customers);
// adapterCustomerView = new ArrayAdapter<String>(this, android.R.layout.simple_list_item_1, namesOfCustomers());
listCustomerView.setAdapter(customerAdapter);
openCustomerDetails();
}
public static ArrayList<String> namesOfCustomers() {
ArrayList<String> customerNames = new ArrayList<>();
if(ZeitErfassen.kunden.size() > 0 ) {
for (Kunde k : ZeitErfassen.kunden) {
customerNames.add(k.getName());
}
}
return customerNames;
}
public static ArrayList<Kunde> getCustomerObjects() {
ArrayList<Kunde> customerList = new ArrayList<>();
if(ZeitErfassen.kunden.size() > 0 ) {
for (Kunde k : ZeitErfassen.kunden) {
customerList.add(k);
}
}
return customerList;
}
public void openCustomerDetails() {
listCustomerView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
Kunde kunde = new Kunde();
kunde = (Kunde)listCustomerView.getItemAtPosition(position);
Intent intent = new Intent(DisplayCustomer.this, DisplayDetailedCustomer.class);
intent.putExtra("selectedCustomerObject",(Parcelable)kunde);
startActivity(intent);
}
});
}
}
My CustomerAdapter to pass data from one intent to another.
public class CustomerAdapter extends ArrayAdapter<Kunde> {
public CustomerAdapter(Context context, ArrayList<Kunde> customerList) {
super(context,0,customerList);
}
public View getView(int position, View convertView, ViewGroup parent) {
//Data for this position
Kunde kunde = getItem(position);
if (convertView == null) {
convertView = LayoutInflater.from(getContext()).inflate(R.layout.items_customer_layout, parent, false);
}
// Lookup view for data population
TextView tvName = (TextView) convertView.findViewById(R.id.tvCustomerName);
// Populate the data into the template view using the data object
tvName.setText(kunde.getName());
// Return the completed view to render on screen
return convertView;
}
}
DatabaseHelper Class
public class DatabaseHelper {
public static RequestQueue requestQueue;
public static String host = "http://192.168.150.238/";
public static final String insertUrl = host+"insertCustomer.php";
public static final String showUrl = host+"showCustomer.php";
public static final String insertTimeUrl = host+"insertTime.php";
public static final String showTimeUrl = host+"showTimes.php";
public static void customerFromDatabaseToList(final Context context) {
//Display customer from database
requestQueue = Volley.newRequestQueue(context);
final ArrayList<String> customerNames = new ArrayList<>();
JsonObjectRequest jsonObjectRequest = new JsonObjectRequest(Request.Method.POST, showUrl, new Response.Listener<JSONObject>() {
#Override
public void onResponse(JSONObject response) {
try {
JSONArray customers = response.getJSONArray("customers");
if(customers.length() > 0) {
for (int i = 0; i < customers.length(); i++) {
JSONObject customer = customers.getJSONObject(i);
String customerName = customer.getString("cus_name");
String customerAddress = customer.getString("cus_address");
int customerID = Integer.valueOf(customer.getString("cus_id"));
if (customerName != null && customerAddress != null) {
try {
Kunde k = new Kunde(customerName, customerAddress, customerID);
if (!listContainsObject(k)) {
ZeitErfassen.kunden.add(k);
}
} catch (Exception e) {
showAlert("Fehler in customerFromDatabaseToListn!", "Fehler", context);
}
} else {
showAlert("Fehler in customerFromDatabaseToListn!", "Fehler", context);
}
}
}
} catch (JSONException e) {
e.printStackTrace();
}
}
}, new Response.ErrorListener() {
#Override
public void onErrorResponse(VolleyError error) {
error.printStackTrace();
}
});
requestQueue.add(jsonObjectRequest);
}
public static boolean listContainsObject(Kunde cust) {
for(Kunde k : ZeitErfassen.kunden) {
if(k.getId() == cust.getId()) {
return true;
}
}
return false;
}
public static void timeToDatabase(final String customer_id, final String time_value, final Context context) {
requestQueue = Volley.newRequestQueue(context);
StringRequest request = new StringRequest(Request.Method.POST, DatabaseHelper.insertTimeUrl, new Response.Listener<String>() {
#Override
public void onResponse(String response) {
}
}, new Response.ErrorListener() {
#Override
public void onErrorResponse(VolleyError error) {
showAlert("Fehler","Fehler bei Verbindung zur Datenbank",context);
}
}) {
#Override
protected Map<String, String> getParams() throws AuthFailureError {
Map<String,String> parameters = new HashMap<String,String>();
parameters.put("customerid",customer_id);
parameters.put("timevalue",time_value);
return parameters;
}
};
requestQueue.add(request);
};
public static void showAlert(String title, String message, Context context) {
// 1. Instantiate an AlertDialog.Builder with its constructor
AlertDialog.Builder builder = new AlertDialog.Builder(context);
// 2. Chain together various setter methods to set the dialog characteristics
builder.setMessage(message)
.setTitle(title);
// 3. Get the AlertDialog from create()
AlertDialog dialog = builder.create();
}
public static ArrayList<String> timesFromDataBaseToList(final Context context,final int customer_id) {
requestQueue = Volley.newRequestQueue(context);
final String cus_id = String.valueOf(customer_id) ;
final ArrayList<String> customerTimes = new ArrayList<>();
StringRequest jsonObjectRequest = new StringRequest(Request.Method.POST, showTimeUrl, new Response.Listener<String>() {
#Override
public void onResponse(String response) {
try {
JSONObject object = new JSONObject(response.toString());
JSONArray times = object.getJSONArray("customertimes");
if (times.length() > 0) {
for (int i = 0; i < times.length(); i++) {
JSONObject jsonObject = times.getJSONObject(i);
String timeValue = jsonObject.getString("time_value");
if (timeValue != null) {
customerTimes.add(timeValue);
}
}
}
} catch (JSONException e) {
e.printStackTrace();
}
}
}, new Response.ErrorListener() {
#Override
public void onErrorResponse(VolleyError error) {
Toast.makeText(context,"Fehler beim Holen der Zeiten",Toast.LENGTH_LONG).show();
error.printStackTrace();
}
}){
protected Map<String, String> getParams() throws AuthFailureError {
Map<String,String> parameters = new HashMap<String,String>();
parameters.put("cus_id",cus_id);
return parameters;
}
};
requestQueue.add(jsonObjectRequest);
return customerTimes;
};
}
DisplayDetailedCustomer / Display the times
public class DisplayDetailedCustomer extends AppCompatActivity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_display_detailed_customer);
Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
setSupportActionBar(toolbar);
getSupportActionBar().setDisplayHomeAsUpEnabled(true);
Intent getCustomerParcable = getIntent();
Kunde customer = getCustomerParcable.getExtras().getParcelable("selectedCustomerObject");
TextView displayCustomerNameDetailed =(TextView) findViewById(R.id.detailedCustomerViewName);
TextView displayCustomerAddressDetailed =(TextView) findViewById(R.id.detailedCustomerAddress);
ListView timeListView = (ListView)findViewById(R.id.detailedTimeListView);
ArrayAdapter<String> adapter = new ArrayAdapter<String>(this,android.R.layout.simple_list_item_1, DatabaseHelper.timesFromDataBaseToList(this,customer.getId()));
timeListView.setAdapter(adapter);
displayCustomerNameDetailed.setText(customer.getName());
displayCustomerAddressDetailed.setText(customer.getAdresse());
}
}
Kunde Class / Customer Class with interface Parcelable
public class Kunde implements Serializable,Parcelable {
private String name;
private String adresse;
private int id;
public LinkedList<String> zeiten;
public Kunde(String name, String adresse) throws Exception{
setName(name);
setAdresse(adresse);
zeiten = new LinkedList<String>();
}
public Kunde(String name, String adresse,int id) throws Exception{
setName(name);
setAdresse(adresse);
setId(id);
zeiten = new LinkedList<String>();
}
public Kunde(){};
public void setId(int id) {
this.id = id;
}
public int getId(){
return id;
}
public void setName(String name) throws Exception {
if(name != null) {
this.name = name;
} else throw new Exception("Name ist ungueltig! in setName");
}
public void setAdresse(String adresse) throws Exception{
if(adresse != null) {
this.adresse = adresse;
}else throw new Exception("Adresse ist ungueltig! in setAdresse");
}
public String getName() {
return name;
}
public String getAdresse() {
return adresse;
}
public void saveZeit(Long totalTime) {
zeiten.add(String.valueOf(totalTime));
}
public void saveTimeToCustomer(Kunde customer,String time){
customer.zeiten.add(time);
}
//------------------------------------Parcelable Methods to pass Daata from one Intent to another----------------------------------------
#Override
public int describeContents() {
return 0;
}
#Override
public void writeToParcel(Parcel dest, int flags) {
dest.writeInt(this.id);
dest.writeString(this.name);
dest.writeString(this.adresse);
// dest.writeList(this.zeiten);
}
// this is used to regenerate your object. All Parcelables must have a CREATOR that implements these two methods
public static final Parcelable.Creator<Kunde> CREATOR = new Parcelable.Creator<Kunde>() {
public Kunde createFromParcel(Parcel in) {
return new Kunde(in);
}
public Kunde[] newArray(int size) {
return new Kunde[size];
}
};
// example constructor that takes a Parcel and gives you an object populated with it's values
private Kunde(Parcel in) {
LinkedList<String> zeiten = null;
id = in.readInt();
name = in.readString();
adresse = in.readString();
}
}
Thanks for taking your time!!
To give an idea of what I am doing. I have a Main activity that allows you to add names to a recyclerView then start a round that sends to an Arraylist of people through an Intent to CurrentMatchActivity. after a while of user input it launches another instance of CurrentMatchActivity by passing an Arraylist of people to a new CurrentMatchActivity.
Here is the Person class
public class Person implements Parcelable {
private String name;
private int wins;
private long totalWins;
private boolean stillPlaying;
private ArrayList<Person> previousOpponents;
Person(String name)
{
this.name = name;
wins = 0;
totalWins = 0;
stillPlaying = true;
previousOpponents = new ArrayList<>();
}
public void setStillPlaying(boolean playing)
{
stillPlaying = playing;
}
public void addOpponent(Person person) {
previousOpponents.add(person);
}
public boolean hasFought(Person person) {
return previousOpponents.contains(person);
}
#Override
public int describeContents() {
return 0;
}
private Person(Parcel in)
{
name = in.readString();
wins = in.readInt();
totalWins = in.readLong();
stillPlaying = (boolean) in.readValue(null);
previousOpponents = new ArrayList<>();
in.readTypedList(previousOpponents, null);
}
#Override
public void writeToParcel(Parcel dest, int flags) {
dest.writeString(name);
dest.writeInt(wins);
dest.writeLong(totalWins);
dest.writeValue(stillPlaying);
dest.writeTypedList(previousOpponents);
}
public static final Parcelable.Creator<Person> CREATOR = new Parcelable.Creator<Person>() {
public Person createFromParcel(Parcel in) {
return new Person(in);
}
public Person[] newArray(int size) {
return new Person[size];
}
};
}
Here is the CurrentMatchActivity
package omarzious.myapplication;
public class CurrentMatchActivity extends Activity {
private ArrayList<Person> people;
private RecyclerView mRecyclerView;
private RecyclerView.Adapter mAdapter;
private RecyclerView.LayoutManager mLayoutManager;
private int round;
private RetainedFragment dataFragment;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_current_match);
FragmentManager fm = getFragmentManager();
dataFragment = (RetainedFragment) fm.findFragmentByTag("currentMatchData");
if (dataFragment == null){
dataFragment = new RetainedFragment();
fm.beginTransaction().add(dataFragment, "currentMatchData").commit();
round = getIntent().getIntExtra("round",1);
people = getIntent().getParcelableArrayListExtra("people");
prepareMatch();
}
else
{
people = dataFragment.getData();
}
this.setTitle(getString(R.string.round)+" "+round);
mRecyclerView = (RecyclerView) findViewById(R.id.current_match_recycler_view);
mLayoutManager = new LinearLayoutManager(this);
mRecyclerView.setLayoutManager(mLayoutManager);
mAdapter = new CurrentMatchAdapter(people, getApplicationContext());
mRecyclerView.setAdapter(mAdapter);
// Swipe Portion
SwipeableRecyclerViewTouchListener swipeTouchListener = new SwipeableRecyclerViewTouchListener(mRecyclerView,
new SwipeableRecyclerViewTouchListener.SwipeListener() {
private int personIndex;
#Override
public boolean canSwipe(int position)
{
if (position == (int)people.size()/2)
{
return false;
}
return people.get(position*2).isStillPlaying();
}
#Override
public void onDismissedBySwipeRight(RecyclerView recyclerView, int[] reverseSortedPositions) {
for (int position : reverseSortedPositions)
{
personIndex = position*2;
//personBeat(personIndex, personIndex+1);
people.get(personIndex).won();
mAdapter.notifyItemChanged(position);
// if player on right won
if (people.get(personIndex).isWinner())
{
people.get(personIndex).setStillPlaying(false);
people.get(personIndex+1).setStillPlaying(false);
if (checkForRoundEnd())
{
startNewRound();
}
}
}
mAdapter.notifyDataSetChanged();
}
public void onDismissedBySwipeLeft(RecyclerView recyclerView, int[] reverseSortedPositions) {
for (int position : reverseSortedPositions) {
personIndex = position*2+1;
people.get(personIndex).won();
mAdapter.notifyItemChanged(personIndex);
// if player on left won
if (people.get(personIndex).isWinner())
{
people.get(personIndex).setStillPlaying(false);
people.get(personIndex-1).setStillPlaying(false);
if (checkForRoundEnd())
{
startNewRound();
}
}
}
mAdapter.notifyDataSetChanged();
}
});
mRecyclerView.addOnItemTouchListener(swipeTouchListener);
}
public void checkForRematches()
{
int i = 0;
Person personA;
Person personB;
ListIterator<Person> a;
boolean collision = false;
int numberOfItterations = 0;
// do {
a = people.listIterator();
collision = false;
i=0;
while ( i < (int)(people.size() / 2))
{
personA = a.next();
personB = a.next();
i++;
if (personA.hasFought(personB)) {
a.remove();
a.add(personB);
people.add(personB);
collision = true;
Toast.makeText(this,"WTF", Toast.LENGTH_SHORT);
}
}
numberOfItterations++;
// } while(collision);
Toast.makeText(this, "prepare match had to itterate "+numberOfItterations+ "times", Toast.LENGTH_SHORT).show();
}
public void prepareMatch() {
Collections.shuffle(people);
int i = 0;
Person personA;
Person personB;
ListIterator<Person> a = people.listIterator();
if (round > 1)
{
// checkForRematches();
}
while (i < (int)(people.size() / 2))
{
personA = a.next();
personB = a.next();
i++;
personA.addOpponent(personB);
personB.addOpponent(personA);
}
}
public boolean checkForRoundEnd()
{
int stillPlayingAllowed = people.size() % 2;
int peopleStillPlaying = 0;
for (Person person : people) {
if (person.isStillPlaying()) {
peopleStillPlaying++;
}
}
return peopleStillPlaying == stillPlayingAllowed;
}
public void startNewRound()
{
Iterator<Person> i = people.iterator();
Person person;
while (i.hasNext()) {
person = i.next();
if (!person.isWinner() && !person.isStillPlaying())
{
i.remove();
}
person.clearWins();
person.setStillPlaying(true);
}
if (people.size() > 1) {
Toast.makeText(this, "Starting new round", Toast.LENGTH_SHORT).show();
Intent intent = new Intent(this, CurrentMatchActivity.class);
intent.putExtra("round",++round);
intent.putParcelableArrayListExtra("people", people);
startActivity(intent);
}
else
{
Intent intent = new Intent(this, GameOverActivity.class);
intent.putParcelableArrayListExtra("people", people);
startActivity(intent);
}
}
#Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.menu_current_match, 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_settings) {
return true;
}
return super.onOptionsItemSelected(item);
}
#Override
public void onDestroy()
{
super.onDestroy();
dataFragment.setData(people);
}
}
now the odd part is it works fine. unless I activate the code.
public void prepareMatch() {
Collections.shuffle(people);
int i = 0;
Person personA;
Person personB;
ListIterator<Person> a;
while (i < (int)(people.size() / 2))
{
personA = a.next();
personB = a.next();
i++;
personA.addOpponent(personB);
personB.addOpponent(personA);
}
}
which causes a null pointer crash in the MainAdapter
The mainActivity uses the mainAdapter. but the currentMatchActivity uses a CurrentMatch adapter.. And the crash happens when it tries to create an CurrentMatchActivity from the CurrentMatchActivity.
I don't believe that MainAdapter should even be in use here... only CurrentMatchAdapter. Furthermore... I don't see how activating the prepareMatch function should affect the flow of my code in that way..
Edit: found out that it was crashing because of because of the parcelable. Guess it didn't like a person list inside of a person list.
I came to the conclusion that the issue was nesting an arraylist of a class inside an arraylist of the same class and making it parcelable. I ended up using an arraylist of int primary keys inside of the class and it fixed the issue.
Example:
class A implements parcelable {
arraylist<int> keys;
}
arraylist<a>