I made an application in which users can send links to their friends. With the link, I added some parameters, So when the user clicks on the link the page with the given parameter will open.
The deep link user sends to his friends is:
Intent sharingIntent = new Intent(android.content.Intent.ACTION_SEND);
sharingIntent.setType("text/plain");
String shareBody = "https://shareemotion.page.link/mood?mood=Sad&bottomneg=2";
sharingIntent.putExtra(android.content.Intent.EXTRA_SUBJECT, "Subject Here");
sharingIntent.putExtra(android.content.Intent.EXTRA_TEXT, shareBody);
context.startActivity(Intent.createChooser(sharingIntent, "Share via"));
While the dynamic link in firebase is:
https://www.myapp.com/?mood=Happy&bottomneg=2
And the code for getting data from link is :
FirebaseDynamicLinks.getInstance()
.getDynamicLink(getIntent())
.addOnSuccessListener(this, new OnSuccessListener<PendingDynamicLinkData>() {
#Override
public void onSuccess(PendingDynamicLinkData pendingDynamicLinkData) {
// Get deep link from result (may be null if no link is found)
Uri deepLink = null;
if (pendingDynamicLinkData != null) {
deepLink = pendingDynamicLinkData.getLink();
}
if(deepLink!=null)
{
String mood = deepLink.getQueryParameter("mood");
String bottomId = deepLink.getQueryParameter("bottomneg");
NewActivity(mood, bottomId);
}
}
})
.addOnFailureListener(this, new OnFailureListener() {
#Override
public void onFailure(#NonNull Exception e) {
Log.e( "getDynamicLink", " "+e);
}
});
So Now when I share the link with mood=Sad the app run but at the fetching point it fetches "Happy"(which is present in the dynamic link) but I want to fetch mood=Sad from the link that sends to another user.
Note
mood=Sad will replace by variable, for now, it uses for testing purposes.
Related
Register Button in Register Acvtivity
public void registerBtnClicked(View view){
String email = binding.userEmailEditText.getText().toString();
String password = binding.userPasswordEditText.getText().toString();
String userNameData = binding.usernameEditText.getText().toString();
user = new Users(userNameData,email,password);
db = FirebaseDatabase.getInstance();
databaseReference = db.getReference(Users.class.getSimpleName());
databaseReference.push().setValue(user);
if(email.equals("") || password.equals("")){
Toast.makeText(this, "Enter email and password", Toast.LENGTH_LONG).show();
}else{
auth.createUserWithEmailAndPassword(email,password).addOnSuccessListener(new OnSuccessListener<AuthResult>() {
#Override
public void onSuccess(AuthResult authResult) {
Intent intent = new Intent(RegisterPage.this, MainActivity.class);
startActivity(intent);
finish();
}
}).addOnFailureListener(new OnFailureListener() {
#Override
public void onFailure(#NonNull Exception e) {
Toast.makeText(RegisterPage.this, e.getLocalizedMessage(),Toast.LENGTH_LONG).show();
}
});
}
}
I created a real time database.But I couldn't figure out how to show username in navigation header section. Can you help me?
If I understand correctly, the firebaseUser is null when you're trying to read the display name from it. This is actually a common scenario, as the user's sign-in session is managed by Firebase in the background, and the current user may change at any time.
The simple fix is to check whether there is a current user before accessing their display name, which you can do with:
firebaseUser = FirebaseAuth.getInstance().getCurrentUser();
if (firebaseUser != null) {
navUserEmail.setText(firebaseUser.getEmail());
navUserName.setText(firebaseUser.getDisplayName());
}
Note though that the display name is an optional property of the user profile, so it can indeed be null. If you want to display nothing in that case, you can do:
String displayName = firebaseUser.getDisplayName();
navUserName.setText(displayName != null ? displayName : "");
Even if you've set the display name of a user, it may take up to an hour until that is updated for all connected clients, as they all cache the user profile. And since such updates happen in the background... 👇
To correctly handle all auth state changes, you'll want to use an auth state listener, as shown in this article: https://stackoverflow.com/collectives/google-cloud/articles/68104924/listen-for-authentication-state-in-android
I'm successfully creating a Firebase dynamic link in Java on Android. My code to do so is in a button click listener.
shareButton.setOnClickListener(new View.OnClickListener()
{
#Override
public void onClick(View v)
{
DynamicLink dynamicLink = FirebaseDynamicLinks.getInstance().createDynamicLink()
.setLink(Uri.parse("https://www.mycompany.com/"))
.setDomainUriPrefix("https://mycompany.page.link/test")
.setAndroidParameters(
new DynamicLink.AndroidParameters.Builder("com.mycompany.app")
.setFallbackUrl(Uri.parse("https://www.mycompany.com/"))
.setMinimumVersion(1)
.build())
.buildDynamicLink();
Uri dynamicLinkUri = dynamicLink.getUri();
shareDynamicLink(dynamicLinkUri);
}
});
public void shareDynamicLink(Uri dynamicLink)
{
Intent shareIntent = new Intent();
String msg = "Check this out: " + dynamicLink;
shareIntent.setAction(Intent.ACTION_SEND);
shareIntent.putExtra(Intent.EXTRA_TEXT, msg);
shareIntent.setType("text/plain");
startActivity(shareIntent);
}
This sends a LONG dynamic link that works just fine. Now I'd like to shorten the link, so I replaced the 'shareDynamicLink' method with this code.
public void shareDynamicLink(Uri dynamicLink)
{
Task<ShortDynamicLink> shortLinkTask = FirebaseDynamicLinks.getInstance().createDynamicLink()
.setLongLink(dynamicLink)
.buildShortDynamicLink()
.addOnCompleteListener(Objects.requireNonNull(this.getActivity()), new OnCompleteListener<ShortDynamicLink>()
{
#Override
public void onComplete(#NonNull Task<ShortDynamicLink> task)
{
if (task.isSuccessful())
{
// Short link created
Uri shortLink = Objects.requireNonNull(task.getResult()).getShortLink();
Uri flowchartLink = task.getResult().getPreviewLink();
Log.e("DynamicLink", "shortLink: " + shortLink + System.lineSeparator());
Log.e("DynamicLink", "flowChartLink: " + flowchartLink + System.lineSeparator());
Intent shareIntent = new Intent();
String msg = "Check this out: " + shortLink;
shareIntent.setAction(Intent.ACTION_SEND);
shareIntent.putExtra(Intent.EXTRA_TEXT, msg);
shareIntent.setType("text/plain");
startActivity(shareIntent);
}
else
{
Toast.makeText(context, "Failed to share event.", Toast.LENGTH_SHORT).show();
}
}
});
}
This second method produces an error that I don't understand.
"400: Cannot shorten a short Dynamic Link:
https://mycompany.page.link/test?afl=https%3A%2F%2Fwww.mycompany.com%2F&amv=1
&apn=com.mycompany.app&ibi=com.mycompany.app&ifl=https%3A%2F%2F
www.mycompany.com%2F&isi=963543827&ipfl=https%3A%2F%2F
www.mycompany.com%2F&link=https%3A%2F%2Fwww.mycompany.com%2F
[https://firebase.google.com/docs/dynamic-links/rest#create_a_short_link_from_parameters]
What am I missing here? This seems like it should work.
Note: I don't need the long dynamic link, just the short one. I tried changing the onClickListener as follows.
shareButton.setOnClickListener(new View.OnClickListener()
{
#Override
public void onClick(View v)
{
Task<ShortDynamicLink> dynamicLink = FirebaseDynamicLinks.getInstance().createDynamicLink()
.setLink(Uri.parse("https://www.mycompany.com/"))
.setDomainUriPrefix("https://mycompany.page.link/test")
.setAndroidParameters(
new DynamicLink.AndroidParameters.Builder("com.mycompany.app")
.setFallbackUrl(Uri.parse("https://www.mycompany.com/"))
.setMinimumVersion(1)
.build())
.buildShortDynamicLink()
.addOnCompleteListener(Objects.requireNonNull(getActivity()), new OnCompleteListener<ShortDynamicLink>()
{
#Override
public void onComplete(#NonNull Task<ShortDynamicLink> task)
{
if (task.isSuccessful())
{
Uri shortLink = Objects.requireNonNull(task.getResult()).getShortLink();
Uri flowchartLink = task.getResult().getPreviewLink();
Log.e("DynamicLink", "shortLink: " + shortLink + System.lineSeparator());
Log.e("DynamicLink", "flowChartLink: " + flowchartLink + System.lineSeparator());
}
else
{
Log.e("DynamicLink", "Link failed: " + task.getException().getMessage() + System.lineSeparator());
}
}
});
}
});
But I still get the same 400 error.
400: Cannot shorten a short Dynamic Link:
https://mycompany.page.link/test?afl=https%3A%2F%2Fwww.mycompany.com%2F&amv=1
&apn=com.mycompany.app&ibi=com.mycompany.app&ifl=https%3A%2F%2F
www.mycompany.com%2F&isi=963543827&ipfl=https%3A%2F%2Fwww.mycompany.com%2F
&link=https%3A%2F%2Fwww.mycompany.com%2F
[https://firebase.google.com/docs/dynamic-links/rest#create_a_short_link_from_parameters]
For anyone who finds this, my problem stemmed from a misunderstanding of how programmatically generated links work vs. predefined links. In my case I was trying to use a pre-defined link from the Firebase console ("https://mycompany.page.link/test") as the PREFIX for my generated link. That caused some sort of confusion on the back end when I tried to shorten it. I still don't understand exactly what it didn't like, but point is it failed.
So the solution for generating links was to use only the base prefix from the Firebase console - .setDomainPrefix("https://mycompany.page.link/"). Using that I can create either ".buildShortDynamicLink()" or "buildDynamicLink()".
The link I created in the Firebase console ("http://mycompany.page.link/test") can only be used verbatim -- no need to generate anything. Just put it in a text message literally and you're done.
Are you going to use the longer version at all, or only the short one? If so, does it work if you use .buildShortDynamicLink() instead of .buildDynamicLink() in your onClick(...) method without the conversion in shareDynamicLink(...)?
Please am very new to java, am trying to put my website in webview, i have few lines of code that send user to email form and is working very fine. But now i have to use the same code in more than 3 place when url match something and i know that there will be a way to put this code one place as a function then call it and time i want to use it. please can someone help me.
function RequestMailForm(newbody, newsubject, newemailto, newmailbbc){
/* That email code*/
}
mva.setWebViewClient(new WebViewClient() {
if (url.startsWith("mailto:")) {
url = url.substring(7);
String body = "Body of message.";
Intent mail = new Intent(Intent.ACTION_SEND);
mail.setType("application/octet-stream");
mail.putExtra(Intent.EXTRA_EMAIL, new String[] { url });
mail.putExtra(Intent.EXTRA_SUBJECT, "Subject");
mail.putExtra(Intent.EXTRA_TEXT, body);
startActivity(mail);
return true;
}
if (url.startsWith("http://example.com/help") || url.startsWith("https://example.com/contact")){
RequestMailForm(newbody, newsubject, newemailto, newmailbbc);
}
});
Create a class and put sendEmail method with message and email paramater.
See the code below.
class SendEmail {
Context context;
public SendEmail(Context context){
this.context = contex;
}
//send an email
public void send(String email) {
Intent emailIntent = new Intent(Intent.ACTION_SENDTO, Uri.fromParts(
"mailto", email, null));
intent.setType("message/rfc822");
intent.putExtra(Intent.EXTRA_SUBJECT, "Subject");
intent.putExtra(Intent.EXTRA_TEXT, "Body of message");
context.startActivity(Intent.createChooser(emailIntent, "Send email..."));
}
}
Then create an object of the SendEmail class and call that function every time you want to send an email like this:
if (url.startsWith("mailto:")) {
url = url.substring(7);
sendEmail.send(url);
return true;
}
I have an android app that is connected to an API through retrofit, ive succesfully logged in, if i press back button to return back to the login activity again, if i try re-logging in again, the app crashes and give me a NullPointerException.
here's connection code
private void loginUser(String email, String password) {
UnifyAuthenticationApiInterface service = this.client.create(UnifyAuthenticationApiInterface.class);
Call<UnifyAuthenticationApiResponse> call = service.staffLogin(email, password);
call.enqueue(new Callback<UnifyAuthenticationApiResponse>() {
#Override
public void onResponse(Call<UnifyAuthenticationApiResponse> call,
Response<UnifyAuthenticationApiResponse> response) {
UnifyAuthenticationApiResponse result = response.body();
School school = new School();
com.peterstev.unify.login.Data data = result.getData();
mySchoolsList = new ArrayList<School>();
mySchoolsList = data.getSchools();
staff = data.getStaff();
gotoHomeActivity();
}
#Override
public void onFailure(Call<UnifyAuthenticationApiResponse> call, Throwable t) {
progressDialog.dismiss();
Toast.makeText(MainActivity.this, "Login Failed # onFailure", Toast.LENGTH_SHORT).show();
}
});
}
and the goToHomeActivity() is
private void gotoHomeActivity() {
progressDialog.dismiss();
if (mySchoolsList.size() > 1) {
schoolsListView = new ListView(MainActivity.this);
schoolsArrayAdapter = new SchoolListAdapter(MainActivity.this, android.R.layout.simple_list_item_1, mySchoolsList);
schoolsListView.setAdapter(schoolsArrayAdapter);
dialog = new Dialog(MainActivity.this);
dialog.setContentView(schoolsListView);
dialog.setTitle("Welcome " + staff.getFullName());
dialog.show();
} else {
Intent intent = new Intent(MainActivity.this, NavMainActivity.class);
startActivity(intent);
}
}
the NullPointerException gets thrown at
com.peterstev.unify.login.Data data = result.getData();
at first, it gets the data n succesfully logs in, but when i use the back button n try to log in again it crashes.
Debugger is your answer - check if you aren't loosing any data when going back - maybe you're storing login params somewhere in activity class but you're not saving instance state properly and second request is triggered without necessary data. Check state of variables just before calling your request first and second time.
In situation like that always best bet to place breakpoint and trigger your work step by step. You cannot be good developer without debugger skills.
I think for some reason, the data object wasn't receiving the result when i used the back button to navigate to the parent activity. so i used and if condition to make it get the required data.
private void loginUser(String email, String password) {
UnifyAuthenticationApiInterface service = this.client.create(UnifyAuthenticationApiInterface.class);
Call<UnifyAuthenticationApiResponse> call = service.staffLogin(email, password);
call.enqueue(new Callback<UnifyAuthenticationApiResponse>() {
#Override
public void onResponse(Call<UnifyAuthenticationApiResponse> call,
Response<UnifyAuthenticationApiResponse> response) {
if(response.isSuccessful()) {
UnifyAuthenticationApiResponse result = response.body();
School school = new School();
data = result.getData();
if(data == null) {
try{
this.onResponse(call, response);
}catch(NullPointerException NPE){
Log.d("NPE", NPE.getMessage());
}
}
mySchoolsList = new ArrayList<School>();
mySchoolsList = data.getSchools();
staff = data.getStaff();
gotoHomeActivity();
}
}
#Override
public void onFailure(Call<UnifyAuthenticationApiResponse> call, Throwable t) {
progressDialog.dismiss();
Toast.makeText(MainActivity.this, "Login Failed # onFailure", Toast.LENGTH_SHORT).show();
}
});
}
I have this code working well on Android 4.0.4.
// Create the new Intent using the 'Send' action.
Intent share = new Intent(Intent.ACTION_SEND);
// Set the MIME type
share.setType(type);
// Create the URI from the media
java.io.File media = new java.io.File(mediaPath);
Uri uri = Uri.fromFile(media);
// Add the URI and the caption to the Intent.
share.putExtra(Intent.EXTRA_STREAM, uri);
share.putExtra(Intent.EXTRA_TEXT, caption);
// Broadcast the Intent.
mActivity.startActivity(Intent.createChooser(share, "Share to"));
But on Android 4.4.2 it crashes the Facebook app. Facebook app opens, the image is not shown and the FB app is dead.
In log dump I've noticed this message:
E/JHEAD ( 5850): can't open '/data/data/cz.volten.brili.android.free/files/product_preview_shared.jpg'
V/ContextImpl( 5850): ----- packageName = com.facebook.katana is NOT LOCKED -----
Could the reason be some security restrictions, e.g. The FB app does not have rights to access the image in the application folder even though it is invoked from an intent?
If so, what would be a proper location for an image shared between the apps?
Shall I use something like this: how to share image to facebook via intent
Could the reason be some security restrictions, e.g. The FB app does not have rights to access the image in the application folder even though it is invoked from an intent?
Correct. That image is on internal storage for your app, which is private to your app.
If so, what would be a proper location for an image shared between the apps?
You can stick with internal storage, though you will need to use a FileProvider, perhaps with my LegacyCompatCursorWrapper, to serve the file. This sample app demonstrates this, albeit with a PDF rather than an image.
Or, put the file on external storage.
Shall I use something like this: how to share image to facebook via intent
You could, though that would seem to be overkill, compared to using FileProvider.
This is what I usually use
private void initShareIntent(String type) {
boolean found = false;
Intent share = new Intent(android.content.Intent.ACTION_SEND);
share.setType("image/jpeg");
// gets the list of intents that can be loaded.
List<ResolveInfo> resInfo = getPackageManager().queryIntentActivities(share, 0);
if (!resInfo.isEmpty()) {
for (ResolveInfo info : resInfo) {
if (info.activityInfo.packageName.toLowerCase().contains(type) ||
info.activityInfo.name.toLowerCase().contains(type)) {
share.putExtra(Intent.EXTRA_TEXT, "Elevator Express");
share.putExtra(Intent.EXTRA_STREAM, Uri.fromFile(new File(imagePath))); // Optional, just if you wanna share an image.
share.setPackage(info.activityInfo.packageName);
found = true;
break;
}
}
if (!found) {
Toast.makeText(getApplicationContext(), "Facebook does not exist", Toast.LENGTH_SHORT).show();
return;
}
startActivity(Intent.createChooser(share, "Select"));
}
}
and call it like this :
iniShareIntent("face");
This code works for me.....here "updateImage" is my image location.
if (isFacebookExist()) {
if (hashClick.isChecked()) {
SharePhoto sharePhoto = new SharePhoto.Builder()
.setBitmap(updateImage)
.build();
if (ShareDialog.canShow(SharePhotoContent.class)) {
SharePhotoContent content = new SharePhotoContent.Builder()
.addPhoto(sharePhoto)
.setShareHashtag(new ShareHashtag.Builder()
.setHashtag("#HashTag")
.build())
.build();
shareDialog.show(content);
}
} else {
SharePhoto sharePhoto = new SharePhoto.Builder()
.setBitmap(updateImage)
.build();
if (ShareDialog.canShow(SharePhotoContent.class)) {
SharePhotoContent content = new SharePhotoContent.Builder()
.addPhoto(sharePhoto)
.build();
shareDialog.show(content);
}
}
} else {
showToast(" Facebook is not install.");
}
private boolean isFacebookExist() {
PackageManager pm = getPackageManager();
try {
PackageInfo info = pm.getPackageInfo("com.facebook.katana", PackageManager.GET_META_DATA);
} catch (PackageManager.NameNotFoundException e) {
return false;
}
return true;
}