How to stop sound from 1st activity when clicking on new activity - android-mediaplayer

I'm working on Media player App when I choose a song from the list it plays fine but when I choose another song the fist one doesn't stop playing .
I tried finish(); but didn't work .
its one Player Layout resource file and multiple Java classes.
public void s2 (View view){
Intent intent = new Intent(s1.this, s2.class);
startActivity(intent);
this.finish();
}

If you are using MediaPlayer class to play a song, you should add player.stop() call to your activity destructor.

Related

Xamarin.Forms Communication Between Two Pages Within Same App on Different Devices

Technologies, frameworks and devices I'm using:
Framework: Xamarin.Forms
IDE: Visual Studio 2022
Physical Device (smartphone): Zebra TC26 (Android 10)
Physical Device (smartwatch): Samsung Galaxy Watch4 (Android 11)
Problem definition
Currently I have a test Xamarin.Forms project that consists of two different UIs (XAML files):
User Interface 1: HomePage.XAML - This screen should be displayed on the smartphone
User Interface 2: WatchScreen.XAML - This screen should be displayed on the smartwatch
With code below I make sure HomePage.XAML is deployed to a smartphone and watchscreen is deployed to a smartwatch:
Page homePage = new NavigationPage(new HomePage());
// BuildVersionCodes.R is a reference to Android version 11 (mostly now used by Wear OS 3.x)
if (Build.VERSION.SdkInt == BuildVersionCodes.R)
{
// SM-R870 is a reference to the Samsung Galaxy Watch4
// Note: This is needed to ensure the UI is specific to the UI of a smartwatch
if (Build.Model == "SM-R870")
{
Page watchScreen = new NavigationPage(new WatchScreen());
MainPage = watchScreen;
}
}
else
{
MainPage = homePage;
}
Now I want to make these pages on different devices communicate with each other. HomePage.xaml exists within the main Xamarin.Forms project as well as WatchScreen.xaml.
The way I want them to communicate with each other is by sending a message or something. A Xamarin.Forms project also comes with a native project. In this native Xamarin.Android project I try to retrieve inside the MainActivity.cs the button that exists within the main project by using (in WatchScreen.xaml this button exists and in WatchScreen.xaml.cs I have a method that gives this button back).
Method in WatchScreen.xaml.cs that gives button back:
public Button GetSendButtonFromWearableUI() => btnSendMessage;
In MainActivity.cs I get this method by using:
Button button = (App.Current.MainPage.Navigation.NavigationStack.LastOrDefault() as WatchScreen)
.GetSendButtonFromWearableUI();
Whenever I click on the button by doing this:
button.Clicked += delegate
{
SendData();
};
Some data should be sent from MainActivity.cs and catched by HomePage.xaml and displayed on it. I tried several approaches but I didn't succeed in achieving what needs to happen.. Therefore, I'm wondering if you guys could help me out with this and would be much appreciated.
In the meantime I've been investigating this issue and came up with a solution. Follow steps below to get the same result. To make this solution work I've combined the Wearable Data Layer API from Google and MessagingCenter from Microsoft.
Also the example below shows only the communication from the smartwatch to the smartphone. In order to reverse processes you can put the send button on the HomePage instead of the smartwatch screen and make sure to subscribe to the correct messages.
One last note: keep in mind that code used below from Google is deprecated but it still works...
References used to make this work:
Syncing Data Between Wearable and Handheld Devices Using Xamarin in Android
Installed dependencies on the Xamarin.Android project within Xamarin.Forms project:
Xamarin.Android.Support.v4
Xamarin.GooglePlayServices.Base
Xamarin.GooglePlayServices.Wearable
MessageKeys.cs
This class is used to declare message keys that are being used to send and receive messages between devices.
public class MessageKeys
{
public const string Smartwatch = "Smartwatch";
public const string Smartphone = "Smartphone";
}
Xamarin.Forms (Base project) - App.xaml.cs
In the App.xaml.cs, as pointed out earlier, I'm making sure the wearable UI displays WatchScreen.xaml and any other devices display regular Android UI -> HomePage.xaml.
Xamarin.Forms (Base project) - WatchScreen.xaml.cs
Send message from Wearable device to Android smartphone.
private void btnSendMessage_Clicked(object sender, EventArgs e)
{
MessagingCenter.Send(Xamarin.Forms.Application.Current, MessageKeys.Smartwatch);
}
Xamarin.Forms (Base project) - HomePage.xaml.cs
public HomePage()
{
InitializeComponent();
MessagingCenter.Subscribe<Xamarin.Forms.Application>(Xamarin.Forms.Application.Current, MessageKeys.Smartphone, (sender) =>
{
DisplayAlert("Message", "Wearable message received!", "OK");
});
}
Xamarin.Forms (Native Android Project) - MainActivity.cs
Within MainActivity.cs I implement the following interfaces:
public class MainActivity : WearableActivity, DataClient.IOnDataChangedListener,
GoogleApiClient.IConnectionCallbacks, GoogleApiClient.IOnConnectionFailedListener
Variables:
private GoogleApiClient client;
const string syncPath = "/[project name]/[subdirectory for watch]";
Internal class 'MessageReceiver' for receiving broadcast messages:
[BroadcastReceiver]
public class MessageReciever : BroadcastReceiver
{
MainActivity main;
public MessageReciever() { }
public MessageReciever(MainActivity owner) { this.main = owner; }
public override void OnReceive(Context context, Intent intent)
{
main.ProcessMessage(intent);
}
}
Registering receiver (to receive through Wearable Data Layer API), creating Google Client and Subscribing to smartwatch message (to retrieve message through MessagingCenter)
protected override void OnCreate(Bundle bundle)
{
IntentFilter filter = new IntentFilter(Intent.ActionSend);
MessageReciever receiver = new MessageReciever(this);
LocalBroadcastManager.GetInstance(this).RegisterReceiver(receiver, filter);
client = new GoogleApiClient.Builder(this, this, this)
.AddApi(WearableClass.Api)
.Build();
MessagingCenter.Subscribe<Xamarin.Forms.Application>(Xamarin.Forms.Application.Current, MessageKeys.Smartwatch, (sender) =>
{
SendData();
});
}
ProcessMessage method: sends received message from wearable to smartphone
public void ProcessMessage(Intent intent)
{
// For now I'm not sending the payload...
string message = intent.GetStringExtra("WearMessage");
MessagingCenter.Send(Xamarin.Forms.Application.Current, MessageKeys.Smartphone);
}
SendData(), OnStart(), OnStop(), OnDataChanged (didn't do anything with this part, because this is to receive messages outside the project and I don't need it for now), OnConnected(), OnConnectionSuspended(), OnConnectionFailed():
See the reference to see what code has been used, since code is exactly the same... P.S.: one thing for SendData has been changed. If you want to keep sending data, remove 'client.Disconenct()' from finally after the try and catch block.
Xamarin.Forms (Native Android Project) - WearableService inherits from WearableListenerService:
WearableService is a new class and created within the native project. Also for this part see the reference, because it's the exact same code being used within my project.
To get an overall overview of what's happening, I've visualized this in the diagram below: (example shows how communication works from smartwatch to smartphone)
If you want to communicate from smartphone to smartwatch, you could do something like this:
That's it guys. Now you will receive messages within the same application using the Wearable Data Layer API and MessagingCenter. Instead of having separate projects, we just use separate UIs to make this happen...

Open Android activity automatically on receiving notification

I have to launch the app on receiving notification. The following piece of code works fine when the app is killed and notification is received (i.e the code inside if condition). But when the app is running in foreground or background, multiple instances of the activity gets created(i.e snippet in else condition). It's not the MainActivity that has to be launched on receiving the notification, instead it's some other activity containing the broadcast Receiver.
I have added the following lines in the onMessage of GCMintentService class.
if (currentPackage.equalsIgnoreCase(context.getPackageName()
.toString())) {
broadcastMessage(context, message);
} else {
Intent mIntent = new Intent(context, MainActivity.class);
mIntent.setAction(Intent.ACTION_MAIN);
mIntent.addCategory(Intent.CATEGORY_LAUNCHER);
mIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
context.startActivity(mIntent);
}
In the activity, under onReceive method of BroadcastReceiver, i am starting the activity again.
private final BroadcastReceiver mHandleMessageReceiver = new BroadcastReceiver() {
#Override
public void onReceive(Context context, Intent intent) {
startActivity(getIntent().setFlags(Intent.FLAG_ACTIVITY_REORDER_TO_FRONT));
}
};
I also had this requirement in one of my application. We can achieve it if we call
Intent mIntent = new Intent(context, MainActivity.class);
mIntent.setAction(Intent.ACTION_MAIN);
mIntent.addCategory(Intent.CATEGORY_LAUNCHER);
mIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
context.startActivity(mIntent);
broadcastMessage(context, message);
In the main activity use the following in the broadcast receiver that would receive the broadcasted message above.
WakeLock wakeLock = null;
KeyguardManager kgMgr = (KeyguardManager) getSystemService(Context.KEYGUARD_SERVICE);
boolean locked = kgMgr.inKeyguardRestrictedInputMode();
PowerManager pm = (PowerManager) context
.getSystemService(Context.POWER_SERVICE);
if (!pm.isScreenOn()) {
wakeLock = pm.newWakeLock(PowerManager.FULL_WAKE_LOCK
| PowerManager.ACQUIRE_CAUSES_WAKEUP, "MyWakeLock");
wakeLock.acquire();
}
if (locked) {
Window mWindow = getWindow();
mWindow.addFlags(WindowManager.LayoutParams.FLAG_SHOW_WHEN_LOCKED);
mWindow.addFlags(WindowManager.LayoutParams.FLAG_TURN_SCREEN_ON);
}
Personally I feel that this is not the best of the answers and also best of the ideas to open the app directly when received a notification as there will be many functions like onCreate onResume, will be triggered automatically, spoil the users work if they are in a really important work by opening another app directly, also we need to put a lot of flags or use any other method to manage the flow of the application, when user open the app, app comes from background, app opened due notification and all such cases. Avoid it as it spoils the whole user experience.

receive all connected players on google play services realtime multiplayer game

is there a way to get a list of all the ids of the players that are connected and near the user that is playing my realtime multiplayer game?
I already tried Games.Players.loadConnectedPlayers() method, but i donĀ“t know how to use its PendingResult
I wanna use public RoomConfig.Builder addPlayersToInvite (ArrayList playerIds)
to make the user play with only specific players
You can use result callback as follows:
Games.Players.loadConnectedPlayers(mHelper.getApiClient(), false).setResultCallback(
new ResultCallback<Players.LoadPlayersResult>() {
#Override
public void onResult(LoadPlayersResult arg0) {
// TODO Auto-generated method stub
}
});

Google Play Services - Sending A Rematch Request

After a multiplayer game is over, is there any possibility of sending a rematch request to the same participants?
Note that this is not provided by the Google API, I am wondering if people have any ideas on implementing such a system.
Thanks,
Rajat
If you just want a solution to inviting all the same people from the previous game.. this works for the player that initiated that initiated the game:
When you get back the Intent from selecting the players.. just save it:
// Handle the result of the "Select players UI" we launched when the user clicked the
// "Invite friends" button. We react by creating a room with those players.
private void handleSelectPlayersResult(int response, Intent data) {
if (response != Activity.RESULT_OK) {
Log.w(TAG, "*** select players UI cancelled, " + response);
Gdx.app.postRunnable(new Runnable() {
#Override
public void run() {
mGHInterface.onBackedOut();
}
});
return;
}
Log.d(TAG, "Select players UI succeeded.");
previousMatch = data;
// get the invitee list ...(etc, etc)
Then, whatever way you want to activate the next bit of code works:
#Override
public void sendOutRematch() {
handleSelectPlayersResult(Activity.RESULT_OK, previousMatch);
}
Now, for players that are invited to the room... need to look at the Room object for them, and get the invited player id's from that object.. and save that list of players so it can be used in the Room Creation process with something like this to grab the ids :
ArrayList<String> playerIDs;
for (Participant p : room.getParticipants()) {
playerIDs.add(p.getPlayer().getPlayerId());
}
then use that list in your room creation process.

Camera application for all Android devices

I'm currently developing a camera application for Android on which some problems have occurred. I need it to work on all Android devices and since all of these works in different ways specially with the camera hardware, I'm having a hard time finding a solution that works for every device.
My application main goal is to launch the camera on a button click, take a photo and upload it to a server. So I don't really need the functionality of saving the image on the device, but if that's needed for further image use I might as well allow it.
For example I'm testing my application on a Samsung Galaxy SII and a Motorola Pad. I got working code that launches the camera, which is by the way C# code since I'm using Monodroid:
Intent cameraIntent = new Intent(Android.Provider.MediaStore.ActionImageCapture);
StartActivityForResult(cameraIntent, PHOTO_CAPTURE);
And I fetch the result, similar to this guide I followed:
http://kevinpotgieter.wordpress.com/2011/03/30/null-intent-passed-back-on-samsung-galaxy-tab/
Why I followed this guide is because the activity returns null on my galaxy device (Another device oriented problem).
This code works fine on the Galaxy device. It takes a photo and saves the photo in the gallery from which i can upload to a server. By further research this is apparently galaxy standard behaviour, so this doesn't work on my Motorola pad. The camera works fine, but no image is saved to gallery.
So with this background my question is, am I on the right path here? Do I need to save the image to gallery in order for further use in my application? Is there any solution that works for every Android device, cause that's the solution i need.
Thanks for any feedback!
After reading the linked article, the approach taken in that article is geared toward the Galaxy line, since they appear to write to the gallery automatically.
This article discusses some other scenarios in detail:
Android ACTION_IMAGE_CAPTURE Intent
So, I don't necessarily think that following the linked article that you provided is the right path. Not all devices automatically write to the gallery as described in that article, afaik. The article I linked to points to the issues being related to security and suggests writing the image to a /sdcard/tmp folder for storing the original image. Going down a similar path would more than likely lead to code that is going to work reliably across many devices.
Here are some other links for reference:
Google discussion regarding this subject: http://code.google.com/p/android/issues/detail?id=1480
Project with potential a solution to the problem: https://github.com/johnyma22/classdroid
While that discussion/project are in Java/Android SDK, the same concepts should apply to Monodroid. I'd be happy to help you adapt the code to a working Mono for Android solution if you need help.
To long2know:
Yes the same concepts applies to Monodroid. I've already read the stack article you linked among with some other similar. However i don't like the approach in that particular post since it checks for bugs for some devices that are hardcoded into a collection. Meaning it might fail to detect bugs in future devices. Since i won't be doing maintenance on this application, i can't allow this. I found a solution elsewhere and adapted it to my case and i'll post it below if someone would need it. It works on both my devices, guessing it would work for the majority of other devices. Thanks for your post!
Solution that allows you to snap a picture and use, also with the option of using a image from gallery. Solution uses option menu for these purposes, just for testing. (Monodroid code).
Camera code is inspired by:
access to full resolution pictures from camera with MonoDroid
namespace StackOverFlow.UsingCameraWithMonodroid
{
[Activity(Label = "ImageActivity")]
public class ImageActivity
private readonly static int TakePicture = 1;
private readonly static int SelectPicture = 2;
private string imageUriString;
protected override void OnCreate(Bundle bundle)
{
base.OnCreate(bundle);
this.SetContentView(Resource.Layout.ImageActivity);
}
public override bool OnCreateOptionsMenu(IMenu menu)
{
MenuInflater flate = this.MenuInflater;
flate.Inflate(Resource.Menu.ImageMenues, menu);
return base.OnCreateOptionsMenu(menu);
}
public override bool OnOptionsItemSelected(IMenuItem item)
{
switch (item.ItemId)
{
case Resource.Id.UseExisting:
this.SelectImageFromStorage();
return true;
case Resource.Id.AddNew:
this.StartCamera();
return true;
default:
return base.OnOptionsItemSelected(item);
}
}
private Boolean isMounted
{
get
{
return Android.OS.Environment.ExternalStorageState.Equals(Android.OS.Environment.MediaMounted);
}
}
private void StartCamera()
{
var imageUri = ContentResolver.Insert(isMounted ? MediaStore.Images.Media.ExternalContentUri
: MediaStore.Images.Media.InternalContentUri, new ContentValues());
this.imageUriString = imageUri.ToString();
var cameraIntent = new Intent(MediaStore.ActionImageCapture);
cameraIntent.PutExtra(MediaStore.ExtraOutput, imageUri);
this.StartActivityForResult(cameraIntent, TakePicture);
}
private void SelectImageFromStorage()
{
Intent intent = new Intent();
intent.SetType("image/*");
intent.SetAction(Intent.ActionGetContent);
this.StartActivityForResult(Intent.CreateChooser(intent,
"Select Picture"), SelectPicture);
}
// Example code of using the result, in my case i want to upload in another activity
protected override void OnActivityResult(int requestCode, Result resultCode, Intent data)
{
// If a picture was taken
if (resultCode == Result.Ok && requestCode == TakePicture)
{
// For some devices data can become null when using the camera activity.
// For this reason we save pass the already saved imageUriString to the upload activity
// in order to adapt to every device. Instead we would want to use the data intent
// like in the SelectPicture option.
var uploadIntent = new Intent(this.BaseContext, typeof(UploadActivity));
uploadIntent.PutExtra("ImageUri", this.imageUriString);
this.StartActivity(uploadIntent);
}
// User has selected a image from storage
else if (requestCode == SelectPicture)
{
var uploadIntent = new Intent(this.BaseContext, typeof(UploadActivity));
uploadIntent.PutExtra("ImageUri", data.DataString);
this.StartActivity(uploadIntent);
}
}
}
}