I am really new to AndroidStudio and I'm trying to make a sharing app. My purpose is to have an app that automatically loads up all the images on my phone(or in my phone's gallery, not that important) and display them on screen. Afterwards, I want to click on one of the images over there, and then use a Share button I made to send that photo to another person (it can be an MMS or any other application, the main problem is that this share button transmit the picture I clicked on most recently).
I don't know a lot about the specifics of Android Studio, meaning I know how to code (sort of) but I am unfamiliar with the possibilities of implementing this. My code is below.
GalleryAdapter.java:
public class GalleryAdapter extends RecyclerView.Adapter<GalleryAdapter.ViewHolder> {
private Context context;
private List<String> images;
protected PhotoListener photoListener;
public GalleryAdapter(Context context, List<String> images, PhotoListener photoListener) {
this.context = context;
this.images = images;
this.photoListener = photoListener;
}
#NonNull
#Override
public ViewHolder onCreateViewHolder(#NonNull ViewGroup parent, int viewType) {
return new ViewHolder(
LayoutInflater.from(context).inflate(R.layout.gallery_item, parent, false)
);
}
#Override
public void onBindViewHolder(#NonNull ViewHolder holder, int position) {
String image=images.get(position);
Glide.with(context).load(image).into(holder.image);
holder.itemView.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
photoListener.onPhotoClick(image);
}
});
}
#Override
public int getItemCount() {
return images.size();
}
public class ViewHolder extends RecyclerView.ViewHolder {
ImageView image;
public ViewHolder(#NonNull View itemView) {
super(itemView);
image=itemView.findViewById(R.id.image);
}
}
public interface PhotoListener{
void onPhotoClick(String path);
}
}
ImagesGallery.java:
public class ImagesGallery {
public static ArrayList<String> listofImages(Context context){
Uri uri;
Cursor cursor;
int column_index_data, column_index_folder_name;
ArrayList<String> listofAllImages=new ArrayList<>();
String absolutePathOfImage;
uri= MediaStore.Images.Media.EXTERNAL_CONTENT_URI;
String[] projection={MediaStore.MediaColumns.DATA, MediaStore.Images.Media.BUCKET_DISPLAY_NAME};
String orderBy= MediaStore.Video.Media.DATE_TAKEN;
cursor=context.getContentResolver().query(uri, projection, null, null, orderBy+" DESC");
column_index_data=cursor.getColumnIndexOrThrow(MediaStore.MediaColumns.DATA);
while(cursor.moveToNext()){
absolutePathOfImage=cursor.getString(column_index_data);
listofAllImages.add(absolutePathOfImage);
}
return listofAllImages;
}
}
MainActivity.java:
public class MainActivity extends AppCompatActivity {
RecyclerView recyclerView;
GalleryAdapter galleryAdapter;
List<String> images;
TextView gallery_number;
private static final int MY_READ_PERMISSION_CODE=101;
#Override
protected void onCreate(Bundle savedInstanceState) {
ActivityCompat.requestPermissions(this, new String[]{Manifest.permission.READ_EXTERNAL_STORAGE}, 101);
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
gallery_number=findViewById(R.id.gallery_number);
recyclerView=findViewById(R.id.recyclerview_gallery_images);
if(ContextCompat.checkSelfPermission(MainActivity.this, Manifest.permission.READ_EXTERNAL_STORAGE)!= PackageManager.PERMISSION_GRANTED){
ActivityCompat.requestPermissions(MainActivity.this, new String[]{Manifest.permission.READ_EXTERNAL_STORAGE}, MY_READ_PERMISSION_CODE);
} else {
loadImages();
}
}
#Override
public boolean onCreateOptionsMenu(Menu menu) {
getMenuInflater().inflate(R.menu.main_menu, menu);
return true;
}
#Override
public boolean onOptionsItemSelected(#NonNull MenuItem item) {
if(item.getItemId()==R.id.share_menu){
Intent shareIntent = new Intent();
shareIntent.setAction(Intent.ACTION_SEND);
Uri uriToImage=Uri.parse("android.resource://com.example.tutorialpaper5/"+R.drawable.test);
shareIntent.putExtra(Intent.EXTRA_STREAM, uriToImage);
shareIntent.setType("image/jpeg");
startActivity(Intent.createChooser(shareIntent, getResources().getText(R.string.app_name)));
} else{
return super.onOptionsItemSelected(item);
}
return true;
}
private void loadImages(){
recyclerView.setHasFixedSize(true);
recyclerView.setLayoutManager(new GridLayoutManager(this, 4));
images=ImagesGallery.listofImages(this);
galleryAdapter=new GalleryAdapter(this, images, new GalleryAdapter.PhotoListener() {
#Override
public void onPhotoClick(String path) {
Toast.makeText(MainActivity.this, ""+path, Toast.LENGTH_LONG).show();
}
});
recyclerView.setAdapter(galleryAdapter);
gallery_number.setText("Photos +("+images.size()+")");
}
#Override
public void onRequestPermissionsResult(int requestCode, #NonNull String[] permissions, #NonNull int[] grantResults) {
super.onRequestPermissionsResult(requestCode, permissions, grantResults);
if(requestCode==MY_READ_PERMISSION_CODE){
if(grantResults[0]==PackageManager.PERMISSION_GRANTED){
Toast.makeText(this, "read external storage permission granted", Toast.LENGTH_LONG).show();
loadImages();
} else {
Toast.makeText(this, "Read external storage permission denied", Toast.LENGTH_LONG).show();
}
}
}
}
You will notice that in my onOptionsItemSelected class I just threw in a picture I had in the drawable directory to see if the share button actually works. It does, now I just need some way for it memorize my last clicked photo and throw it in that Intent. But again, I am not sure if that is possible.
There are multiple options, here are two simple solutions just to link your code parts.
Suggestion with minimal changes in your logic:
You can just save the onPhotoClick(String path) to a field that will defined in the activity class scope and then use this field in the onOptionsItemSelected adding some code parts:
public class MainActivity extends AppCompatActivity {
String clickedImagePath = null
// ...
#Override
public boolean onOptionsItemSelected(#NonNull MenuItem item) {
if(item.getItemId()==R.id.share_menu){
if (clickedImagePath != null) {
// The code you had for sharing with changing line for uriToImage
Uri uriToImage=Uri.parse(clickedImagePath);
} else {
// maybe show some error than nothing selected
}
}
}
// ...
public void onPhotoClick(String path) {
Toast.makeText(MainActivity.this, ""+path, Toast.LENGTH_LONG).show();
clickedImagePath = path
}
// ...
Maybe a better UX
Remove the onOptionsItemSelected completely and move the intent code to the onPhotoClick listener.
#Override
public void onPhotoClick(String path) {
Toast.makeText(MainActivity.this, ""+path, Toast.LENGTH_LONG).show();
Intent shareIntent = new Intent();
shareIntent.setAction(Intent.ACTION_SEND);
Uri uriToImage=Uri.parse(path); // <-- Don't forget to fix the path
shareIntent.putExtra(Intent.EXTRA_STREAM, uriToImage);
shareIntent.setType("image/jpeg");
MainActivity.this.startActivity(Intent.createChooser(shareIntent, getResources().getText(R.string.app_name)));
}
Related
I'm currently building a booking application for laundry's machine. I need to get the item count and if the count is zero it will show the dialog box which told user that there is no data in the system.
The Activity code:
public class DobbySelection2 extends AppCompatActivity {
String local;
private Dialog dialog;
private FirebaseFirestore db = FirebaseFirestore.getInstance();
private DobbyAdapter adapter;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_dobby_selection2);
dialog = new Dialog(this);
dialog.setContentView(R.layout.custom_dialog2);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
dialog.getWindow().setBackgroundDrawable(getDrawable(R.drawable.custom_dialogbackground));
}
dialog.getWindow().setLayout(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT);
dialog.setCancelable(false); //Optional
dialog.getWindow().getAttributes().windowAnimations = R.style.DialogAnimation; //Setting the animations to dialog
Button Yes = dialog.findViewById(R.id.btn_yes);
Yes.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
Intent intent = new Intent(DobbySelection2.this, MainActivity.class );
dialog.dismiss();
startActivity(intent);
}
});
setUpRecyclerView();
}
private void setUpRecyclerView(){
Intent i = getIntent();
local = i.getStringExtra("PLACE");
if (local == null){
local = "Selangor";
}
CollectionReference dobbyRef = db.collection("locality")
.document(local)
.collection("Dobby");
Query query = dobbyRef.orderBy("name", Query.Direction.DESCENDING);
FirestoreRecyclerOptions<Dobby> options = new FirestoreRecyclerOptions.Builder<Dobby>()
.setQuery(query, Dobby.class)
.build();
adapter = new DobbyAdapter(options);
RecyclerView recyclerView = findViewById(R.id.recycler_view);
recyclerView.setHasFixedSize(true);
//recyclerView.setLayoutManager(new LinearLayoutManager(this));
recyclerView.setLayoutManager(new CustomLinearLayoutManager(this));
recyclerView.setAdapter(adapter);
if(adapter.getItemCount() == 0){
dialog.show();
}
adapter.setOnItemClickListener(new DobbyAdapter.OnItemClickListener() {
#Override
public void onItemClick(DocumentSnapshot documentSnapshot, int position) {
Dobby dobby = documentSnapshot.toObject(Dobby.class);
String id = documentSnapshot.getId();
Toast.makeText(DobbySelection2.this, "ID : " + id, Toast.LENGTH_SHORT).show();
Intent intent = new Intent(DobbySelection2.this, Booking2.class);
intent.putExtra("PLACE", local);
intent.putExtra("ID", id);
startActivity(intent);
}
});
}
#Override
protected void onStart() {
super.onStart();
adapter.startListening();
}
#Override
protected void onStop() {
super.onStop();
adapter.stopListening();
}
}
Adapter code:
public class DobbyAdapter extends FirestoreRecyclerAdapter<Dobby, DobbyAdapter.DobbyHolder>{
private OnItemClickListener listener;
/**
* Create a new RecyclerView adapter that listens to a Firestore Query. See {#link
* FirestoreRecyclerOptions} for configuration options.
*
* #param options
*/
public DobbyAdapter(#NonNull FirestoreRecyclerOptions<Dobby> options) {
super(options);
}
#Override
protected void onBindViewHolder(#NonNull DobbyHolder holder, int position, #NonNull Dobby model) {
holder.textViewName.setText(model.getName());
holder.textViewAddress.setText(model.getAddress());
holder.textViewDistance.setText(model.getDistance());
}
#NonNull
#Override
public DobbyHolder onCreateViewHolder(#NonNull ViewGroup parent, int viewType) {
View v = LayoutInflater.from(parent.getContext()).inflate(R.layout.itemdobby, parent, false);
return new DobbyHolder(v);
}
class DobbyHolder extends RecyclerView.ViewHolder{
TextView textViewName;
TextView textViewAddress;
TextView textViewDistance;
public DobbyHolder(#NonNull View itemView) {
super(itemView);
textViewName = itemView.findViewById(R.id.nameDobby);
textViewAddress = itemView.findViewById(R.id.addressDobby);
textViewDistance = itemView.findViewById(R.id.distanceDobby);
itemView.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
int position = getAdapterPosition();
if(position != RecyclerView.NO_POSITION && listener != null){
listener.onItemClick(getSnapshots().getSnapshot(position), position);
}
}
});
}
}
public interface OnItemClickListener {
void onItemClick(DocumentSnapshot documentSnapshot, int position);
}
public void setOnItemClickListener(OnItemClickListener listener){
this.listener = listener;
}
}
But the dialog box always pop up indicating that the count is zero even though there is data inside of the recycler view. How can I fix this?
My guess is that the dialog you're talking about comes from here:
if(adapter.getItemCount() == 0){
dialog.show();
}
If so, it makes sense that it shows up as this code runs before any data has been loaded.
Data is loaded from Firestore (and most modern cloud APIs) asynchronously, and this changes the order in which code executes. It's easiest to see this if you set breakpoint on the if line above, on adapter.startListening(); and on the first line inside your onBindViewHolder.
If you now run the code in the debugger, you'll see that it:
First hits the if(adapter.getItemCount() == 0){ line
Then adapter.startListening()`
Then gets to onBindViewHolder
So now it hopefully makes sense why your code always show the dialog: no data has been loaded yet at that point.
The solution for this is always the same: you need to make sure that the code that needs the data runs after the data has been loaded. Since you're using the FirestoreRecyclerAdapter from FirebaseUI, you can do this inside its onDataChanged method that signals that a complete snapshot was loaded (regardless of whether there was any data in that snapshot) and is shown in the documentation on data and error events.
So if you move your if check into a onDataChanged method in your DobbyAdapter, it will get called whenever the adapter has loaded a complete snapshot, and it will show the dialog when there are no items.
I'm changing old styled code for Activity Results, and got stuck on permission results. In fragment where users can pick one contact from a list and copy it's data, permission callback is not working at all, however activity result is firing callback... Here is simplified fragment class:
public class PeopleAddEdit_SubVen_Fragment extends Fragment {
private ActivityResultLauncher<Intent> mActivityResult;
private ActivityResultLauncher<String> mPermissionResult;
#Override
public View onCreateView(#NotNull LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.fragment_addedit_ppl_subven, container, false);
ImageView contacticon = view.findViewById(R.id.contacticon_container);
contacticon.setImageDrawable(AppLib.getAppDrawable(R.drawable.icons_88));
contacticon.setOnClickListener(view1 -> processContact());
return view;
}
#Override
public void onAttach(#NotNull Context context) {
super.onAttach(context);
AppCompatActivity activity = (AppCompatActivity) context;
mActivityResult = registerForActivityResult(
new ActivityResultContracts.StartActivityForResult(),
new ActivityResultCallback<ActivityResult>() {
#Override
public void onActivityResult(ActivityResult result) {
if (result.getResultCode() == Activity.RESULT_OK) {
Intent data = result.getData();
//processing data here
...
}
}
});
mPermissionResult = registerForActivityResult(
new ActivityResultContracts.RequestPermission(),
new ActivityResultCallback<Boolean>() {
#Override
public void onActivityResult(Boolean result) {
if (result) {
PeopleAddEdit_SubVen_Fragment.this.startProcessingContacts();
} else {
Toast.makeText(PeopleAddEdit_SubVen_Fragment.this.getActivity(), "No permission.", Toast.LENGTH_SHORT).show();
}
}
});
}
private void processContact() {
int getContacts = ContextCompat.checkSelfPermission(thisContext, Manifest.permission.READ_CONTACTS);
if (getContacts != PackageManager.PERMISSION_GRANTED) {
mPermissionResult.launch(Manifest.permission.READ_CONTACTS);
} else {
startProcessingContacts();
}
}
private void startProcessingContacts() {
Intent intent = new Intent(Intent.ACTION_PICK, ContactsContract.Contacts.CONTENT_URI);
mActivityResult.launch(intent);
}
}
When Contacts are not granted, after displaying popup to deny or allow Contacts, nothing happens regardless of choice. If I click button again (after I allow Contacts), I get contacts displayed, so activity result is firing callback, but permission callback is not fired at all, but permission is granting or denying, depending on choice, but not firing result.
In the build.gradle I have
implementation 'androidx.activity:activity:1.4.0'
implementation 'androidx.fragment:fragment:1.4.0-rc01'
Any ideas why is not firing?
Problem solved. I just needed to remove from parent activity
#Override
public void onRequestPermissionsResult(int requestCode, #NonNull String[] permissions, #NonNull int[] grantResults) {
...
}
and it works now.
I Have code which is defined for image (drawable )
Means Image is are already defined but I want user to select Image from Gallery .
SO first I want to get all Images from gallery and then it is show in view and from their user can select Image .
So it means all Images must be saved in array like below .
Any Help for this.
public class StickerSelectActivity extends AppCompatActivity {
public static final String EXTRA_STICKER_ID = "extra_sticker_id";
private final int[] stickerIds = {
R.drawable.abra,
R.drawable.bellsprout,
R.drawable.bracelet,
R.drawable.bullbasaur,
R.drawable.camera,
R.drawable.candy,
R.drawable.caterpie,
R.drawable.charmander,
R.drawable.mankey,
R.drawable.map,
R.drawable.mega_ball,
R.drawable.meowth,
R.drawable.pawprints,
R.drawable.pidgey,
R.drawable.pikachu,
R.drawable.pikachu_1,
R.drawable.pikachu_2,
R.drawable.player,
R.drawable.pointer,
R.drawable.pokebag,
R.drawable.pokeball,
R.drawable.pokeballs,
R.drawable.pokecoin,
R.drawable.pokedex,
R.drawable.potion,
R.drawable.psyduck,
R.drawable.rattata,
R.drawable.revive,
R.drawable.squirtle,
R.drawable.star,
R.drawable.star_1,
R.drawable.superball,
R.drawable.tornado,
R.drawable.venonat,
R.drawable.weedle,
R.drawable.zubat
};
#Override
protected void onCreate(#Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.select_sticker_activity);
//noinspection ConstantConditions
getSupportActionBar().setDisplayHomeAsUpEnabled(true);
RecyclerView recyclerView = (RecyclerView) findViewById(R.id.stickers_recycler_view);
GridLayoutManager glm = new GridLayoutManager(this, 3);
recyclerView.setLayoutManager(glm);
List<Integer> stickers = new ArrayList<>(stickerIds.length);
for (Integer id : stickerIds) {
stickers.add(id);
}
recyclerView.setAdapter(new StickersAdapter(stickers, this));
}
#Override
public boolean onOptionsItemSelected(MenuItem item) {
if (item.getItemId() == android.R.id.home) {
onBackPressed();
return true;
}
return super.onOptionsItemSelected(item);
}
private void onStickerSelected(int stickerId) {
Intent intent = new Intent();
intent.putExtra(EXTRA_STICKER_ID, stickerId);
setResult(RESULT_OK, intent);
finish();
}
class StickersAdapter extends RecyclerView.Adapter<StickersAdapter.StickerViewHolder> {
private final List<Integer> stickerIds;
private final Context context;
private final LayoutInflater layoutInflater;
StickersAdapter(#NonNull List<Integer> stickerIds, #NonNull Context context) {
this.stickerIds = stickerIds;
this.context = context;
this.layoutInflater = LayoutInflater.from(context);
}
#Override
public StickerViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
return new StickerViewHolder(layoutInflater.inflate(R.layout.sticker_item, parent, false));
}
#Override
public void onBindViewHolder(StickerViewHolder holder, int position) {
holder.image.setImageDrawable(ContextCompat.getDrawable(context, getItem(position)));
}
#Override
public int getItemCount() {
return stickerIds.size();
}
private int getItem(int position) {
return stickerIds.get(position);
}
class StickerViewHolder extends RecyclerView.ViewHolder {
ImageView image;
StickerViewHolder(View itemView) {
super(itemView);
image = (ImageView) itemView.findViewById(R.id.sticker_image);
itemView.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
int pos = getAdapterPosition();
if (pos >= 0) { // might be NO_POSITION
onStickerSelected(getItem(pos));
}
}
});
}
}
}
}
Its not required If you want to show all available images in gallery in your application. You can use
private Cursor cc = null;
cc = this.getContentResolver().query(
MediaStore.Images.Media.EXTERNAL_CONTENT_URI, null, null, null,
null)
This will give you a connection with files available in gallery. More detailed answer is here
How to implement Image Gallery in Gridview in android?
If In case in your application you have an image view and you want your user to click on the image and then Android should ask if they want to select an image from gallery/camera you can follow this, You can call selectImage method on setOnClickListener on ImageView.
private void selectImage() {
final CharSequence[] items = { "Take Photo", "Choose from Library" };
AlertDialog.Builder builder = new AlertDialog.Builder(getActivity());
builder.setTitle("Update Profile Photograph");
builder.setItems(items, new DialogInterface.OnClickListener() {
#Override
public void onClick(DialogInterface dialog, int item) {
boolean result = Utility.checkPermission(getActivity());
if (items[item].equals("Take Photo")) {
if(result)
cameraIntent();
} else if (items[item].equals("Choose from Library")) {
if(result)
galleryIntent();
}
}
});
builder.show();
}
private void cameraIntent() {
Intent takePicture = new Intent(android.provider.MediaStore.ACTION_IMAGE_CAPTURE);
File out = Environment.getExternalStorageDirectory();
out = new File(out, familyMemberId + ".png");
Uri photoURI = FileProvider.getUriForFile(getContext(), getContext().getPackageName() + ".app.provider", out);
takePicture.putExtra(MediaStore.EXTRA_OUTPUT, photoURI);
startActivityForResult(takePicture, 0);
}
private void galleryIntent() {
Intent pickPhoto = new Intent(Intent.ACTION_PICK,
android.provider.MediaStore.Images.Media.EXTERNAL_CONTENT_URI);
startActivityForResult(pickPhoto , 1);//one can be replaced with any action code
}
#Override
public void onActivityResult(int requestCode, int resultCode, Intent imageReturnedIntent) {
super.onActivityResult(requestCode, resultCode, imageReturnedIntent);
switch(requestCode) {
case 0:
if(resultCode == Activity.RESULT_OK){
File out = Environment.getExternalStorageDirectory();
out = new File(out, familyMemberId + ".png");
Uri photoURI = FileProvider.getUriForFile(getContext(), getContext().getPackageName() + ".app.provider", out);
Toast.makeText(getContext(), photoURI.toString(), Toast.LENGTH_LONG).show();
imageUri = photoURI.toString();
Glide.with(this).load(imageUri).into(familyMemberProfilePick);
}
break;
case 1:
if(resultCode == Activity.RESULT_OK){
Uri selectedImage = imageReturnedIntent.getData();
imageUri = selectedImage.toString();
Glide.with(this).load(imageUri).into(familyMemberProfilePick);
}
break;
}
}
Please don't forget add these in
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
<application ...
<provider
android:name=".utility.GenericFileProvider"
android:authorities="${applicationId}.app.provider"
android:exported="false"
android:grantUriPermissions="true">
<meta-data
android:name="android.support.FILE_PROVIDER_PATHS"
android:resource="#xml/provider_paths"/>
</provider>
....
</application>
I have a MasterActivity that has a few fragments. One fragment allows the user to open up Square to pay. After the user signs their name in Square and the data is returned to my app, my app crashes because the Payment fragment can't find the MasterActivity as it is null.
This only happens when the user signs the receipt. If the user pays cash (no signature) the My App works fine.
I have noticed that the when the Square App is ready for a signature it rotates the screen, just before the signature capture activity is view-able, I can see my app rotate too.
After the Square application has returned to my app, I can see the successful upload of the data to my server from my app. Then, it is only when the payment fragment asks the MasterActivity to refresh the data, I get a null pointer exception for the DISP_KEY in MasterAcitvity .
Can any see what I might be doing wrong?
MasterActivity
public class MasterActivity extends AppCompatActivity {
private String TAG = getClass().getSimpleName();
private String DISP_KEY = "";
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_master);
Intent intent = getIntent();
DISP_KEY = (String) intent.getSerializableExtra("SELECTED_DISPATCH");
initView();
refreshData();
}
#Override
public void onBackPressed() {
super.onBackPressed();
}
public void refreshData() {
//Do some network download data stuff using the DISP_KEY
}
private void initView() {
TabLayout tabLayout = (TabLayout) findViewById(R.id.tab_layout);
//JUST TEXT
tabLayout.addTab(tabLayout.newTab().setText("Details"));
tabLayout.addTab(tabLayout.newTab().setText("Sections"));
tabLayout.addTab(tabLayout.newTab().setText("Area"));
tabLayout.addTab(tabLayout.newTab().setText("Notes"));
tabLayout.addTab(tabLayout.newTab().setText("Payments"));
final ViewPager viewPager = (ViewPager) findViewById(R.id.pager);
final PagerAdapter adapter = new TabPagerAdapter(getSupportFragmentManager(), tabLayout.getTabCount());
viewPager.setAdapter(adapter);
}
}
PaymentFragment
public class PaymentFragment extends Fragment {
private static final int SQUARE_CHARGE_REQUEST_CODE = 1;
private String TAG = getClass().getSimpleName();
private PosClient posClient;
public PaymentFragment() {
// Required empty public constructor for fragments
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.fragment_payment, container, false);
initGUI(view);
return view;
}
#Override
public void onStart() {
super.onStart();
mVehicle = ((MasterActivity) this.getActivity()).getCurrentVehicle();
if (mVehicle != null) {
reloadData();
}
}
#Override
public void onAttach(Context context) {
super.onAttach(context);
if (this != null) {
((MasterActivity) context).registerDataReloadListener(this);
posClient = PosSdk.createClient(getActivity(), AppConfig.SQUARE_APP_ID);
} else {
((MasterActivity) context).onBackPressed();
}
}
#Override
public void onDetach() {
super.onDetach();
if (this != null) {
((MasterActivity) getActivity()).unregisterDataReloadListener(this);
}
}
public void reloadData() {
//Ask the master activity to reload data
}
// SQUARE
private void acceptSquarePayment() {
ChargeRequest.TenderType types;
ChargeRequest request = new ChargeRequest.Builder(Integer.parseInt(square_balance), CurrencyCode.USD)
.enforceBusinessLocation(square_location_id)
.restrictTendersTo(types)
.requestMetadata(square_call_num)
.autoReturn(3200, TimeUnit.MILLISECONDS)
.build();
Intent intent = posClient.createChargeIntent(request);
startActivityForResult(intent, SQUARE_CHARGE_REQUEST_CODE);
}
// GET SQAURE RESULTS
#Override
public void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if (resultCode == Activity.RESULT_OK) {
ChargeRequest.Success success = posClient.parseChargeSuccess(data);
sendReceiptToAPIServer(success.serverTransactionId, success.clientTransactionId, success.requestMetadata);
}
}
private void sendReceiptToAPIServer(String serverTransactionId, String clientTransactionId, String callNum) {
//Do some data upload stuff
//After the successufull upload, this is where the crash happens
reloadData();
}
#Override
public void onDataReload() {
mVehicle = ((MasterActivity) this.getActivity()).getCurrentVehicle();
if (getView() != null) {
reloadData();
}
}
}
I have made an app that lets the user add location through place picker and add them into the SQLite database.I am displaying these locations in recyclerview. In order to delete an item from recyclerview, this is what I have done so far.
1) User long presses on an item in recyclerview and then alert dialogue appears with 2 buttons (Delete and Cancel).
What I can't-do:
1) Now I don't know how to delete an item from recyclerview and from SQLite database when the user taps on the delete button.
I have searched for it but don't how it can be implemented. I am posting the code for MainActivity.java class, PlaceDbhelper.java class, and PlacelistAdapter.java class.
MainActivity.java class
public class MainActivity extends AppCompatActivity implements
ConnectionCallbacks,
OnConnectionFailedListener {
// Constants
public static final String TAG = MainActivity.class.getSimpleName();
private static final int PERMISSIONS_REQUEST_FINE_LOCATION = 111;
private static final int PLACE_PICKER_REQUEST = 1;
// Member variables
private PlaceListAdapter mAdapter;
private RecyclerView mRecyclerView;
private boolean mIsEnabled;
private GoogleApiClient mClient;
private Geofencing mGeofencing;
//String arr;
/**
* Called when the activity is starting
*
* #param savedInstanceState The Bundle that contains the data supplied in onSaveInstanceState
*/
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
// Set up the recycler view
mRecyclerView = (RecyclerView) findViewById(R.id.places_list_recycler_view);
mRecyclerView.setLayoutManager(new LinearLayoutManager(this));
mAdapter = new PlaceListAdapter(this, null);
mRecyclerView=(RecyclerView)findViewById(R.id.places_list_recycler_view);
mRecyclerView.setAdapter(mAdapter);
Switch onOffSwitch = (Switch) findViewById(R.id.enable_switch);
mIsEnabled = getPreferences(MODE_PRIVATE).getBoolean(getString(R.string.setting_enabled), false);
onOffSwitch.setChecked(mIsEnabled);
onOffSwitch.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
#Override
public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
SharedPreferences.Editor editor = getPreferences(MODE_PRIVATE).edit();
editor.putBoolean(getString(R.string.setting_enabled), isChecked);
mIsEnabled = isChecked;
editor.commit();
if (isChecked) mGeofencing.registerAllGeofences();
else mGeofencing.unRegisterAllGeofences();
}
});
mClient = new GoogleApiClient.Builder(this)
.addConnectionCallbacks(this)
.addOnConnectionFailedListener(this)
.addApi(LocationServices.API)
.addApi(Places.GEO_DATA_API)
.enableAutoManage(this, this)
.build();
mGeofencing = new Geofencing(this, mClient);
mRecyclerView.addOnItemTouchListener(new RecyclerTouchListener(this,
mRecyclerView, new ClickListener() {
public void onClick(View view, final int position) {
picture.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
}
});*/
}
public void onItemClick(View view, int position) {
}
#Override
public void onLongClick(View view, int position) {
final AlertDialog alertDialog =new AlertDialog.Builder(MainActivity.this).create();
alertDialog.setTitle("Are you want to delete this");
alertDialog.setCancelable(false);
alertDialog.setMessage("By deleting this, item will permanently be deleted. Are you still want to delete this?");
alertDialog.setButton(DialogInterface.BUTTON_POSITIVE, "Cancel", new DialogInterface.OnClickListener() {
#Override
public void onClick(DialogInterface dialog, int which) {
}
});
alertDialog.setButton(DialogInterface.BUTTON_NEGATIVE, "Delete", new DialogInterface.OnClickListener() {
#Override
public void onClick(DialogInterface dialog, int which) {
}
});
alertDialog.show();
Toast.makeText(MainActivity.this, "Long press on position :"+position,
Toast.LENGTH_LONG).show();
}
}));
}
/***
* Called when the Google API Client is successfully connected
*
* #param connectionHint Bundle of data provided to clients by Google Play services
*/
#Override
public void onConnected(#Nullable Bundle connectionHint) {
refreshPlacesData();
Log.i(TAG, "API Client Connection Successful!");
}
/***
* Called when the Google API Client is suspended
*
* #param cause cause The reason for the disconnection. Defined by constants CAUSE_*.
*/
#Override
public void onConnectionSuspended(int cause) {
Log.i(TAG, "API Client Connection Suspended!");
}
/***
* Called when the Google API Client failed to connect to Google Play Services
*
* #param result A ConnectionResult that can be used for resolving the error
*/
#Override
public void onConnectionFailed(#NonNull ConnectionResult result) {
Log.e(TAG, "API Client Connection Failed!");
}
public void refreshPlacesData() {
Uri uri = PlaceContract.PlaceEntry.CONTENT_URI;
Cursor data = getContentResolver().query(
uri,
null,
null,
null,
null);
if (data == null || data.getCount() == 0) return;
List<String> guids = new ArrayList<String>();
while (data.moveToNext()) {
guids.add(data.getString(data.getColumnIndex(PlaceContract.PlaceEntry.COLUMN_PLACE_ID)));
}
PendingResult<PlaceBuffer> placeResult = Places.GeoDataApi.getPlaceById(mClient,
guids.toArray(new String[guids.size()]));
placeResult.setResultCallback(new ResultCallback<PlaceBuffer>() {
#Override
public void onResult(#NonNull PlaceBuffer places) {
mAdapter.swapPlaces(places);
mGeofencing.updateGeofencesList(places);
if (mIsEnabled) mGeofencing.registerAllGeofences();
}
});
}
public void onAddPlaceButtonClicked(View view) {
if (ActivityCompat.checkSelfPermission(this, android.Manifest.permission.ACCESS_FINE_LOCATION)
!= PackageManager.PERMISSION_GRANTED) {
Toast.makeText(this, getString(R.string.need_location_permission_message), Toast.LENGTH_LONG).show();
return;
}
try {
PlacePicker.IntentBuilder builder = new PlacePicker.IntentBuilder();
Intent i = builder.build(this);
startActivityForResult(i, PLACE_PICKER_REQUEST);
} catch (GooglePlayServicesRepairableException e) {
Log.e(TAG, String.format("GooglePlayServices Not Available [%s]", e.getMessage()));
} catch (GooglePlayServicesNotAvailableException e) {
Log.e(TAG, String.format("GooglePlayServices Not Available [%s]", e.getMessage()));
} catch (Exception e) {
Log.e(TAG, String.format("PlacePicker Exception: %s", e.getMessage()));
}
}
/***
* Called when the Place Picker Activity returns back with a selected place (or after canceling)
*
* #param requestCode The request code passed when calling startActivityForResult
* #param resultCode The result code specified by the second activity
* #param data The Intent that carries the result data.
*/
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
if (requestCode == PLACE_PICKER_REQUEST && resultCode == RESULT_OK) {
Place place = PlacePicker.getPlace(this, data);
if (place == null) {
Log.i(TAG, "No place selected");
return;
}
String placeID = place.getId();
// Insert a new place into DB
ContentValues contentValues = new ContentValues();
contentValues.put(PlaceContract.PlaceEntry.COLUMN_PLACE_ID, placeID);
getContentResolver().insert(PlaceContract.PlaceEntry.CONTENT_URI, contentValues);
// Get live data information
refreshPlacesData();
}
}
#Override
public void onResume() {
super.onResume();
// Initialize location permissions checkbox
CheckBox locationPermissions = (CheckBox) findViewById(R.id.location_permission_checkbox);
if (ActivityCompat.checkSelfPermission(MainActivity.this,
android.Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED) {
locationPermissions.setChecked(false);
} else {
locationPermissions.setChecked(true);
locationPermissions.setEnabled(false);
}
// Initialize ringer permissions checkbox
CheckBox ringerPermissions = (CheckBox) findViewById(R.id.ringer_permissions_checkbox);
NotificationManager nm = (NotificationManager) getSystemService(NOTIFICATION_SERVICE);
// Check if the API supports such permission change and check if permission is granted
if (android.os.Build.VERSION.SDK_INT >= 24 && !nm.isNotificationPolicyAccessGranted()) {
ringerPermissions.setChecked(false);
} else {
ringerPermissions.setChecked(true);
ringerPermissions.setEnabled(false);
}
}
public void onRingerPermissionsClicked(View view) {
Intent intent = new Intent(android.provider.Settings.ACTION_NOTIFICATION_POLICY_ACCESS_SETTINGS);
startActivity(intent);
}
public void onLocationPermissionClicked(View view) {
ActivityCompat.requestPermissions(MainActivity.this,
new String[]{android.Manifest.permission.ACCESS_FINE_LOCATION},
PERMISSIONS_REQUEST_FINE_LOCATION);
}
public static interface ClickListener{
public void onClick(View view,int position);
public void onLongClick(View view,int position);
}
class RecyclerTouchListener implements RecyclerView.OnItemTouchListener{
private ClickListener clicklistener;
private GestureDetector gestureDetector;
public RecyclerTouchListener(Context context, final RecyclerView recycleView, final ClickListener clicklistener){
this.clicklistener=clicklistener;
gestureDetector=new GestureDetector(context,new GestureDetector.SimpleOnGestureListener(){
#Override
public boolean onSingleTapUp(MotionEvent e) {
return true;
}
#Override
public void onLongPress(MotionEvent e) {
View child=recycleView.findChildViewUnder(e.getX(),e.getY());
if(child!=null && clicklistener!=null){
clicklistener.onLongClick(child,recycleView.getChildAdapterPosition(child));
}
}
});
}
#Override
public boolean onInterceptTouchEvent(RecyclerView rv, MotionEvent e) {
View child=rv.findChildViewUnder(e.getX(),e.getY());
if(child!=null && clicklistener!=null && gestureDetector.onTouchEvent(e)){
clicklistener.onClick(child,rv.getChildAdapterPosition(child));
}
return false;
}
#Override
public void onTouchEvent(RecyclerView rv, MotionEvent e) {
}
#Override
public void onRequestDisallowInterceptTouchEvent(boolean disallowIntercept) {
}
}
}
PlaceDbhelper.java class
public class PlaceDbHelper extends SQLiteOpenHelper {
// The database name
private static final String DATABASE_NAME = "location.db";
PlaceListAdapter obj1;
// If you change the database schema, you must increment the database version
private static final int DATABASE_VERSION = 1;
// Constructor
public PlaceDbHelper(Context context) {
super(context, DATABASE_NAME, null, DATABASE_VERSION);
}
#Override
public void onCreate(SQLiteDatabase sqLiteDatabase) {
// Create a table to hold the places data
final String SQL_CREATE_PLACES_TABLE = "CREATE TABLE " + PlaceEntry.TABLE_NAME + " (" +
PlaceEntry._ID + " INTEGER PRIMARY KEY AUTOINCREMENT," +
PlaceEntry.COLUMN_PLACE_ID + " TEXT NOT NULL, " +
"UNIQUE (" + PlaceEntry.COLUMN_PLACE_ID + ") ON CONFLICT REPLACE" +
"); ";
sqLiteDatabase.execSQL(SQL_CREATE_PLACES_TABLE);
}
String pe=PlaceEntry._ID.toString();
#Override
public void onUpgrade(SQLiteDatabase sqLiteDatabase, int i, int i1) {
// For now simply drop the table and create a new one.
sqLiteDatabase.execSQL("DROP TABLE IF EXISTS " + PlaceEntry.TABLE_NAME);
onCreate(sqLiteDatabase);
}
PlacelistAdapter.java class
public class PlaceListAdapter extends
RecyclerView.Adapter<PlaceListAdapter.PlaceViewHolder> {
private Context mContext;
private PlaceBuffer mPlaces;
PlaceDbHelper obj1;
RecyclerView recycleview;
public PlaceListAdapter(Context context, PlaceBuffer places) {
this.mContext = context;
this.mPlaces = places;
}
#Override
public PlaceViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
// Get the RecyclerView item layout
LayoutInflater inflater = LayoutInflater.from(mContext);
View view = inflater.inflate(R.layout.item_place_card, parent, false);
//final Activity activity;
return new PlaceViewHolder(view);
}
#Override
public void onBindViewHolder(PlaceViewHolder holder, int position) {
String placeName = mPlaces.get(position).getName().toString();
String placeAddress = mPlaces.get(position).getAddress().toString();
holder.nameTextView.setText(placeName);
holder.addressTextView.setText(placeAddress);
}
public void swapPlaces(PlaceBuffer newPlaces) {
mPlaces = newPlaces;
if (mPlaces != null) {
// Force the RecyclerView to refresh
this.notifyDataSetChanged();
}
}
#Override
public int getItemCount() {
if (mPlaces == null) return 0;
return mPlaces.getCount();
}
/**
* PlaceViewHolder class for the recycler view item
*/
class PlaceViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener {
TextView nameTextView;
TextView addressTextView;
public PlaceViewHolder(final View itemView) {
super(itemView);
nameTextView = (TextView) itemView.findViewById(R.id.name_text_view);
addressTextView = (TextView) itemView.findViewById(R.id.address_text_view);
}
#Override
public void onClick(View v) {
}
I have solution for you, you need to delete row from db and then remove from your arraylist and after it notify you adapter. like below.
Use this method in your PlaceDbhelper.java class
public void removePlace(String placeId){
SQLiteDatabase db = this.getWritableDatabase();
db.delete(PlaceEntry.TABLE_NAME, PlaceEntry.COLUMN_PLACE_ID + "=\"" + placeId+"\"", null) ;
}
now call this method in alert when click DELETE
private void deletePlace(int position){
PlaceDbhelper dbHelper = new PlaceDbhelper(MainActivity.this);
dbHelper.removePlace(placeArraylist.get(position).getPlaceId());
placeArraylist.remove(position);
mAdapter.notifyDataSetChanged();
}
Hope this will help you, If this solve your problem make it approved. Ask if you need help.