Move emulation lifecycle handling into EmulationFragment.
The Activity is responsible for just its views and menus and such. It signals the Fragment via setGamePath, StartEmulation and StopEmulation. The Fragment manages the actual emulation lifecycle. It is solely responsible for calling the NativeLibrary lifecycle methods. With this lifecycle simplification, the NativeLibrary no longer needs to kill the Activity. It happens normally now. This simplifies a lot of things, live handling rotation.
This commit is contained in:
parent
d48c64457a
commit
4cab718065
|
@ -399,20 +399,6 @@ public final class NativeLibrary
|
|||
}
|
||||
}
|
||||
|
||||
public static void endEmulationActivity()
|
||||
{
|
||||
Log.verbose("[NativeLibrary] Ending EmulationActivity.");
|
||||
EmulationActivity emulationActivity = sEmulationActivity.get();
|
||||
if (emulationActivity != null)
|
||||
{
|
||||
emulationActivity.exitWithAnimation();
|
||||
}
|
||||
else
|
||||
{
|
||||
Log.warning("[NativeLibrary] EmulationActivity is null, can't end.");
|
||||
}
|
||||
}
|
||||
|
||||
public static void setEmulationActivity(EmulationActivity emulationActivity)
|
||||
{
|
||||
Log.verbose("[NativeLibrary] Registering EmulationActivity.");
|
||||
|
|
|
@ -23,7 +23,6 @@ import android.view.Menu;
|
|||
import android.view.MenuItem;
|
||||
import android.view.MotionEvent;
|
||||
import android.view.View;
|
||||
import android.widget.FrameLayout;
|
||||
import android.widget.ImageView;
|
||||
import android.widget.LinearLayout;
|
||||
import android.widget.SeekBar;
|
||||
|
@ -55,8 +54,8 @@ public final class EmulationActivity extends AppCompatActivity
|
|||
private static final String FRAGMENT_SUBMENU_TAG = "submenu";
|
||||
private View mDecorView;
|
||||
private ImageView mImageView;
|
||||
private EmulationFragment mEmulationFragment;
|
||||
|
||||
private FrameLayout mFrameEmulation;
|
||||
private LinearLayout mMenuLayout;
|
||||
|
||||
private SharedPreferences mPreferences;
|
||||
|
@ -85,7 +84,6 @@ public final class EmulationActivity extends AppCompatActivity
|
|||
}
|
||||
};
|
||||
private String mScreenPath;
|
||||
private FrameLayout mFrameContent;
|
||||
private String mSelectedTitle;
|
||||
|
||||
@Retention(SOURCE)
|
||||
|
@ -219,12 +217,13 @@ public final class EmulationActivity extends AppCompatActivity
|
|||
|
||||
Java_GCAdapter.manager = (UsbManager) getSystemService(Context.USB_SERVICE);
|
||||
Java_WiimoteAdapter.manager = (UsbManager) getSystemService(Context.USB_SERVICE);
|
||||
|
||||
setContentView(R.layout.activity_emulation);
|
||||
|
||||
mImageView = (ImageView) findViewById(R.id.image_screenshot);
|
||||
mFrameContent = (FrameLayout) findViewById(R.id.frame_content);
|
||||
mFrameEmulation = (FrameLayout) findViewById(R.id.frame_emulation_fragment);
|
||||
mMenuLayout = (LinearLayout) findViewById(R.id.layout_ingame_menu);
|
||||
mEmulationFragment = (EmulationFragment) getSupportFragmentManager()
|
||||
.findFragmentById(R.id.fragment_emulation);
|
||||
|
||||
Intent gameToEmulate = getIntent();
|
||||
String path = gameToEmulate.getStringExtra("SelectedGame");
|
||||
|
@ -260,14 +259,6 @@ public final class EmulationActivity extends AppCompatActivity
|
|||
|
||||
Animations.fadeViewOut(mImageView)
|
||||
.setStartDelay(2000)
|
||||
.withStartAction(new Runnable()
|
||||
{
|
||||
@Override
|
||||
public void run()
|
||||
{
|
||||
mFrameEmulation.setVisibility(View.VISIBLE);
|
||||
}
|
||||
})
|
||||
.withEndAction(new Runnable()
|
||||
{
|
||||
@Override
|
||||
|
@ -277,18 +268,12 @@ public final class EmulationActivity extends AppCompatActivity
|
|||
}
|
||||
});
|
||||
|
||||
// Instantiate an EmulationFragment.
|
||||
EmulationFragment emulationFragment = EmulationFragment.newInstance(path);
|
||||
|
||||
// Add fragment to the activity - this triggers all its lifecycle callbacks.
|
||||
getSupportFragmentManager().beginTransaction()
|
||||
.add(R.id.frame_emulation_fragment, emulationFragment, EmulationFragment.FRAGMENT_TAG)
|
||||
.commit();
|
||||
mEmulationFragment.setGamePath(path);
|
||||
mEmulationFragment.startEmulation();
|
||||
}
|
||||
else
|
||||
{
|
||||
mImageView.setVisibility(View.GONE);
|
||||
mFrameEmulation.setVisibility(View.VISIBLE);
|
||||
}
|
||||
|
||||
if (mDeviceHasTouchScreen)
|
||||
|
@ -311,23 +296,6 @@ public final class EmulationActivity extends AppCompatActivity
|
|||
mIsGameCubeGame = Platform.fromNativeInt(NativeLibrary.GetPlatform(path)) == Platform.GAMECUBE;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onStart()
|
||||
{
|
||||
super.onStart();
|
||||
Log.debug("[EmulationActivity] EmulationActivity starting.");
|
||||
NativeLibrary.setEmulationActivity(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onStop()
|
||||
{
|
||||
super.onStop();
|
||||
Log.debug("[EmulationActivity] EmulationActivity stopping.");
|
||||
|
||||
NativeLibrary.clearEmulationActivity();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onPostCreate(Bundle savedInstanceState)
|
||||
{
|
||||
|
@ -376,7 +344,8 @@ public final class EmulationActivity extends AppCompatActivity
|
|||
}
|
||||
else
|
||||
{
|
||||
stopEmulation();
|
||||
mEmulationFragment.stopEmulation();
|
||||
exitWithAnimation();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -406,15 +375,6 @@ public final class EmulationActivity extends AppCompatActivity
|
|||
}
|
||||
}
|
||||
|
||||
private void stopEmulation()
|
||||
{
|
||||
EmulationFragment fragment = (EmulationFragment) getSupportFragmentManager()
|
||||
.findFragmentByTag(EmulationFragment.FRAGMENT_TAG);
|
||||
fragment.notifyEmulationStopped();
|
||||
|
||||
NativeLibrary.StopEmulation();
|
||||
}
|
||||
|
||||
public void exitWithAnimation()
|
||||
{
|
||||
runOnUiThread(new Runnable()
|
||||
|
@ -458,7 +418,6 @@ public final class EmulationActivity extends AppCompatActivity
|
|||
@Override
|
||||
public void run()
|
||||
{
|
||||
mFrameContent.removeView(mFrameEmulation);
|
||||
setResult(mPosition);
|
||||
finishAfterTransition();
|
||||
}
|
||||
|
@ -599,20 +558,23 @@ public final class EmulationActivity extends AppCompatActivity
|
|||
return;
|
||||
|
||||
case MENU_ACTION_EXIT:
|
||||
toggleMenu();
|
||||
stopEmulation();
|
||||
toggleMenu(); // Hide the menu (it will be showing since we just clicked it)
|
||||
mEmulationFragment.stopEmulation();
|
||||
exitWithAnimation();
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private void editControlsPlacement() {
|
||||
EmulationFragment emulationFragment = (EmulationFragment) getSupportFragmentManager()
|
||||
.findFragmentById(R.id.frame_emulation_fragment);
|
||||
if (emulationFragment.isConfiguringControls()) {
|
||||
emulationFragment.stopConfiguringControls();
|
||||
} else {
|
||||
emulationFragment.startConfiguringControls();
|
||||
private void editControlsPlacement()
|
||||
{
|
||||
if (mEmulationFragment.isConfiguringControls())
|
||||
{
|
||||
mEmulationFragment.stopConfiguringControls();
|
||||
}
|
||||
else
|
||||
{
|
||||
mEmulationFragment.startConfiguringControls();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -701,20 +663,18 @@ public final class EmulationActivity extends AppCompatActivity
|
|||
}
|
||||
builder.setNeutralButton(getString(R.string.emulation_toggle_all), new DialogInterface.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(DialogInterface dialogInterface, int i) {
|
||||
EmulationFragment emulationFragment = (EmulationFragment) getSupportFragmentManager()
|
||||
.findFragmentByTag(EmulationFragment.FRAGMENT_TAG);
|
||||
emulationFragment.toggleInputOverlayVisibility();
|
||||
public void onClick(DialogInterface dialogInterface, int i)
|
||||
{
|
||||
mEmulationFragment.toggleInputOverlayVisibility();
|
||||
}
|
||||
});
|
||||
builder.setPositiveButton(getString(R.string.ok), new DialogInterface.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(DialogInterface dialogInterface, int i) {
|
||||
public void onClick(DialogInterface dialogInterface, int i)
|
||||
{
|
||||
editor.apply();
|
||||
|
||||
EmulationFragment emulationFragment = (EmulationFragment) getSupportFragmentManager()
|
||||
.findFragmentByTag(EmulationFragment.FRAGMENT_TAG);
|
||||
emulationFragment.refreshInputOverlay();
|
||||
mEmulationFragment.refreshInputOverlay();
|
||||
}
|
||||
});
|
||||
|
||||
|
@ -759,9 +719,7 @@ public final class EmulationActivity extends AppCompatActivity
|
|||
editor.putInt("controlScale", seekbar.getProgress());
|
||||
editor.apply();
|
||||
|
||||
EmulationFragment emulationFragment = (EmulationFragment) getSupportFragmentManager()
|
||||
.findFragmentByTag(EmulationFragment.FRAGMENT_TAG);
|
||||
emulationFragment.refreshInputOverlay();
|
||||
mEmulationFragment.refreshInputOverlay();
|
||||
}
|
||||
});
|
||||
|
||||
|
@ -788,9 +746,7 @@ public final class EmulationActivity extends AppCompatActivity
|
|||
public void onClick(DialogInterface dialogInterface, int i) {
|
||||
editor.apply();
|
||||
|
||||
EmulationFragment emulationFragment = (EmulationFragment) getSupportFragmentManager()
|
||||
.findFragmentByTag(EmulationFragment.FRAGMENT_TAG);
|
||||
emulationFragment.refreshInputOverlay();
|
||||
mEmulationFragment.refreshInputOverlay();
|
||||
|
||||
Toast.makeText(getApplication(), R.string.emulation_controller_changed, Toast.LENGTH_SHORT).show();
|
||||
}
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
package org.dolphinemu.dolphinemu.fragments;
|
||||
|
||||
import android.content.Context;
|
||||
import android.content.SharedPreferences;
|
||||
import android.os.Bundle;
|
||||
import android.preference.PreferenceManager;
|
||||
|
@ -14,15 +15,12 @@ import android.widget.Button;
|
|||
|
||||
import org.dolphinemu.dolphinemu.NativeLibrary;
|
||||
import org.dolphinemu.dolphinemu.R;
|
||||
import org.dolphinemu.dolphinemu.activities.EmulationActivity;
|
||||
import org.dolphinemu.dolphinemu.overlay.InputOverlay;
|
||||
import org.dolphinemu.dolphinemu.utils.Log;
|
||||
|
||||
public final class EmulationFragment extends Fragment implements SurfaceHolder.Callback
|
||||
{
|
||||
public static final String FRAGMENT_TAG = "emulation_fragment";
|
||||
|
||||
private static final String ARG_GAME_PATH = "game_path";
|
||||
|
||||
private SharedPreferences mPreferences;
|
||||
|
||||
private Surface mSurface;
|
||||
|
@ -31,18 +29,22 @@ public final class EmulationFragment extends Fragment implements SurfaceHolder.C
|
|||
|
||||
private Thread mEmulationThread;
|
||||
|
||||
private boolean mEmulationStarted;
|
||||
private boolean mEmulationRunning;
|
||||
private String mGamePath;
|
||||
private final EmulationState mEmulationState = new EmulationState();
|
||||
|
||||
public static EmulationFragment newInstance(String path)
|
||||
@Override
|
||||
public void onAttach(Context context)
|
||||
{
|
||||
EmulationFragment fragment = new EmulationFragment();
|
||||
super.onAttach(context);
|
||||
|
||||
Bundle arguments = new Bundle();
|
||||
arguments.putString(ARG_GAME_PATH, path);
|
||||
fragment.setArguments(arguments);
|
||||
|
||||
return fragment;
|
||||
if (context instanceof EmulationActivity)
|
||||
{
|
||||
NativeLibrary.setEmulationActivity((EmulationActivity) context);
|
||||
}
|
||||
else
|
||||
{
|
||||
throw new IllegalStateException("EmulationFragment must have EmulationActivity parent");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -67,38 +69,20 @@ public final class EmulationFragment extends Fragment implements SurfaceHolder.C
|
|||
{
|
||||
View contents = inflater.inflate(R.layout.fragment_emulation, container, false);
|
||||
|
||||
SurfaceView surfaceView = (SurfaceView) contents.findViewById(R.id.surface_emulation);
|
||||
mInputOverlay = (InputOverlay) contents.findViewById(R.id.surface_input_overlay);
|
||||
|
||||
SurfaceView surfaceView = contents.findViewById(R.id.surface_emulation);
|
||||
surfaceView.getHolder().addCallback(this);
|
||||
|
||||
// If the input overlay was previously disabled, then don't show it.
|
||||
mInputOverlay = contents.findViewById(R.id.surface_input_overlay);
|
||||
if (mInputOverlay != null)
|
||||
{
|
||||
// If the input overlay was previously disabled, then don't show it.
|
||||
if (!mPreferences.getBoolean("showInputOverlay", true))
|
||||
{
|
||||
mInputOverlay.setVisibility(View.GONE);
|
||||
}
|
||||
}
|
||||
|
||||
if (savedInstanceState == null)
|
||||
{
|
||||
mEmulationThread = new Thread(mEmulationRunner);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Likely a rotation occurred.
|
||||
// TODO Pass native code the Surface, which will have been recreated, from surfaceChanged()
|
||||
// TODO Also, write the native code that will get the video backend to accept the new Surface as one of its own.
|
||||
}
|
||||
|
||||
return contents;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onViewCreated(View view, Bundle savedInstanceState)
|
||||
{
|
||||
Button doneButton = (Button) view.findViewById(R.id.done_control_config);
|
||||
Button doneButton = contents.findViewById(R.id.done_control_config);
|
||||
if (doneButton != null)
|
||||
{
|
||||
doneButton.setOnClickListener(new View.OnClickListener()
|
||||
|
@ -110,29 +94,29 @@ public final class EmulationFragment extends Fragment implements SurfaceHolder.C
|
|||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onStart()
|
||||
{
|
||||
super.onStart();
|
||||
startEmulation();
|
||||
// The new Surface created here will get passed to the native code via onSurfaceChanged.
|
||||
|
||||
return contents;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onStop()
|
||||
{
|
||||
pauseEmulation();
|
||||
super.onStop();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDestroyView()
|
||||
public void onDetach()
|
||||
{
|
||||
super.onDestroyView();
|
||||
if (getActivity().isFinishing() && mEmulationStarted)
|
||||
{
|
||||
NativeLibrary.StopEmulation();
|
||||
NativeLibrary.clearEmulationActivity();
|
||||
super.onDetach();
|
||||
}
|
||||
|
||||
public void setGamePath(String setPath)
|
||||
{
|
||||
this.mGamePath = setPath;
|
||||
}
|
||||
|
||||
public void toggleInputOverlayVisibility()
|
||||
|
@ -171,6 +155,12 @@ public final class EmulationFragment extends Fragment implements SurfaceHolder.C
|
|||
public void surfaceChanged(SurfaceHolder holder, int format, int width, int height)
|
||||
{
|
||||
Log.debug("[EmulationFragment] Surface changed. Resolution: " + width + "x" + height);
|
||||
|
||||
if (mEmulationState.isPaused())
|
||||
{
|
||||
NativeLibrary.UnPauseEmulation();
|
||||
}
|
||||
|
||||
mSurface = holder.getSurface();
|
||||
NativeLibrary.SurfaceChanged(mSurface);
|
||||
}
|
||||
|
@ -181,45 +171,57 @@ public final class EmulationFragment extends Fragment implements SurfaceHolder.C
|
|||
Log.debug("[EmulationFragment] Surface destroyed.");
|
||||
NativeLibrary.SurfaceDestroyed();
|
||||
|
||||
if (mEmulationRunning)
|
||||
if (mEmulationState.isRunning())
|
||||
{
|
||||
pauseEmulation();
|
||||
}
|
||||
}
|
||||
|
||||
private void startEmulation()
|
||||
public void startEmulation()
|
||||
{
|
||||
if (!mEmulationStarted)
|
||||
synchronized (mEmulationState)
|
||||
{
|
||||
if (mEmulationState.isStopped())
|
||||
{
|
||||
Log.debug("[EmulationFragment] Starting emulation thread.");
|
||||
|
||||
mEmulationThread = new Thread(mEmulationRunner, "NativeEmulation");
|
||||
mEmulationThread.start();
|
||||
// The thread will call mEmulationState.run()
|
||||
}
|
||||
else
|
||||
else if (mEmulationState.isPaused())
|
||||
{
|
||||
Log.debug("[EmulationFragment] Resuming emulation.");
|
||||
NativeLibrary.UnPauseEmulation();
|
||||
mEmulationState.run();
|
||||
}
|
||||
else
|
||||
{
|
||||
Log.debug("[EmulationFragment] Bug, startEmulation called while running.");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
mEmulationRunning = true;
|
||||
public void stopEmulation() {
|
||||
synchronized (mEmulationState)
|
||||
{
|
||||
if (!mEmulationState.isStopped())
|
||||
{
|
||||
NativeLibrary.StopEmulation();
|
||||
mEmulationState.stop();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void pauseEmulation()
|
||||
{
|
||||
synchronized (mEmulationState)
|
||||
{
|
||||
Log.debug("[EmulationFragment] Pausing emulation.");
|
||||
|
||||
NativeLibrary.PauseEmulation();
|
||||
mEmulationRunning = false;
|
||||
mEmulationState.pause();
|
||||
}
|
||||
|
||||
/**
|
||||
* Called by containing activity to tell the Fragment emulation is already stopping,
|
||||
* so it doesn't try to stop emulation on its way to the garbage collector.
|
||||
*/
|
||||
public void notifyEmulationStopped()
|
||||
{
|
||||
mEmulationStarted = false;
|
||||
mEmulationRunning = false;
|
||||
}
|
||||
|
||||
private Runnable mEmulationRunner = new Runnable()
|
||||
|
@ -227,18 +229,17 @@ public final class EmulationFragment extends Fragment implements SurfaceHolder.C
|
|||
@Override
|
||||
public void run()
|
||||
{
|
||||
mEmulationRunning = true;
|
||||
mEmulationStarted = true;
|
||||
|
||||
while (mSurface == null)
|
||||
if (!mEmulationRunning)
|
||||
return;
|
||||
// Busy-wait for surface to be set
|
||||
while (mSurface == null) {}
|
||||
|
||||
synchronized (mEmulationState)
|
||||
{
|
||||
Log.info("[EmulationFragment] Starting emulation: " + mSurface);
|
||||
|
||||
mEmulationState.run();
|
||||
}
|
||||
// Start emulation using the provided Surface.
|
||||
String path = getArguments().getString(ARG_GAME_PATH);
|
||||
NativeLibrary.Run(path);
|
||||
NativeLibrary.Run(mGamePath);
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -258,4 +259,50 @@ public final class EmulationFragment extends Fragment implements SurfaceHolder.C
|
|||
{
|
||||
return mInputOverlay.isInEditMode();
|
||||
}
|
||||
|
||||
private static class EmulationState
|
||||
{
|
||||
private enum State
|
||||
{
|
||||
STOPPED, RUNNING, PAUSED
|
||||
}
|
||||
|
||||
private State state;
|
||||
|
||||
EmulationState()
|
||||
{
|
||||
// Starting state is stopped.
|
||||
state = State.STOPPED;
|
||||
}
|
||||
|
||||
public boolean isStopped()
|
||||
{
|
||||
return state == State.STOPPED;
|
||||
}
|
||||
|
||||
public boolean isRunning()
|
||||
{
|
||||
return state == State.RUNNING;
|
||||
}
|
||||
|
||||
public boolean isPaused()
|
||||
{
|
||||
return state == State.PAUSED;
|
||||
}
|
||||
|
||||
public void run()
|
||||
{
|
||||
state = State.RUNNING;
|
||||
}
|
||||
|
||||
public void pause()
|
||||
{
|
||||
state = State.PAUSED;
|
||||
}
|
||||
|
||||
public void stop()
|
||||
{
|
||||
state = State.STOPPED;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -5,11 +5,11 @@
|
|||
xmlns:tools="http://schemas.android.com/tools"
|
||||
android:id="@+id/frame_content">
|
||||
|
||||
<FrameLayout
|
||||
android:id="@+id/frame_emulation_fragment"
|
||||
<fragment
|
||||
android:id="@+id/fragment_emulation"
|
||||
android:name="org.dolphinemu.dolphinemu.fragments.EmulationFragment"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:visibility="invisible"/>
|
||||
android:layout_height="match_parent"/>
|
||||
|
||||
<org.dolphinemu.dolphinemu.ui.NVidiaShieldWorkaroundView
|
||||
android:layout_width="match_parent"
|
||||
|
|
|
@ -3,11 +3,11 @@
|
|||
android:layout_height="match_parent"
|
||||
android:id="@+id/frame_content">
|
||||
|
||||
<FrameLayout
|
||||
android:id="@+id/frame_emulation_fragment"
|
||||
<fragment
|
||||
android:id="@+id/fragment_emulation"
|
||||
android:name="org.dolphinemu.dolphinemu.fragments.EmulationFragment"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:visibility="invisible"/>
|
||||
android:layout_height="match_parent"/>
|
||||
|
||||
<ImageView
|
||||
android:layout_width="match_parent"
|
||||
|
|
|
@ -58,7 +58,6 @@ std::string s_set_userpath;
|
|||
|
||||
jclass s_jni_class;
|
||||
jmethodID s_jni_method_alert;
|
||||
jmethodID s_jni_method_end;
|
||||
|
||||
// The Core only supports using a single Host thread.
|
||||
// If multiple threads want to call host functions then they need to queue
|
||||
|
@ -732,7 +731,6 @@ Java_org_dolphinemu_dolphinemu_NativeLibrary_CacheClassesAndMethods(JNIEnv* env,
|
|||
// Source/Android/app/build/intermediates/classes/arm/debug/org/dolphinemu/dolphinemu/NativeLibrary.class
|
||||
s_jni_method_alert =
|
||||
env->GetStaticMethodID(s_jni_class, "displayAlertMsg", "(Ljava/lang/String;)V");
|
||||
s_jni_method_end = env->GetStaticMethodID(s_jni_class, "endEmulationActivity", "()V");
|
||||
}
|
||||
|
||||
// Surface Handling
|
||||
|
@ -816,9 +814,6 @@ JNIEXPORT void JNICALL Java_org_dolphinemu_dolphinemu_NativeLibrary_Run(JNIEnv*
|
|||
ANativeWindow_release(s_surf);
|
||||
s_surf = nullptr;
|
||||
}
|
||||
|
||||
// Execute the Java method.
|
||||
env->CallStaticVoidMethod(s_jni_class, s_jni_method_end);
|
||||
}
|
||||
|
||||
#ifdef __cplusplus
|
||||
|
|
Loading…
Reference in New Issue