I am using some example code from the internet that manages music. One section of the code is a way of pausing music and preparing it to play again. I am not understanding a double bracket notation. I thought it may have been a fancy way of doing an If-Else, but my equivalent snippet of code does not work, however, the code with the double brackets works perfectly. What exactly does it mean when you add two open brackets to an If-statement?
Here is the snippet of code
// previousMusic should always be something valid
if (currentMusic != -1) {{
previousMusic = currentMusic;
Log.d(TAG, "Music is paused");
}
currentMusic = -1;
Log.d(TAG, "Paused music is prepared to play again (if necessary)");
}
Here is what I thought it could have meant. It does not work as intended, so this is not the same actually.
// previousMusic should always be something valid
if (currentMusic != -1) {
previousMusic = currentMusic;
Log.d(TAG, "Music is paused");
} else {
currentMusic = -1;
Log.d(TAG, "Paused music is prepared to play again");
}
Thank you in advance for the explanation.
hat exactly does it mean when you add two open brackets to an If-statement?
Nothing special really it is just a block of code where you put your previousMusic = currentMusic in another scope of the method.
It is like saying:
if (currentMusic != -1) {
previousMusic = currentMusic;
Log.d(TAG, "Music is paused");
currentMusic = -1;
Log.d(TAG, "Paused music is prepared to play again (if necessary)");
}
But if you make a variable inside the block of code then you cant access it outside the block because the scope of the variable is only accessible to the block of code.
if(1==1)
{
int i2;
{
int i;
i2= 1; //can access from top level scope
}
i = 0; //compile time error cant access the variable in the block of code
}
I hope you are aware about the scope of variables.
Example 1:
if(some condition){
{ // x is born here
int x = 32;
} // x is dead here
// not allowed!
Log.d(TAG,"Value is: " + x);
}
Example 2:
if(some condition){
int x = 32;
// totally legit!
Log.d(TAG,"Value is: " + x);
}
See the subtle difference between the two?
In Example 1, the nested {} limit the scope of x. The variable x is available for use only till the closing brace } of its corresponding opening brace {
The correct way to understand that code is:
if (currentMusic != -1) {
{
previousMusic = currentMusic;
Log.d(TAG, "Music is paused");
}
currentMusic = -1;
Log.d(TAG, "Paused music is prepared to play again (if necessary)");
}
When you put a braces in your code, you just create a new scope to handle your variables.
Related
In my Android Auto projection-type app I am trying to get info on the car I am attached to. Preferably manufacturer or other VHAL type parameters. Speed, tach, gear position etc would be nice too.
Is this possible in Android Auto?
I tried:
car = Car.createCar(getCarContext());
CarInfoManager carInfoManager = (CarInfoManager) car.getCarManager(Car.INFO_SERVICE);
but I get an exception on Car.createCar
I am trying this code in the onCreateSession in the CarAppService with no luck
Two previous answers to my question from other people got deleted. No idea why, but they gave me the hints I needed to fix the code and get it working.
in the CarAppService implementation, in the
public Session onCreateSession() {
at the end where I do:
return new Session() {
I have a block of code like this:
CarInfo carInfo =
getCarContext().getCarService(CarHardwareManager.class).getCarInfo();
mCarHardwareExecutor = ContextCompat.getMainExecutor(getCarContext());
OnCarDataAvailableListener<Model> mModelListener = data -> {
synchronized (this) {
String statusText = "" + data.getYear().getValue() + " " + data.getManufacturer().getValue() + " " + data.getName().getValue();
theSimpleAAScreen.setStatusText(statusText);
theSimpleAAScreen.invalidate();
}
/* get year, make, model */
try {
carInfo.fetchModel(mCarHardwareExecutor, mModelListener);
} catch (SecurityException e) {
Log.e(TAG, "No permission to get model");
}
theSimpleAAScreen is an object that is the android auto screen: I set a value for what to print and invalidate the screen so it redraws. There is probably a better / smoother way but this works and answers my question.
I'm using URLs from an API. Some of the URLs are mp4's without sound(video is playing just no sound). How do I check if that video has sound or not? I've been searching through SimpleExoPlayer docs and testing the methods on my URLS
https://exoplayer.dev/doc/reference/com/google/android/exoplayer2/SimpleExoPlayer.html for the past couple hours
But I can't figure out how to detect check if the video playing has sound or not.
Tried all the methods in getAudioAttributes(), getAudioComponents() and now just tried getAudioFormat() but they all return null.
try{
Log.d(TAG, "onCreateView: " + player.getAudioFormat().channelCount);
}catch (Exception e){
Log.d(TAG, "onCreateView: " + e);
}
And yes I've made sure the link's actually have Audio.
You can track the current tracks with Player#EventListener#OnTracksChanged and get the current ones with Player#getCurrentTrackGroups(). If you go through the track groups you can look for the type. If you find AUDIO type there that means your video file contains the audio track.
If you additionally want to check if any of the audio tracks was selected, then Player#getCurrentTrackSelections() is the place to look at.
To complete #Hamza Khan's answer, here is my code to check whether the loaded video has any audio:
override fun onTracksChanged(
trackGroups: TrackGroupArray?,
trackSelections: TrackSelectionArray?
) {
if (trackGroups != null && !trackGroups.isEmpty){
for (arrayIndex in 0 until trackGroups.length){
for (groupIndex in 0 until trackGroups[arrayIndex].length){
val sampleMimeType = trackGroups[arrayIndex].getFormat(groupIndex).sampleMimeType
if ( sampleMimeType != null && sampleMimeType.contains("audio") ){
//video contains audio
}
}
}
}
}
player.addListener(new Player.EventListener() {
#Override
public void onTracksChanged(TrackGroupArray trackGroups, TrackSelectionArray trackSelections) {
if (trackGroups != null && !trackGroups.isEmpty()) {
for (int i = 0; i < trackGroups.length; i++) {
for (int g = 0; g < trackGroups.get(i).length; g++) {
String sampleMimeType = trackGroups.get(i).getFormat(g).sampleMimeType;
if (sampleMimeType != null && sampleMimeType.contains("audio")) {
//video contains audio
}
}
}
}
}
}
JAVA version of mrj answer
Came across this thread which helped me a lot!
I have been searching the same problem for days. But unable to get any hint for that.
I need to create an app like voodoo app, which shows its custom layout only on specific pages of different apps like flipkart,etc.
Now, till this time, i have found options of using AccessebilityService and MediaProjection classes for the same. But i am stuck, how can i know programmatically, that Flipkart's Product Detail Page is visible so that i can display my app's custom view over it like Voodoo app does.
Any suggestions?
What you want to do is the following.
Using accessibility services track incoming events. Then you want to track TYPE_WINDOW_CONTENT_CHANGED events, and detect when the window content matches what you'd expect.
#Override
public void onAccessibilityEvent(AccessibilityEvent e) {
switch (e.getEventType()) {
case AccessibilityEvent.TYPE_WINDOW_CONTENT_CHANGED: {
if (isFlipkartProdcutDetailPage(getRootInActiveWindow()) {
doStuff()
}
}
}
}
public boolean isFlipkartProductDetailPage(AccessibilityNodeInfo nodeInfo) {
//Use the node info tree to identify the proper content.
//For now we'll just log it to logcat.
Log.w("TAG", toStringHierarchy(nodeInfo, 0));
}
private String toStringHierarchy(AccessibilityNodeInfo info, int depth) {
if (info == null) return "";
String result = "|";
for (int i = 0; i < depth; i++) {
result += " ";
}
result += info.toString();
for (int i = 0; i < info.getChildCount(); i++) {
result += "\n" + toStringHierarchy(info.getChild(i), depth + 1);
}
return result;
}
I create a room and it gets successfully made. And my onRoomCreated method gets called...
#Override
public void onRoomCreated(int statusCode, Room room) {
mRoomId = room.getRoomId();
Intent i = Games.RealTimeMultiplayer.getWaitingRoomIntent(gApiClient, room, 2);
startActivityForResult(i, RC_WAITING_ROOM);
}
Then in my onActivityResult...
Room r = data.getExtras().getParcelable(Multiplayer.EXTRA_ROOM);
ArrayList<String> invitees = new ArrayList<String>();
for (Participant p : r.getParticipants()) {
invitees.add(p.getPlayer().getPlayerId()); //<---NULL POINTER!
}
I get that null pointer. Why?
EDIT: The android docs say this about the getPlayer() method...
Returns the Player that this participant represents. Note that this may be null if the identity of the player is unknown. This occurs in automatching scenarios where some players are not permitted to see the real identity of others.
That is why I am getting null, because my room is through auto-matching.
Now the question is. How can I create a turnbasedgame using only participant IDs? Not Player IDs
Now that I see what you are asking more clearly (my fault, not yours), here is how I do it:
(for clarification I use LibGDX, so may be some interface stuff you don't need, and I am still using GamesClient not the new API methods, but is for all intents the same)
First, the final call I look to start my game is onRoomConnected
#Override
public void onRoomConnected(int statusCode, Room room) {
//dLog("onRoomConnected");
mRoomCurrent = room;
mParticipants = room.getParticipants();
mMyID = room.getParticipantId(aHelper.getGamesClient().getCurrentPlayerId());
//dLog("The id is " + mMyID);
try {
bWaitRoomDismissedFromCode = true;
finishActivity(RC_WAITING_ROOM);
} catch (Exception e) {
//dLog("would have errored out in waiting room");
}
//tell the Game the room is connected
if (statusCode == GamesClient.STATUS_OK) {
theGameInterface.onRoomConnected(room.getParticipantIds(), mMyID, room.getCreationTimestamp() );
} else {
leaveRoom();
}
}
So, now have all the participantIDs.. now in my Game code (where I sent that List of Ids), I sort the list of IDs so that in determining Player order, it is the same methodology for all Players. First I build my opponents.
private void buildOpponents() {
// this creates a new opponent with a View on the Stage()
//sort the participants the same for all players
sortParticipantIDs();
for (String s : mParticipantIds) {
if(s.contains(mMyID) || mMyID.contains(s)) continue;
newOpponentWindow ow = new newOpponentWindow(s, MyAssetManager.getMySkin(), getStage());
Opponent o = new Opponent(this, s);
mapOpponents.put(s, o);
o.setWindow(ow);
getStage().addActor(ow);
}
setOpponentWindowPositions();
}
Then after some more setup I start Play and my first Time through, I have chosen that whoever is the top ID gets the honor of starting (I find this randomizes play enough, without having to do another method.. .but you can let the top ID do another method, and send that out to the other Players) Note this checks over my Opponents to determine Starting Player if someone leaves the room later in the game as well.
private boolean determineIfStartingBidder() {
Collections.sort(mParticipantIds);
// now look thru list
// if the number is mine then return true
// if the number is not mine.. and opponent is not Out of Game or Disconnected.. then return false
for (String s : mParticipantIds) {
if(s.contains(mMyID) || mMyID.contains(s)){
return true;
}
if(mapOpponents.get(s).getCurrentState() == currentState.DISCONNECTED || mapOpponents.get(s).getCurrentState() == currentState.OUTOFGAME ||
mapOpponents.get(s).getCurrentState() == currentState.LOSTGAME) {
continue;
}
return false;
}
return false;
}
Then in your game logic, just go through your ParticipantID list in whatever manner makes sense to pass the baton around! This works well, since all the calls for passing messages require the ParticipantID, and are there for easy grab n go!
Prior Answer Below ------------------------------------------------
try
data.getParcelableExtra(Multiplayer.EXTRA_ROOM);
no need for the getExtras
Still new to Java/android so trying to figure out the best way to code a multilevel if statement. What I'm trying to do is for a combat system that needs to check if player/npc is alive. If they are alive it then will check to see if they scored a critical hit. If they didn't critical hit then will see if they hit or missed.
combat = mydbhelper.getCombat();
startManagingCursor(combat);
if (playerCurHp == 0) {
combat.moveToPosition(11);
npcCombatStory = combat.getString(combat.getColumnIndex(dbhelper.KEY_COMBATDESC));
} else {
if (playerCritFlag.equals("Critical")) {
combat.moveToPosition(2);
playerCombatStory = combat.getString(combat.getColumnIndex(dbhelper.KEY_COMBATDESC));
} else {
if (playerHitFlag.equals("Hit")) {
combat.moveToPosition(1);
playerCombatStory = combat.getString(combat.getColumnIndex(dbhelper.KEY_COMBATDESC));
}
if (playerHitFlag.equals("Miss")) {
combat.moveToPosition(3);
playerCombatStory = combat.getString(combat.getColumnIndex(dbhelper.KEY_COMBATDESC));
}
}
}
if (npcCurHp == 0) {
combat.moveToPosition(10);
npcCombatStory = combat.getString(combat.getColumnIndex(dbhelper.KEY_COMBATDESC));
} else {
if (npcCritFlag.equals("Critical")) {
combat.moveToPosition(5);
npcCombatStory = combat.getString(combat.getColumnIndex(dbhelper.KEY_COMBATDESC));
} else {
if (npcHitFlag.equals("Hit")) {
combat.moveToPosition(4);
npcCombatStory = combat.getString(combat.getColumnIndex(dbhelper.KEY_COMBATDESC));
}
if(npcHitFlag.equals("Miss")) {
combat.moveToPosition(6);
npcCombatStory = combat.getString(combat.getColumnIndex(dbhelper.KEY_COMBATDESC));
}
}
}
Is what I'm using. Was working when I had the if statements all separate. But it would check each one and do actions I don't need (If they hit, pull String, if crit pull another, then if dead pull again). Trying to make it stop when it finds the "Flag" that matches. When doing my rolls if the player hits it sets the flag to "Hit" like below code.
Random attackRandom = new Random();
int attackRoll = attackRandom.nextInt(100);
totalAtt = attackRoll + bonusAttack + weaponAtt + stanceAtt;
Random defensiveRandom = new Random();
int defenseRoll = defensiveRandom.nextInt(100);
npcDef = defenseRoll + npcDodge + npcBonusDodge;
if (totalAtt > npcDef) {
playerHitFlag = "Hit";
playerDamage();
} else {
playerHitFlag = "Miss";
npcAttack();
}
At the end it takes these playerCombatStory and npcCombatStory strings and uses them to setText to show the player what happened on that turn of combat.
I think you are looking for the else if statement:
if (condition) {
}
else if (other_condition) {
}
else if (another_condition) {
}
else {
// There can only be one else statement in a given if-else block
}
Your question isn't clear. But meaningful advice can still be offered.
Personally, I find this code hard to read. I think it'll be hard to maintain in the future as your logic becomes more complex.
I think you need to decouple the logic of what's done from how you decide. Encapsulate what's done in a Command object and use a map or state machine to look up what to do.
I would change the type of npcCritFlag to int or enum. Then use switch statement with case
This should look much better and easier to understand