I'm trying to save state data when you change the orientation of the android device, since I understand that's when it destroys activities and fragments. Does something special have to be done for fragments that are inside of other layouts (I have two fragments inside of my main activity xml). I thought I could simply handle saving data with saveInstanceState, but that seems to never be called, as the bundle that's passed into the onCreateView always is null. Any thoughts? I"m sure I'm missing something obvious here.
public class ControlFrag extends Fragment implements View.OnClickListener{
int hours, min, sec;
TextView text;
Button start;
Async async;
boolean clicked;
private static final String THREAD_STATUS = "thread status";
private static final String HOUR = "hour";
private static final String MINUTE = "minute";
private static final String SECOND = "second";
public ControlFrag() {
// Required empty public constructor
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
// Inflate the layout for this fragment
View v = inflater.inflate(R.layout.fragment_control, container, false);
text = (TextView) v.findViewById(R.id.timer);
start = (Button) v.findViewById(R.id.start);
start.setOnClickListener(this);
if (savedInstanceState != null) {
text.setText("Test");
boolean isRunning = savedInstanceState.getBoolean(THREAD_STATUS);
if (isRunning) {
sec = savedInstanceState.getInt(SECOND);
text.setText("" + sec);
async = new Async();
async.execute(sec);
}
}
else {
async = new Async();
}
return v;
}
#Override
public void onClick(View view) {
if (async.getStatus() != AsyncTask.Status.RUNNING) {
async = new Async();
async.execute(0);
}
}
#Override
public void onSaveInstanceState(Bundle outState) {
super.onSaveInstanceState(outState);
if (async != null && async.getStatus() == AsyncTask.Status.RUNNING) {
outState.putBoolean(THREAD_STATUS, true);
outState.putInt(SECOND, sec);
async.cancel(true);
}
else {
outState.putBoolean(THREAD_STATUS, false);
}
}
#Override
public void onDestroy() {
super.onDestroy();
if (async != null && async.getStatus() == AsyncTask.Status.RUNNING) {
async.cancel(true);
async = null;
}
}
private class Async extends AsyncTask<Integer, String, Void> {
#Override
protected void onPostExecute(Void aVoid) {
super.onPostExecute(aVoid);
}
#Override
protected void onProgressUpdate(String... values) {
super.onProgressUpdate(values);
text.setText(values[0] + values[1] + values[2]);
}
#Override
protected Void doInBackground(Integer... integers) {
sec = integers[0];
while (sec < 100) {
try {
sec++;
String second;
if(sec > 59){
sec = 0;
}
if (sec < 10) {
second = "0" + sec;
} else {
second = "" + sec;
}
publishProgress("" + sec, ":" + sec, ":" + second);
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
return null;
}
}
}
Code for Activity:
public class MainActivity extends AppCompatActivity implements View.OnClickListener{
public Button nextScreen;
public TextView timer;
public ControlFrag control;
public ListFrag list;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
control = new ControlFrag();
list = new ListFrag();
FragmentTransaction transaction = getSupportFragmentManager().beginTransaction();
if (savedInstanceState == null) {
// transaction.replace(R.id.fragment_container, control, "portraitControl");
}
if (getResources().getConfiguration().orientation == Configuration.ORIENTATION_LANDSCAPE) {
transaction.replace(R.id.fragment_container1, list, "landscapeList");
}
else {
nextScreen = (Button) findViewById(R.id.nextScreen);
nextScreen.setOnClickListener(this);
}
transaction.commit();
}
#Override
public void onSaveInstanceState(Bundle outState) {
super.onSaveInstanceState(outState);
outState.putString("Test", "GO");
}
#Override
public void onRestoreInstanceState(Bundle savedInstanceState) {
super.onRestoreInstanceState(savedInstanceState);
if (getResources().getConfiguration().orientation == Configuration.ORIENTATION_PORTRAIT) {
nextScreen.setText(savedInstanceState.getString("Test"));
}
}
#Override
protected void onDestroy() {
super.onDestroy();
}
#Override
public void onConfigurationChanged(Configuration newConfig) {
super.onConfigurationChanged(newConfig);
if (newConfig.orientation == Configuration.ORIENTATION_LANDSCAPE) {
} else if (newConfig.orientation == Configuration.ORIENTATION_PORTRAIT) {
}
}
#Override
public void onClick(View view) {
if (getSupportFragmentManager().findFragmentByTag("portraitControl") != null) {
FragmentTransaction transaction = getSupportFragmentManager().beginTransaction();
transaction.replace(R.id.fragment_container, list, "portraitList");
transaction.commit();
}
else {
FragmentTransaction transaction = getSupportFragmentManager().beginTransaction();
transaction.replace(R.id.fragment_container, control, "portraitControl");
transaction.commit();
}
}
}
Related
Im stuck here 2 days. I am trying to restore scroll position after device rotation.
Im saving an arraylist in the onSaveInstance, adding the movies i have to it and trying to set the adapter.
If i switch shorting criteria and rotate the device, it scrolls up to the top and not retaining its position. Here's my code
public class MainActivity extends AppCompatActivity {
public static final String MOVIE_LIST = "instanceMovieList";
public static final String RECYCLER_VIEW_STATE_KEY = "RECYCLER_VIEW_STATE_KEY";
private static final String LOG_TAG = MainActivity.class.getSimpleName();
Context mContext;
Toolbar mToolBar;
#BindView(R.id.prefSpinnner)
Spinner prefSpinner;
#BindView(R.id.noDataTv)
TextView noDataTv;
#BindView(R.id.rv_movies)
RecyclerView mMoviesRV;
private AppDatabase mDb;
private String userOption = "Most Popular";
private ArrayList<Movie> mMoviesList = new ArrayList<>();
private MovieRecycleViewAdapter movieRecycleViewAdapter;
private RecyclerView.LayoutManager mLayoutManager;
private Parcelable mListState;
#Override
protected void onSaveInstanceState(Bundle outState) {
if (mMoviesList != null) {
outState.putParcelableArrayList(MOVIE_LIST, mMoviesList);
mListState = mLayoutManager.onSaveInstanceState();
outState.putParcelable(RECYCLER_VIEW_STATE_KEY, mListState);
}
super.onSaveInstanceState(outState);
}
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
ButterKnife.bind(this);
GridLayoutManager gridLayoutManager = new GridLayoutManager(this, 2);
mMoviesRV.setLayoutManager(gridLayoutManager);
mMoviesRV.setHasFixedSize(true);
movieRecycleViewAdapter = new MovieRecycleViewAdapter(MainActivity.this, mMoviesList);
mMoviesRV.setAdapter(movieRecycleViewAdapter);
mLayoutManager = mMoviesRV.getLayoutManager();
if (savedInstanceState != null && savedInstanceState.containsKey(MOVIE_LIST)) {
ArrayList<Movie> savedMovieList = savedInstanceState.getParcelableArrayList(MOVIE_LIST);
Log.d(LOG_TAG, "getting movies from instance ");
mMoviesList.addAll(savedMovieList);
movieRecycleViewAdapter = new MovieRecycleViewAdapter(MainActivity.this, mMoviesList);
mMoviesRV.setAdapter(movieRecycleViewAdapter);
}
mToolBar = findViewById(R.id.toolbar);
mToolBar.setTitle(getResources().getString(R.string.app_name));
ArrayAdapter<String> spinAdapter = new ArrayAdapter<String>(MainActivity.this, R.layout.pref_spinner_item_list, getResources().getStringArray(R.array.userPrefs));
spinAdapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
prefSpinner.setAdapter(spinAdapter);
prefSpinner.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
#Override
public void onItemSelected(AdapterView<?> adapterView, View view, int i, long l) {
userOption = prefSpinner.getSelectedItem().toString();
if (userOption.contentEquals("Most Popular") || userOption.contentEquals("Highest Rated")) {
PopulateMoviesTask newTask = new PopulateMoviesTask();
newTask.execute();
} else {
setUpViewModel();
}
}
#Override
public void onNothingSelected(AdapterView<?> adapterView) {
PopulateMoviesTask newTask = new PopulateMoviesTask();
newTask.execute();
}
});
mDb = AppDatabase.getInstance(getApplicationContext());
}
private void setUpViewModel() {
MainViewModel viewModel = ViewModelProviders.of(this).get(MainViewModel.class);
viewModel.getMovies().observe(this, new Observer<List<Movie>>() {
#Override
public void onChanged(#Nullable List<Movie> movies) {
Log.d(LOG_TAG, "updating list of movies from livedata in viewmodel");
movieRecycleViewAdapter.setMovies(movies);
}
});
}
#Override
protected void onRestoreInstanceState(Bundle savedInstanceState) {
super.onRestoreInstanceState(savedInstanceState);
if (savedInstanceState != null) {
mMoviesList = savedInstanceState.getParcelableArrayList(MOVIE_LIST);
mListState = savedInstanceState.getParcelable(RECYCLER_VIEW_STATE_KEY);
}
}
#Override
protected void onResume() {
super.onResume();
if (mListState != null) {
mLayoutManager.onRestoreInstanceState(mListState);
}
}
private class PopulateMoviesTask extends AsyncTask<URL, Void, String> {
#Override
protected String doInBackground(URL... urls) {
URL searchMovieObjectUrl = NetworkUtils.createUrl(userOption);
String jsonString = "";
try {
jsonString = NetworkUtils.makeHttpRequest(searchMovieObjectUrl);
} catch (IOException e) {
Log.e("Main Activity", "Problem making the HTTP request.", e);
}
return jsonString;
}
#Override
protected void onPostExecute(String jsonString) {
if (jsonString == null) {
mMoviesRV.setVisibility(View.GONE);
noDataTv.setVisibility(View.VISIBLE);
} else {
mMoviesRV.setVisibility(View.VISIBLE);
noDataTv.setVisibility(View.GONE);
mMoviesList = JsonUtils.extractFeatureFromJson(jsonString);
}
movieRecycleViewAdapter = new MovieRecycleViewAdapter(MainActivity.this, mMoviesList);
mMoviesRV.setAdapter(movieRecycleViewAdapter);
}
}
}
Use this
private Parcelable recyclerViewState;// global
onResume
#Override
public void onResume() {
super.onResume();
mMoviesRV.getLayoutManager().onRestoreInstanceState(recyclerViewState);
}
onPasue
#Override
public void onPause() {
super.onPause();
recyclerViewState= mMoviesRV.getLayoutManager().onSaveInstanceState();
}
Since i found out what was going on, i think i should post an answer.
#Override protected void onSaveInstanceState(Bundle outState) {
if (mMoviesList != null) {
outState.putParcelableArrayList(MOVIE_LIST, mMoviesList);
mListState = mLayoutManager.onSaveInstanceState();
outState.putParcelable(RECYCLER_VIEW_STATE_KEY, mListState);
}
super.onSaveInstanceState(outState);
}
is enough to save the moviesList through lifecycle and then retrieve it
if (savedInstanceState != null && savedInstanceState.containsKey(MOVIE_LIST)) {
mMoviesList = savedInstanceState.getParcelableArrayList(MOVIE_LIST);
This answers the original question
But the problem was in my adapter and WHEN i was initializing it.
The adapter should only be initialized in onCreate (in my case at least) and then notify it if the Arraylist data changed more info here.
Good day, I have a fragment called MainFragment called from MainActivity. Inside MainFragment I have private OnProgressUpdateListener progressListener; this interface instance helps me talk to ProgressDialog Fragment.
I'm able to initialize interface instance inside my activities but I'm getting ClassCastException when I attempt to initialize the interface instance inside MainFragment
Below are my classes:
--------------------------------------------------------------------------------
Interface
--------------------------------------------------------------------------------
public interface OnProgressUpdateListener
{
void onProgressUpdate(String message);
void onDismissDialog();
}
--------------------------------------------------------------------------------
Child Fragment to MainFragment
--------------------------------------------------------------------------------
public class ProgressbarDialog extends DialogFragment implements OnProgressUpdateListener
{
TextView progressMessage;
ProgressBar progressBar;
View dialogView;
LayoutInflater inflater;
AlertDialog alertDialog;
AlertDialog.Builder dialogBuilder;
public ProgressbarDialog()
{
}
public static ProgressbarDialog newInstance(String title, String message)
{
ProgressbarDialog fragment = new ProgressbarDialog();
Bundle args = new Bundle();
args.putCharSequence("title", title);
args.putCharSequence("message", message);
fragment.setArguments(args);
return fragment;
}
#Override
public Dialog onCreateDialog(Bundle savedInstanceState)
{
dialogBuilder = new AlertDialog.Builder(getActivity());
inflater = getActivity().getLayoutInflater();
dialogView = inflater.inflate(R.layout.content_progressdialog,null);
dialogBuilder.setView(dialogView);
progressBar = dialogView.findViewById(R.id.pbProgressSpinner);
progressMessage = dialogView.findViewById(R.id.tvProgressMessage);
dialogBuilder.setTitle(getArguments().getString("title"));
progressBar.setIndeterminate(true);
progressMessage.setText(getArguments().getString("message"));
alertDialog = dialogBuilder.create();
alertDialog.setCanceledOnTouchOutside(false);
alertDialog.show();
return alertDialog;
}
#Override
public void onProgressUpdate(String message)
{
progressMessage.setText(message);
}
#Override
public void onDismissDialog()
{
alertDialog.dismiss();
}
}
--------------------------------------------------------------------------------
MainFragment - Parent Fragment To ProgressbarDialog
--------------------------------------------------------------------------------
public class MainFragment extends Fragment
{
private View mainView;
private CheckBox rememberMe;
private boolean stayLoggedIn;
private CountDownLatch latch;
private FragmentManager manager;
private OnMainListener mListener;
private EditText email, password;
private ProgressbarDialog progressDialog;
private OnProgressUpdateListener progressListener;
private final int REGISTER_CODE = 1, RESET_CODE = 2;
private FloatingActionButton fabRegister, fabLogin, fabReset;
public MainFragment()
{}
public static MainFragment newInstance()
{
MainFragment fragment = new MainFragment();
Bundle args = new Bundle();
fragment.setArguments(args);
return fragment;
}
#Override
public void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
if (getArguments() != null)
{}
manager = getChildFragmentManager();
progressDialog = ProgressbarDialog.newInstance("Authentication", "Connecting To Server, Please Wait...");
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState)
{
// Inflate the layout for this fragment
mainView = inflater.inflate(R.layout.main_fragment, container, false);
stayLoggedIn = false;
rememberMe = mainView.findViewById(R.id.cbRememberMe);
email = mainView.findViewById(R.id.edtLoginEmail);
password = mainView.findViewById(R.id.edtLoginPassword);
fabRegister = mainView.findViewById(R.id.fabRegister);
fabLogin = mainView.findViewById(R.id.fabLogin);
fabReset = mainView.findViewById(R.id.fabReset);
return mainView;
}
#Override
public void onViewCreated(View view, #Nullable Bundle savedInstanceState)
{
super.onViewCreated(view, savedInstanceState);
email.setTag("Account Email Required!");
password.setTag("Account Password Required!");
}
#Override
public void onStart()
{
super.onStart();
rememberMe.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
#Override
public void onCheckedChanged(CompoundButton compoundButton, boolean b) {
stayLoggedIn = b;
}
});
fabRegister.setOnClickListener(new View.OnClickListener()
{
#Override
public void onClick(View view)
{
mListener.onFABInteraction(REGISTER_CODE);
}
});
fabLogin.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view)
{
onLoginRequest();
}
});
fabReset.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view)
{
mListener.onFABInteraction(RESET_CODE);
}
});
}
#Override
public void onAttach(Context context)
{
super.onAttach(context);
try
{
if (context instanceof OnMainListener)
{
mListener = (OnMainListener) context;
}
else
{
throw new RuntimeException(context.toString()
+ " must implement OnMainListener");
}
}
catch (Exception e)
{
Log.e(MainFragment.class.getName(), e.getMessage());
}
}
**#Override
public void onAttachFragment(Fragment childFragment) {
super.onAttachFragment(childFragment);
if(childFragment instanceof OnProgressUpdateListener)
{
progressListener = (OnProgressUpdateListener) childFragment;
//This code is never executed
}
}**
#Override
public void onDetach()
{
super.onDetach();
mListener = null;
}
interface OnMainListener
{
void onLoginSuccess(BackendlessUser user);
void onFABInteraction(int option);
}
private class OnAuthentication extends AsyncTask<String, String, BackendlessUser>
{
#Override
protected void onPreExecute() {
super.onPreExecute();
latch = new CountDownLatch(1);
progressDialog.show(manager, MainFragment.class.getName());
Code Fails here, null pointer exception is thrown because progressListener interface instance is not initialised.
progressListener.onProgressUpdate("Authenticating User, Please Wait...");
}
#Override
protected void onProgressUpdate(String... values)
{
super.onProgressUpdate(values);
progressListener.onProgressUpdate(values[0]);
}
#Override
protected BackendlessUser doInBackground(String... strings)
{
try
{
Backendless.UserService.login(
Utility.getText(email),
Utility.getText(password),
onLoginCallback, stayLoggedIn);
publishProgress("Validating Credentials, Please Wait...");
latch.await();
}
catch (InterruptedException e)
{
publishProgress(e.getMessage());
}
return Utility.loginUser;
}
#Override
protected void onPostExecute(BackendlessUser user)
{
super.onPostExecute(user);
Utility.clearViews(email, password, rememberMe);
progressListener.onDismissDialog();
if(user != null)
{
if(((MainActivity)getActivity()).onRoleValidation(user))
{
mListener.onLoginSuccess(user);
}
else
{
//send a push notification to master channel
Utility.sendNotification(getActivity(),
"New Application User",
"New Registration",
"New User Awaiting Role Assignment", "Master",
"Role Assignment Pending For User :"
+ user.getEmail()
+ ":" + user.getProperty("name").toString()
+ " " + user.getProperty("surname").toString());
}
}
}
}
private void onLoginRequest()
{
if(Utility.hasText(email, password))
{
if(Utility.isEmailValid(Utility.getText(email)))
{
new OnAuthentication().
execute(Utility.getText(email),
Utility.getText(password));
}
else
{
Utility.showToast(getActivity(), "Invalid Email");
Utility.clearViews(email);
}
}
}
private AsyncCallback<BackendlessUser> onLoginCallback = new AsyncCallback<BackendlessUser>()
{
#Override
public void handleResponse(BackendlessUser backendlessUser)
{
latch.countDown();
Utility.loginUser = backendlessUser;
Log.i(MainFragment.class.getName(), "Login Successful!\n" + backendlessUser.getUserId());
}
#Override
public void handleFault(BackendlessFault backendlessFault)
{
latch.countDown();
progressListener.onProgressUpdate("Login Unsuccessful!");
Log.e(MainFragment.class.getName(), "Login Failed!\n" + backendlessFault.getMessage());
}
};
}
My app currently looks like this:
I want to add a search bar where I can search any place as Google maps. The search bar should be in an Auto Complete way.I got this code from https://examples.javacodegeeks.com/android/android-google-places-autocomplete-api-example/
Have a look at the above link.
And these codes where for an ORDINARY APP to get Auto Complete search bar. It doesnt suit for app using fragment. And I dont know how to do it with fragments.
Here is my code
For the Main Activity (ProfileActivity)
public class ProfileActivity extends AppCompatActivity {
final String TAG = this.getClass().getName();
BottomBar mBottomBar;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_profile);
mBottomBar = BottomBar.attach(this, savedInstanceState);
mBottomBar.setItemsFromMenu(R.menu.menu_user, new OnMenuTabClickListener() {
#Override
public void onMenuTabSelected(#IdRes int i) {
if(i == R.id.ButtonBarFeed)
{
NewsFragment f = new NewsFragment();
getSupportFragmentManager().beginTransaction().replace(R.id.frame,f).commit();
}
else if(i == R.id.ButtonBarMap)
{
MapFragment f = new MapFragment();
getSupportFragmentManager().beginTransaction().replace(R.id.frame,f).commit();
}
else if(i == R.id.ButtonBarUser)
{
UserFragment f = new UserFragment();
getSupportFragmentManager().beginTransaction().replace(R.id.frame,f).commit();
}
}
#Override
public void onMenuTabReSelected(#IdRes int menuItemId) {
}
});
mBottomBar.mapColorForTab(0,"#28809f");
}
public boolean googleServicesAvailable(){
GoogleApiAvailability api = GoogleApiAvailability.getInstance();
int isAvailable = api.isGooglePlayServicesAvailable(this);
if(isAvailable == ConnectionResult.SUCCESS){
return true;
}else if(api.isUserResolvableError(isAvailable)){
Dialog dialog = api.getErrorDialog(this, isAvailable, 0);
dialog.show();
} else {
Toast.makeText(this,"Can't connet to Play Services", Toast.LENGTH_LONG).show();
}
return false;
}
boolean twice;
#Override
public void onBackPressed() {
Log.d(TAG, "click");
if(twice == true){
Intent intent = new Intent(Intent.ACTION_MAIN);
intent.addCategory(Intent.CATEGORY_HOME);
intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
startActivity(intent);
finish();
System.exit(0);
}
twice = true;
Log.d(TAG, "twice:" + twice);
Toast.makeText(ProfileActivity.this, "Please press BACK again to exit", Toast.LENGTH_SHORT).show();
new Handler().postDelayed(new Runnable() {
#Override
public void run() {
twice = false;
Log.d(TAG, "twice:" + twice);
}
}, 3000);
}
}
MapFragment
public class MapFragment extends Fragment implements OnMapReadyCallback {
#Nullable
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
return inflater.inflate(R.layout.map, container, false);
}
#Override
public void onViewCreated(View view, Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
SupportMapFragment fragment = (SupportMapFragment)getChildFragmentManager().findFragmentById(R.id.mapView1);
fragment.getMapAsync(this);
}
#Override
public void onMapReady(GoogleMap googleMap){
}
}
I have to add a search bar with Auto Complete like Google map.Please with reference of the Link which I have given at starting, Can Anyone code for my MapFragment?
In my project I have just one Activity that have View.
I think that it has two View that switch the View. The first View is my home that has one Button named "play" . when You click play Button in goes to the second View. Second View is my game.
And now my problem is that when I want to use onBackPressed() method in the second View, it closes the Activity. and onBackPressed() method do the same in both View.
How to handle onBackPressed() method in second View that return to the first View.
How to switch the View in onBackPressed()?
I am new with Android and now I really confused.
any suggestion? or any key word to search to solve my problem.
here is my code:
public class PTPlayer extends Cocos2dxActivity {
static Splash splash;
public static AppList appList;
static Noti_Queue noti_queue;
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
Log.v("----------", "onActivityResult: request: " + requestCode + " result: " + resultCode);
if (requestCode == PTServicesBridge.RC_SIGN_IN) {
}
}
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
getWindow().addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
if (splash == null) {
splash = new Splash(this);
splash.set_identity("1");
}
if (appList == null) {
appList = new AppList(this);
appList.set_identity("1");
}
if (noti_queue == null) {
noti_queue = new Noti_Queue(this);
noti_queue.set_identity("1");
}
}
#Override
public void onNativeInit() {
initBridges();
}
private void initBridges() {
PTStoreBridge.initBridge(this);
PTServicesBridge.initBridge(this, getString(R.string.app_id));
if (PTJniHelper.isAdNetworkActive("kChartboost")) {
PTAdChartboostBridge.initBridge(this);
}
if (PTJniHelper.isAdNetworkActive("kRevMob")) {
PTAdRevMobBridge.initBridge(this);
}
if (PTJniHelper.isAdNetworkActive("kAdMob") || PTJniHelper.isAdNetworkActive("kFacebook")) {
PTAdAdMobBridge.initBridge(this);
}
if (PTJniHelper.isAdNetworkActive("kAppLovin")) {
PTAdAppLovinBridge.initBridge(this);
}
if (PTJniHelper.isAdNetworkActive("kLeadBolt")) {
PTAdLeadBoltBridge.initBridge(this);
}
if (PTJniHelper.isAdNetworkActive("kVungle")) {
PTAdVungleBridge.initBridge(this);
}
if (PTJniHelper.isAdNetworkActive("kPlayhaven")) {
PTAdUpsightBridge.initBridge(this);
}
if (PTJniHelper.isAdNetworkActive("kMoPub")) {
PTAdMoPubBridge.initBridge(this);
}
if (PTJniHelper.isAdNetworkActive("kFacebook")) {
PTAdFacebookBridge.initBridge(this);
}
if (PTJniHelper.isAdNetworkActive("kHeyzap")) {
PTAdHeyzapBridge.initBridge(this);
}
}
#Override
public Cocos2dxGLSurfaceView onCreateView() {
Cocos2dxGLSurfaceView glSurfaceView = new Cocos2dxGLSurfaceView(this);
glSurfaceView.setEGLConfigChooser(8, 8, 8, 0, 0, 0);
return glSurfaceView;
}
static {
System.loadLibrary("player");
}
#Override
protected void onResume() {
super.onResume();
if (PTJniHelper.isAdNetworkActive("kChartboost")) {
PTAdChartboostBridge.onResume(this);
}
}
#Override
protected void onStart() {
super.onStart();
if (PTJniHelper.isAdNetworkActive("kChartboost")) {
PTAdChartboostBridge.onStart(this);
}
}
#Override
protected void onStop() {
super.onStop();
if (PTJniHelper.isAdNetworkActive("kChartboost")) {
PTAdChartboostBridge.onStop(this);
}
}
#Override
protected void onDestroy() {
super.onDestroy();
}
#Override
public void onBackPressed() {
splash.Display();
splash = null;
super.onBackPressed();
}
}
here i think that in my second view:
public abstract class Cocos2dxActivity extends Activity implements Cocos2dxHelperListener {
// ===========================================================
// Constants
// ===========================================================
private static final String TAG = Cocos2dxActivity.class.getSimpleName();
// ===========================================================
// Fields
// ===========================================================
private Cocos2dxGLSurfaceView mGLSurfaceView;
private Cocos2dxHandler mHandler;
private static Context sContext = null;
public static Context getContext() {
return sContext;
}
// ===========================================================
// Constructors
// ===========================================================
#Override
protected void onCreate(final Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
sContext = this;
this.mHandler = new Cocos2dxHandler(this);
this.init();
Cocos2dxHelper.init(this, this);
}
// ===========================================================
// Getter & Setter
// ===========================================================
// ===========================================================
// Methods for/from SuperClass/Interfaces
// ===========================================================
#Override
protected void onResume() {
super.onResume();
Cocos2dxHelper.onResume();
this.mGLSurfaceView.onResume();
}
#Override
protected void onPause() {
super.onPause();
Cocos2dxHelper.onPause();
this.mGLSurfaceView.onPause();
}
#Override
public void showDialog(final String pTitle, final String pMessage) {
Message msg = new Message();
msg.what = Cocos2dxHandler.HANDLER_SHOW_DIALOG;
msg.obj = new Cocos2dxHandler.DialogMessage(pTitle, pMessage);
this.mHandler.sendMessage(msg);
}
#Override
public void showEditTextDialog(final String pTitle, final String pContent, final int pInputMode, final int pInputFlag, final int pReturnType, final int pMaxLength) {
Message msg = new Message();
msg.what = Cocos2dxHandler.HANDLER_SHOW_EDITBOX_DIALOG;
msg.obj = new Cocos2dxHandler.EditBoxMessage(pTitle, pContent, pInputMode, pInputFlag, pReturnType, pMaxLength);
this.mHandler.sendMessage(msg);
}
#Override
public void runOnGLThread(final Runnable pRunnable) {
this.mGLSurfaceView.queueEvent(pRunnable);
}
// ===========================================================
// Methods
// ===========================================================
public void init() {
// FrameLayout
ViewGroup.LayoutParams framelayout_params =
new ViewGroup.LayoutParams(ViewGroup.LayoutParams.FILL_PARENT,
ViewGroup.LayoutParams.FILL_PARENT);
FrameLayout framelayout = new FrameLayout(this);
framelayout.setLayoutParams(framelayout_params);
// Cocos2dxEditText layout
ViewGroup.LayoutParams edittext_layout_params =
new ViewGroup.LayoutParams(ViewGroup.LayoutParams.FILL_PARENT,
ViewGroup.LayoutParams.WRAP_CONTENT);
this.mGLSurfaceView = this.onCreateView();
// Switch to supported OpenGL (ARGB888) mode on emulator
if (isAndroidEmulator())
this.mGLSurfaceView.setEGLConfigChooser(8 , 8, 8, 8, 16, 0);
this.mGLSurfaceView.setCocos2dxRenderer(new Cocos2dxRenderer());
RelativeLayout relativeLayout = new RelativeLayout(getApplicationContext());
RelativeLayout.LayoutParams params = new RelativeLayout.LayoutParams(RelativeLayout.LayoutParams.MATCH_PARENT, RelativeLayout.LayoutParams.MATCH_PARENT);
params.addRule(RelativeLayout.ALIGN_PARENT_TOP);
relativeLayout.setLayoutParams(params);
//AdView adad = new AdView(this);
ClickBanner_CLickYab_Holder adad = new ClickBanner_CLickYab_Holder(this);
RelativeLayout.LayoutParams adad_params = new RelativeLayout.LayoutParams(RelativeLayout.LayoutParams.WRAP_CONTENT, RelativeLayout.LayoutParams.WRAP_CONTENT);
adad_params.addRule(RelativeLayout.CENTER_HORIZONTAL);
adad_params.addRule(RelativeLayout.ALIGN_PARENT_BOTTOM);
// adad.setToken(getString(R.string.adad_token));
adad.setLayoutParams(adad_params);
Button myButton = new Button(this);
myButton.setBackgroundResource(R.drawable.more);
RelativeLayout.LayoutParams adad_params1 = new RelativeLayout.LayoutParams(RelativeLayout.LayoutParams.WRAP_CONTENT,
RelativeLayout.LayoutParams.WRAP_CONTENT);
adad_params1.addRule(RelativeLayout.ALIGN_PARENT_RIGHT);
adad_params1.addRule(RelativeLayout.ALIGN_PARENT_TOP);
myButton.setLayoutParams(adad_params1);
myButton.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
PTPlayer.appList.Display();
}
});
Button myButton1 = new Button(this);
myButton1.setBackgroundResource(R.drawable.more);
RelativeLayout.LayoutParams adad_params2 = new RelativeLayout.LayoutParams(RelativeLayout.LayoutParams.WRAP_CONTENT,
RelativeLayout.LayoutParams.WRAP_CONTENT);
adad_params2.addRule(RelativeLayout.ALIGN_PARENT_LEFT);
adad_params2.addRule(RelativeLayout.ALIGN_PARENT_TOP);
myButton1.setLayoutParams(adad_params2);
myButton1.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
PTPlayer.appList.Display();
}
});
relativeLayout.addView(this.mGLSurfaceView);
relativeLayout.addView(adad);
relativeLayout.addView(myButton);
relativeLayout.addView(myButton1);
ClickBanner_CLickYab_Holder.setTestMode();
setContentView(relativeLayout);
}
public Cocos2dxGLSurfaceView onCreateView() {
return new Cocos2dxGLSurfaceView(this);
}
private final static boolean isAndroidEmulator() {
String model = Build.MODEL;
Log.d(TAG, "model=" + model);
String product = Build.PRODUCT;
Log.d(TAG, "product=" + product);
boolean isEmulator = false;
if (product != null) {
isEmulator = product.equals("sdk") || product.contains("_sdk") || product.contains("sdk_");
}
Log.d(TAG, "isEmulator=" + isEmulator);
return isEmulator;
}
}
you must use of Override Method for when back button pressed
if you want to stay on currnt activity use like this
#Override
public void onBackPressed() {
return;
}
if you want to use double click to exit and one click to stay you can use like this
first define a variable for double click
boolean doubleBackToExit = false;
and the Override backbutton method
#Override
public void onBackPressed() {
if (doubleBackToExit) {
//on double back button pressed
return;
}
this.doubleBackToExit = true;
new Handler().postDelayed(new Runnable() {
#Override
public void run() {
doubleBackToExit=false;
}
}, 2000);
}
Then do this.
#Override
public void onBackPressed() {
super.onBackPressed();
Intent intent = new Intent(MainActivityPhase2.this, GlobalSearch.class);
startActivity(intent);
finish();
}
Just don't call the super.onBackPressed() everytime.
#Override
public void onBackPressed() {
if (isFirstView()) {
super.onBackPressed();
} else {
switchToFirstView();
}
Call in only when there isn't any last view available. Or where you want to close the App. The code will finish your activity when you are on the first activity. And switch to first activity if you are on second activity.
Just replace my methods as per your code.
Overriding onBackPressed() of the activity and provide your screen where you want to go.
onBackpressed() check which is the current view you are showing and according to move to the first view.
in your second class Cocos2dxActivity, place this code.
#Override
public void onBackPressed() {
this.finish();
}
If you have just one activity with two View you can use Fragments.
Using Fragments, Activity.OnBackPressed() will remove last fragment in the stack and you can resolve your problem.
So, in the activity you have to put a container in xml layout file:
<FrameLayout android:id="#+id/container" android:layout_width="match_parent"
android:clickable="true" android:layout_height="match_parent"/>
In the Activity java file:
getFragmentManager().beginTransaction()
.add(R.id.container,new YourHomeFragment())
.commit();
So to add second Fragment you can use this code:
getFragmentManager().beginTransaction()
.add(R.id.container,new YourPlayFragment())
.addToBackStack("YourPlayFragment") //string what you want
.commit();
Pay attention: you can call this code or in YourHomeFragment class (into button clickListener) or in your Activity (using a callback system). For example:
In YourHomeFragment -->
playButton.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
getFragmentManager().beginTransaction()
.add(R.id.container,new YourPlayFragment())
.addToBackStack("YourPlayFragment") //string what you want
.commit();
}
});
In this way, you have to declare two layout xml file for fragments and one for Activity.
List of java and relative xml files:
MainActivity.java
activity_main.xml
YourHomeFragment.java
fragment_your_home.xml <-- insert here your first View
YourPlayFragment.java
fragment_your_play.xml <-- play view
I'm developing an android kind-of-gallery-app with Firebase, so I will have plenty of images. I know that I need to be careful about memory management.
When I was searching how to find memory leak in android apps, I came across with LeakCanary. It looks really great, so I used in my app.
Basically my app has 3 fragments, which are Drawer, ProductGrid and ProductDetail. Sometimes LeakCanary says that I have a memory leak in ProductGrid, but I couldn't find it! Usually, adapters or static methods or listeners could cause memory leak because of Context object, but my knowledge is not sufficient to say 'aah that's because of here'
Here are the classes. Where is the leak?(If you suggest me anything that I can improve my code or approach, I would be appreciated!)
Because of body character limit, I put the link leak canary log file.
How I suspect there is a memory leak
First of all, LeakCanary shows a dialog and logs the dump. Second thing is, when I click on an item in drawer, in grid and in detail like 15 times(respectively), memory usage increases. It starts with 18M, increases 22M-23M after showing 3 images(normal). Then it heads up to 29M-30M after clicking on 15 times. If you click on around 30-40, memory usage increases 34M-35M
Edit: I've just figured out that, if I open and close drawer, memory usage increases 0.05M everytime, so one time opening and closing drawer costs 0.1M! What am i missing?
Main.java
public class Main extends ActionBarActivity implements DrawerListener {
private Toolbar mToolbar;
private Drawer drawerFragment;
private HomePage homeFragment;
private FragmentHelper fh = new FragmentHelper();
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
if (homeFragment == null)
homeFragment = new HomePage();
if (savedInstanceState == null) {
mToolbar = (Toolbar) findViewById(R.id.toolbar);
setSupportActionBar(mToolbar);
getSupportActionBar().setDisplayShowHomeEnabled(true);
drawerFragment = (Drawer)
getSupportFragmentManager().findFragmentById(R.id.navigation_drawer);
drawerFragment.setUp(R.id.navigation_drawer,
(DrawerLayout) findViewById(R.id.drawer_layout), mToolbar);
drawerFragment.setDrawerListener(this);
drawerFragment.setRetainInstance(true);
displayView(null);
}
}
#Override
public boolean onCreateOptionsMenu(Menu menu) {
getMenuInflater().inflate(R.menu.menu_main, menu);
return true;
}
#Override
public boolean onOptionsItemSelected(MenuItem item) {
int id = item.getItemId();
if (id == R.id.action_home) {
getSupportActionBar().setTitle(getString(R.string.app_name));
fh.replace(getSupportFragmentManager(), homeFragment, R.id.container_body);
return true;
}
if (id == R.id.action_settings) {
return true;
}
if (id == R.id.action_search) {
Toast.makeText(getApplicationContext(), "Search action is selected!", Toast.LENGTH_SHORT).show();
return true;
}
return super.onOptionsItemSelected(item);
}
#Override
public void onDrawerItemSelected(View view, int position, Category category) {
displayView(category);
}
private void displayView(Category category) {
if (category != null) {
getSupportActionBar().setTitle(category.getName());
ProductGrid gridFragment = new ProductGrid();
Bundle args = new Bundle();
args.putString(Product.CATEGORY_ID, category.getId());
gridFragment.setArguments(args);
fh.replace(getSupportFragmentManager(), gridFragment, R.id.container_body);
} else {
getSupportActionBar().setTitle(getString(R.string.app_name));
fh.replace(getSupportFragmentManager(), homeFragment, R.id.container_body);
}
}
}
Drawer.java
public class Drawer extends Fragment {
private Firebase mFirebase;
private Alert alert;
private RecyclerView recyclerView;
private View containerView;
private DrawerLayout mDrawerLayout;
private ActionBarDrawerToggle mDrawerToggle;
private DrawerListener drawerListener;
private DrawerAdapter mAdapter;
private List<Category> mCategories;
public Drawer() {
}
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
alert = new Alert(getActivity().getApplicationContext());
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View layout = inflater.inflate(R.layout.drawer, container, false);
mCategories = new ArrayList<>();
mAdapter = new DrawerAdapter(mCategories);
recyclerView = (RecyclerView) layout.findViewById(R.id.drawer_list);
recyclerView.setLayoutManager(new LinearLayoutManager(getActivity().getApplicationContext()));
recyclerView.setItemAnimator(new SlideInOutLeftItemAnimator(recyclerView));
recyclerView.setAdapter(mAdapter);
mFirebase = new Firebase(getActivity().getResources().getString(R.string.firebase_ref))
.child(FirebaseRoots.CATEGORY);
Query query = mFirebase.orderByChild(Category.PRIO);
query.addChildEventListener(new ChildEventListener() {
#Override
public void onChildAdded(DataSnapshot dataSnapshot, String s) {
Category model = dataSnapshot.getValue(Category.class);
model.setId(dataSnapshot.getKey());
mCategories.add(model);
recyclerView.scrollToPosition(mCategories.size() - 1);
mAdapter.notifyItemInserted(mCategories.size() - 1);
}
#Override
public void onChildChanged(DataSnapshot dataSnapshot, String s) {
Category model = dataSnapshot.getValue(Category.class);
model.setId(dataSnapshot.getKey());
int index = -1;
for (int i = 0; i < mCategories.size(); i++) {
if (mCategories.get(i).getId().equals(model.getId())) {
index = i;
break;
}
}
mCategories.set(index, model);
recyclerView.scrollToPosition(0);
mAdapter.notifyItemChanged(index);
}
#Override
public void onChildRemoved(DataSnapshot dataSnapshot) {
Category model = dataSnapshot.getValue(Category.class);
model.setId(dataSnapshot.getKey());
int index = -1;
for (int i = 0; i < mCategories.size(); i++) {
if (mCategories.get(i).getId().equals(model.getId())) {
index = i;
break;
}
}
mCategories.remove(index);
recyclerView.scrollToPosition(0);
mAdapter.notifyItemRemoved(index);
}
#Override
public void onChildMoved(DataSnapshot dataSnapshot, String s) {
}
#Override
public void onCancelled(FirebaseError firebaseError) {
alert.show(firebaseError.toString());
}
});
recyclerView.addOnItemTouchListener(new RecyclerTouchListener(getActivity().getApplicationContext(),
recyclerView, new ClickListener() {
#Override
public void onClick(View view, int position) {
Category category = mCategories.get(position);
drawerListener.onDrawerItemSelected(view, position, category);
mDrawerLayout.closeDrawer(containerView);
}
#Override
public void onLongClick(View view, int position) {
}
}));
return layout;
}
public void setUp(int fragmentId, DrawerLayout drawerLayout, final Toolbar toolbar) {
containerView = getActivity().findViewById(fragmentId);
mDrawerLayout = drawerLayout;
mDrawerToggle = new ActionBarDrawerToggle(getActivity(), drawerLayout, toolbar, R.string.drawer_open, R.string.drawer_close) {
#Override
public void onDrawerOpened(View drawerView) {
super.onDrawerOpened(drawerView);
getActivity().invalidateOptionsMenu();
}
#Override
public void onDrawerClosed(View drawerView) {
super.onDrawerClosed(drawerView);
getActivity().invalidateOptionsMenu();
}
#Override
public void onDrawerSlide(View drawerView, float slideOffset) {
super.onDrawerSlide(drawerView, slideOffset);
toolbar.setAlpha(1 - slideOffset / 2);
}
};
mDrawerLayout.setDrawerListener(mDrawerToggle);
mDrawerLayout.post(new Runnable() {
#Override
public void run() {
mDrawerToggle.syncState();
}
});
}
public void setDrawerListener(DrawerListener listener) {
this.drawerListener = listener;
}
}
ProductGrid.java
public class ProductGrid extends Fragment implements ChildEventListener{
private Firebase mFirebaseRef;
private Alert alert;
private RecyclerView recyclerView;
private GridAdapter mAdapter;
private String categoryId;
private ArrayList<Product> mProducts;
private FileSystem fs;
public ProductGrid() {
}
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
this.categoryId = getArguments().getString(Product.CATEGORY_ID);
this.alert = new Alert(getActivity().getApplicationContext());
this.fs = new FileSystem(getActivity().getApplicationContext());
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View layout = inflater.inflate(R.layout.grid, container, false);
fieldInitialize(layout);
mProducts = new ArrayList<>();
mAdapter = new GridAdapter(mProducts, getActivity().getApplicationContext());
recyclerView.addItemDecoration(new MarginDecoration(getActivity()));
recyclerView.setHasFixedSize(true);
recyclerView.setLayoutManager(new GridLayoutManager(getActivity(), 2));
recyclerView.setAdapter(mAdapter);
mFirebaseRef = new Firebase(getActivity().getResources().getString(R.string.firebase_ref))
.child(FirebaseRoots.PRODUCT);
Query query = mFirebaseRef.orderByChild(Product.CATEGORY_ID).equalTo(categoryId);
query.addChildEventListener(this);
recyclerView.addOnItemTouchListener(new RecyclerTouchListener(getActivity(), recyclerView, new ClickListener() {
#Override
public void onClick(View view, int position) {
ProductDetail detailFragment = new ProductDetail();
Bundle args = new Bundle();
args.putSerializable("product", mProducts);
args.putInt("position", position);
detailFragment.setArguments(args);
FragmentTransaction transaction = getFragmentManager().beginTransaction();
transaction.replace(R.id.container_body, detailFragment);
transaction.addToBackStack(null);
transaction.commit();
}
#Override
public void onLongClick(View view, int position) {
}
}));
return layout;
}
#Override
public void onAttach(Activity activity) {
super.onAttach(activity);
}
#Override
public void onDetach() {
super.onDetach();
}
public void fieldInitialize(View layout) {
recyclerView = (RecyclerView) layout.findViewById(R.id.product_grid_layout);
}
#Override
public void onChildAdded(DataSnapshot dataSnapshot, String s) {
Product model = dataSnapshot.getValue(Product.class);
model.setId(dataSnapshot.getKey());
mProducts.add(model);
if (!fs.getFileNames().contains(model.getName() + FileExt.JPG.get())) {
fs.writeImage(model.getName(), ImageUtil.base64ToBitmap(
StringUtil.getBase64FromUrl(model.getImageData().getDataUrl())));
}
Collections.sort(mProducts);
recyclerView.scrollToPosition(0);
mAdapter.notifyItemInserted(mProducts.size() - 1);
}
#Override
public void onChildChanged(DataSnapshot dataSnapshot, String s) {
Product model = dataSnapshot.getValue(Product.class);
model.setId(dataSnapshot.getKey());
fs.writeImage(model.getName(), ImageUtil.base64ToBitmap(
StringUtil.getBase64FromUrl(model.getImageData().getDataUrl())));
int index = -1;
for (int i = 0; i < mProducts.size(); i++) {
if (mProducts.get(i).getId().equals(model.getId())) {
index = i;
break;
}
}
mProducts.set(index, model);
recyclerView.scrollToPosition(0);
mAdapter.notifyItemChanged(index);
}
#Override
public void onChildRemoved(DataSnapshot dataSnapshot) {
Product model = dataSnapshot.getValue(Product.class);
model.setId(dataSnapshot.getKey());
fs.deleteImage(model.getName());
int index = -1;
for (int i = 0; i < mProducts.size(); i++) {
if (mProducts.get(i).getId().equals(model.getId())) {
index = i;
break;
}
}
mProducts.remove(index);
recyclerView.scrollToPosition(0);
mAdapter.notifyItemRemoved(index);
}
#Override
public void onChildMoved(DataSnapshot dataSnapshot, String s) {
}
#Override
public void onCancelled(FirebaseError firebaseError) {
alert.show(firebaseError.toString());
}
#Override public void onDestroy() {
super.onDestroy();
RefWatcher refWatcher = AcarsanApp.getRefWatcher(getActivity());
refWatcher.watch(this);
}
}
ProductDetail.java
public class ProductDetail extends Fragment {
private FullScreenImageAdapter adapter;
private ViewPager viewPager;
private ArrayList<Product> products;
private int position;
public ProductDetail() {
}
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
products = (ArrayList<Product>) getArguments().getSerializable("product");
position = getArguments().getInt("position");
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.product_detail, container, false);
viewPager = (ViewPager) view.findViewById(R.id.product_gallery);
adapter = new FullScreenImageAdapter(getActivity().getApplicationContext(), products);
viewPager.setAdapter(adapter);
viewPager.setCurrentItem(position);
return view;
}
#Override
public void onAttach(Activity activity) {
super.onAttach(activity);
}
#Override
public void onDetach() {
super.onDetach();
}
}
FileSystem
public class FileSystem {
private Context mContext;
public static final String PHOTOS_FOLDER = "photos";
public FileSystem(Context mContext) {
this.mContext = mContext;
}
public void writeImage(String name, Bitmap bitmap) {
String filename = name + FileExt.JPG.get();
File dir = mContext.getDir(PHOTOS_FOLDER, Context.MODE_PRIVATE);
File fileWithinDir = new File(dir, filename);
FileOutputStream outputStream;
try {
outputStream = new FileOutputStream(fileWithinDir);
bitmap.compress(Bitmap.CompressFormat.JPEG, 100, outputStream);
outputStream.close();
} catch (Exception e) {
e.printStackTrace();
}
}
public List<String> getFileNames() {
List<String> fileNames = new ArrayList<>();
File file = mContext.getDir(PHOTOS_FOLDER, Context.MODE_PRIVATE);
File[] files = file.listFiles();
for (File f : files) {
fileNames.add(f.getName());
}
return fileNames;
}
}
ImageUtil
public class ImageUtil {
public static Bitmap base64ToBitmap(String encodedImage) {
if (encodedImage == null)
return null;
byte[] decodedString = Base64.decode(encodedImage, Base64.DEFAULT);
return BitmapFactory.decodeByteArray(decodedString, 0, decodedString.length);
}
}