简体   繁体   中英

com.google.android.gms leaks memory while using play services in libgdx game and makes it laggy

This is my main activity

package com.sdsmdg.cycle;

import android.content.Intent;
import android.net.Uri;
import android.os.Bundle;
import android.util.Log;

import com.badlogic.gdx.backends.android.AndroidApplication;
import com.badlogic.gdx.backends.android.AndroidApplicationConfiguration;
import com.google.android.gms.games.Games;
import com.google.android.gms.games.GamesActivityResultCodes;
import com.google.example.games.basegameutils.GameHelper;
import com.sdsmdg.ball.R;    

public class AndroidLauncher extends AndroidApplication implements PlayServices {

    private GameHelper gameHelper;
    private final static int requestCode = 1;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        AndroidApplicationConfiguration config = new AndroidApplicationConfiguration();
        initialize(new CGame(this), config);

        gameHelper = new GameHelper(this, GameHelper.CLIENT_GAMES);

        GameHelper.GameHelperListener gameHelperListener = new GameHelper.GameHelperListener() {
            @Override
            public void onSignInFailed() {
                Log.i("AndroidLauncher", "Sign in Failed!");
            }

            @Override
            public void onSignInSucceeded() {
                Log.i("AndroidLauncher", "Sign in Successful!");
            }
        };

        gameHelper.setup(gameHelperListener);
    }

    @Override
    protected void onStart() {
        super.onStart();
        gameHelper.onStart(this);
    }

    @Override
    protected void onStop() {
        super.onStop();
        gameHelper.onStop();
    }

    @Override
    protected void onActivityResult(int requestCode, int resultCode, Intent data) {
        super.onActivityResult(requestCode, resultCode, data);
        gameHelper.onActivityResult(requestCode, resultCode, data);

        if (resultCode == GamesActivityResultCodes.RESULT_RECONNECT_REQUIRED){
            // force a disconnect to sync up state, ensuring that mClient reports "not connected"
            gameHelper.disconnect();
        }
    }

    @Override
    public void signIn() {
        try {
            runOnUiThread(new Runnable() {
                @Override
                public void run() {
                    gameHelper.beginUserInitiatedSignIn();
                }
            });
        } catch (Exception e) {
            Log.i("MainActivity", "Log in failed: " + e.getMessage() + ".");
        }
    }

    @Override
    public void signOut() {
        try {
            runOnUiThread(new Runnable() {
                @Override
                public void run() {
                    gameHelper.signOut();
                }
            });
        } catch (Exception e) {
            Log.i("MainActivity", "Log out failed: " + e.getMessage() + ".");
        }
    }

    @Override
    public void rateGame() {
        String str = "Your PlayStore Link";
        startActivity(new Intent(Intent.ACTION_VIEW, Uri.parse(str)));
    }

    @Override
    public void unlockAchievementBeginner() {
        //This achievement is named Beginner, for playing 10 games
        if (gameHelper.isSignedIn())
            Games.Achievements.unlock(gameHelper.getApiClient(),
                    getString(R.string.achievement_beginner));
    }

    @Override
    public void unlockAchievement2() {
        //This gets unlocked on making a score of 2
        if (gameHelper.isSignedIn())
            Games.Achievements.unlock(gameHelper.getApiClient(),
                    getString(R.string.achievement_welcome_to_the_2_group));
    }

    @Override
    public void unlockAchievementTrickyOne() {
        //This gets unlocked when the ball hits the bat only once in a game
        if (gameHelper.isSignedIn())
            Games.Achievements.unlock(gameHelper.getApiClient(),
                    getString(R.string.achievement_the_tricky_one));
    }

    @Override
    public void unlockAchievementCentury() {
        if (gameHelper.isSignedIn())
            Games.Achievements.unlock(gameHelper.getApiClient(),
                    getString(R.string.achievement_century));
    }

    @Override
    public void unlockAchievementHalfCentury() {
        if (gameHelper.isSignedIn())
            Games.Achievements.unlock(gameHelper.getApiClient(),
                    getString(R.string.achievement_half_century));
    }

    @Override
    public void unlockAchievementBored() {
        //Play 100 games to unlock this achievement
        if (gameHelper.isSignedIn())
            Games.Achievements.unlock(gameHelper.getApiClient(),
                    getString(R.string.achievement_bored));
    }

    @Override
    public void unlockAchievementIntoHeavens() {
        //hit the ball such that it goes out of the screen 3 times continuously without dying
        if (gameHelper.isSignedIn()) {
            Games.Achievements.unlock(gameHelper.getApiClient(),
                    getString(R.string.achievement_into_the_heavens));
        }

    }

    @Override
    public void unlockAchievementYouAreGod() {
        //hit the ball such that it goes out of the screen 4 times continuously without dying
        if (gameHelper.isSignedIn()) {
            Games.Achievements.unlock(gameHelper.getApiClient(),
                    getString(R.string.achievement_you_are_the_god));
        }
    }

    @Override
    public void submitScore(int highScore) {
        if (isSignedIn()) {
            Games.Leaderboards.submitScore(gameHelper.getApiClient(),
                    getString(R.string.leaderboard_leaderboard), highScore);
        }
    }

    @Override
    public void showAchievement() {
        if (isSignedIn()) {
            startActivityForResult(Games.Achievements.getAchievementsIntent(gameHelper.getApiClient()), requestCode);
        } else {
            signIn();
        }
    }

    @Override
    public void showScore() {
        if (isSignedIn() == true) {
            startActivityForResult(Games.Leaderboards.getLeaderboardIntent(gameHelper.getApiClient(),
                    getString(R.string.leaderboard_leaderboard)), requestCode);
        } else {
            signIn();
        }
    }

    @Override
    public boolean isSignedIn() {
        return gameHelper.isSignedIn();
    }


}

The game works fine in the first few runs but starts to lag afterwards. The error in Android Monitor is like this:

E/ActivityThread: Service com.google.android.gms.car.CarService has leaked ServiceConnection fmj@35e4d4a that was originally bound here
                                                   android.app.ServiceConnectionLeaked: Service com.google.android.gms.car.CarService has leaked ServiceConnection fmj@35e4d4a that was originally bound here
                                                       at android.app.LoadedApk$ServiceDispatcher.<init>(LoadedApk.java:1093)
                                                       at android.app.LoadedApk.getServiceDispatcher(LoadedApk.java:987)
                                                       at android.app.ContextImpl.bindServiceCommon(ContextImpl.java:1313)
                                                       at android.app.ContextImpl.bindService(ContextImpl.java:1296)
                                                       at android.content.ContextWrapper.bindService(ContextWrapper.java:610)
                                                       at android.content.ContextWrapper.bindService(ContextWrapper.java:610)
                                                       at android.content.ContextWrapper.bindService(ContextWrapper.java:610)
                                                       at ivw.a(:com.google.android.gms:120)
                                                       at ivw.a(:com.google.android.gms:137)
                                                       at fmj.h(:com.google.android.gms:76)
                                                       at fmj.<init>(:com.google.android.gms:64)
                                                       at fpn.i(:com.google.android.gms:551)
                                                       at com.google.android.gms.car.CarChimeraService.onBind(:com.google.android.gms:165)
                                                       at com.google.android.chimera.container.ServiceProxy.onBind(:com.google.android.gms:165)
                                                       at android.app.ActivityThread.handleBindService(ActivityThread.java:2938)
                                                       at android.app.ActivityThread.-wrap2(ActivityThread.java)
                                                       at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1451)
                                                       at android.os.Handler.dispatchMessage(Handler.java:102)
                                                       at android.os.Looper.loop(Looper.java:148)
                                                       at android.app.ActivityThread.main(ActivityThread.java:5461)
                                                       at java.lang.reflect.Method.invoke(Native Method)
                                                       at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:726)
                                                       at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:616)

SQLiteConnectionPool: A SQLiteConnection object for database '/data/user/0/com.google.android.gms/databases/metrics.db' was leaked!  Please fix your application to end transactions in progress properly and to close the database when it is no longer needed.
09-12 16:45:59.072 8993-9001/com.google.android.gms W/SQLiteConnectionPool: A SQLiteConnection object for database '/data/user/0/com.google.android.gms/databases/help_responses.db' was leaked!  Please fix your application to end transactions in progress properly and to close the database when it is no longer needed.
09-12 16:45:59.074 8993-9001/com.google.android.gms W/SQLiteConnectionPool: A SQLiteConnection object for database '/data/user/0/com.google.android.gms/databases/auto_complete_suggestions.db' was leaked!  Please fix your application to end transactions in progress properly and to close the database when it is no longer needed.
09-12 16:47:41.038 8993-9001/com.google.android.gms E/DataBuffer: Internal data leak within a DataBuffer object detected!  Be sure to explicitly call release() on all DataBuffer extending objects when you are done with them. (internal object: com.google.android.gms.common.data.DataHolder@dbfbc4)
09-12 16:47:45.845 18100-18108/com.google.android.gms.ui E/DataBuffer: Internal data leak within a DataBuffer object detected!  Be sure to explicitly call release() on all DataBuffer extending objects when you are done with them. (internal object: com.google.android.gms.common.data.DataHolder@d4f2783)

The last part indicates that there is a memory leak in google gms service. I have been searching the web for weeks now, but cannot find out what I am doing wrong

The stackstrace you posted does not seem to have a reference to AndroidLauncher.java. It looks like things go wrong in another part of your code.

The log says at the end

'Internal data leak within a DataBuffer object detected! Be sure to explicitly call release() on all DataBuffer extending objects when you are done with them.'

Do you use any DataBuffer extending objects?

问题是我试图多次调用unlockAchievementBeginner(),这可能导致太频繁的垃圾收集,从而导致游戏延迟

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM