I'm testing the new support library leanback to design apps for TV, and i have a error ever android try to inflate the BrowseFragment and it throws this exception and don't know how to solve it. Thank you so much for your help.
Error -
java.lang.RuntimeException: Unable to start activity ComponentInfo{com.directsportsnetwork.tv/com.directsportsnetwork.tv.ui.TeamSclActivity}: android.view.InflateException: Binary XML file line #67 in com.directsportsnetwork.tv:layout/activity_teamscl: Binary XML file line #24 in com.directsportsnetwork.tv:layout/lb_browse_fragment: Binary XML file line #24 in com.directsportsnetwork.tv:layout/lb_browse_fragment: Error inflating class androidx.leanback.widget.BrowseFrameLayout
at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:3449)
at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:3601)
at android.app.servertransaction.LaunchActivityItem.execute(LaunchActivityItem.java:85)
at android.app.servertransaction.TransactionExecutor.executeCallbacks(TransactionExecutor.java:135)
at android.app.servertransaction.TransactionExecutor.execute(TransactionExecutor.java:95)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:2066)
at android.os.Handler.dispatchMessage(Handler.java:106)
at android.os.Looper.loop(Looper.java:223)
at android.app.ActivityThread.main(ActivityThread.java:7656)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:592)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:947)
Caused by: android.view.InflateException: Binary XML file line #67 in com.directsportsnetwork.tv:layout/activity_teamscl: Binary XML file line #24 in com.directsportsnetwork.tv:layout/lb_browse_fragment: Binary XML file line #24 in com.directsportsnetwork.tv:layout/lb_browse_fragment: Error inflating class androidx.leanback.widget.BrowseFrameLayout
Caused by: android.view.InflateException: Binary XML file line #24 in com.directsportsnetwork.tv:layout/lb_browse_fragment: Binary XML file line #24 in com.directsportsnetwork.tv:layout/lb_browse_fragment: Error inflating class androidx.leanback.widget.BrowseFrameLayout
Caused by: android.view.InflateException: Binary XML file line #24 in com.directsportsnetwork.tv:layout/lb_browse_fragment: Error inflating class androidx.leanback.widget.BrowseFrameLayout
Caused by: java.lang.NullPointerException: Attempt to invoke virtual method 'java.lang.Object java.lang.reflect.Field.get(java.lang.Object)' on a null object reference
at uk.co.chrisjenx.calligraphy.ReflectionUtils.getValue(ReflectionUtils.java:29)
at uk.co.chrisjenx.calligraphy.CalligraphyLayoutInflater.createCustomViewInternal(CalligraphyLayoutInflater.java:203)
at uk.co.chrisjenx.calligraphy.CalligraphyLayoutInflater.access$000(CalligraphyLayoutInflater.java:20)
at uk.co.chrisjenx.calligraphy.CalligraphyLayoutInflater$PrivateWrapperFactory2.onCreateView(CalligraphyLayoutInflater.java:302)
at android.view.LayoutInflater$FactoryMerger.onCreateView(LayoutInflater.java:237)
at android.view.LayoutInflater.tryCreateView(LayoutInflater.java:1067)
at android.view.LayoutInflater.createViewFromTag(LayoutInflater.java:995)
at android.view.LayoutInflater.createViewFromTag(LayoutInflater.java:959)
at android.view.LayoutInflater.rInflate(LayoutInflater.java:1121)
at android.view.LayoutInflater.rInflateChildren(LayoutInflater.java:1082)
at android.view.LayoutInflater.inflate(LayoutInflater.java:680)
at uk.co.chrisjenx.calligraphy.CalligraphyLayoutInflater.inflate(CalligraphyLayoutInflater.java:60)
at android.view.LayoutInflater.inflate(LayoutInflater.java:532)
at androidx.leanback.app.BrowseFragment.onCreateView(BrowseFragment.java:1318)
at android.app.Fragment.performCreateView(Fragment.java:2505)
at android.app.FragmentManagerImpl.ensureInflatedFragmentView(FragmentManager.java:1491)
at android.app.FragmentManagerImpl.moveToState(FragmentManager.java:1274)
at android.app.FragmentManagerImpl.moveToState(FragmentManager.java:1486)
at android.app.FragmentManagerImpl.addFragment(FragmentManager.java:1728)
E/AndroidRuntime: at android.app.FragmentManagerImpl.onCreateView(FragmentManager.java:3562)
at android.app.FragmentController.onCreateView(FragmentController.java:104)
at android.app.Activity.onCreateView(Activity.java:7112)
at androidx.fragment.app.FragmentActivity.onCreateView(FragmentActivity.java:229)
at uk.co.chrisjenx.calligraphy.CalligraphyLayoutInflater$PrivateWrapperFactory2.onCreateView(CalligraphyLayoutInflater.java:303)
at android.view.LayoutInflater$FactoryMerger.onCreateView(LayoutInflater.java:237)
at android.view.LayoutInflater.tryCreateView(LayoutInflater.java:1067)
at android.view.LayoutInflater.createViewFromTag(LayoutInflater.java:995)
at android.view.LayoutInflater.createViewFromTag(LayoutInflater.java:959)
at android.view.LayoutInflater.rInflate(LayoutInflater.java:1121)
at android.view.LayoutInflater.rInflateChildren(LayoutInflater.java:1082)
at android.view.LayoutInflater.inflate(LayoutInflater.java:680)
at uk.co.chrisjenx.calligraphy.CalligraphyLayoutInflater.inflate(CalligraphyLayoutInflater.java:60)
at android.view.LayoutInflater.inflate(LayoutInflater.java:532)
at android.view.LayoutInflater.inflate(LayoutInflater.java:479)
at android.transition.Scene.enter(Scene.java:182)
at com.android.internal.policy.PhoneWindow.transitionTo(PhoneWindow.java:522)
at com.android.internal.policy.PhoneWindow.setContentView(PhoneWindow.java:453)
at android.app.Activity.setContentView(Activity.java:3468)
at androidx.activity.ComponentActivity.setContentView(ComponentActivity.java:448)
at com.directsportsnetwork.tv.ui.TeamSclActivity.onCreate(TeamSclActivity.java:55)
at android.app.Activity.performCreate(Activity.java:8000)
at android.app.Activity.performCreate(Activity.java:7984)
at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1309)
at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:3422)
at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:3601)
at android.app.servertransaction.LaunchActivityItem.execute(LaunchActivityItem.java:85)
at android.app.servertransaction.TransactionExecutor.executeCallbacks(TransactionExecutor.java:135)
at android.app.servertransaction.TransactionExecutor.execute(TransactionExecutor.java:95)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:2066)
at android.os.Handler.dispatchMessage(Handler.java:106)
at android.os.Looper.loop(Looper.java:223)
at android.app.ActivityThread.main(ActivityThread.java:7656)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:592)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:947)
My Activity code is -
package com.directsportsnetwork.tv.ui;
import android.annotation.SuppressLint;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.os.Bundle;
import android.os.Handler;
import android.view.KeyEvent;
import android.widget.ImageView;
import android.widget.RelativeLayout;
import androidx.core.content.ContextCompat;
import androidx.fragment.app.FragmentActivity;
import com.directsportsnetwork.tv.R;
import com.directsportsnetwork.tv.api.DeviceLogManager;
import com.directsportsnetwork.tv.api.Utils;
import org.json.JSONArray;
import java.util.HashMap;
import uk.co.chrisjenx.calligraphy.CalligraphyContextWrapper;
public class TeamSclActivity extends FragmentActivity {
private String TAG = TeamSclActivity.class.getSimpleName();
private ImageView topShelfImg, topShelfMask;
private TeamSclFragment mTeamSclFragment;
private BroadcastReceiver broadcastReceiver = new BroadcastReceiver() {
#Override
public void onReceive(Context context, Intent intent) {
finish();
}
};
#SuppressWarnings("unchecked")
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_teamscl);
IntentFilter filter = new IntentFilter();
filter.addAction("com.directsportsnetwork.tv.STOP");
registerReceiver(broadcastReceiver, filter);
DeviceLogManager.instance().sendTeamSelectionPageData(TeamSclActivity.this);
topShelfImg = (ImageView) findViewById(R.id.top_shelf_image);
topShelfMask = (ImageView) findViewById(R.id.top_shelf_mask);
Intent intent = getIntent();
if (intent != null) {
try {
String channelData = intent.getStringExtra(Utils.EXTRA_CHANNEL_RESPONSE);
HashMap<String, Integer> teamTrnMap = (HashMap<String, Integer>) intent.getSerializableExtra(Utils.EXTRA_TEAM_TRN_MAP);
mTeamSclFragment = (TeamSclFragment) getFragmentManager().findFragmentById(R.id.main_browse_fragment);
mTeamSclFragment.onResponseData(new JSONArray(channelData), teamTrnMap);
} catch (Exception e) {
e.printStackTrace();
}
setTopShelfMask();
final Handler mHandler = new Handler();
mHandler.postDelayed(new Runnable() {
#Override
public void run() {
try {
mHandler.postDelayed(this, 300);
if (mTeamSclFragment.getView() != null && getCurrentFocus() instanceof RelativeLayout) {
mTeamSclFragment.getView().requestFocus();
mHandler.removeCallbacks(this);
mHandler.removeCallbacksAndMessages(null);
}
}catch (Exception e) {
e.printStackTrace();
}
}
}, 300); //Changes START HERE FOR NEW CHANGES - 10/20/2018
}
}
#Override
protected void attachBaseContext(Context newBase) {
super.attachBaseContext(CalligraphyContextWrapper.wrap(newBase));
}
#Override
protected void onResume() {
super.onResume();
}
#Override
protected void onPause() {
super.onPause();
}
#Override
protected void onDestroy() {
super.onDestroy();
unregisterReceiver(broadcastReceiver);
}
#SuppressLint("MissingSuperCall")
#Override
protected void onSaveInstanceState(Bundle outState) {
//No call for super(). Bug on API Level > 11.
}
// remot Button OnClickListener methods
#Override
public boolean onKeyUp(int keyCode, KeyEvent event) {
switch (keyCode) {
case KeyEvent.KEYCODE_DPAD_LEFT:
case KeyEvent.KEYCODE_DPAD_RIGHT:
case KeyEvent.KEYCODE_DPAD_UP:
case KeyEvent.KEYCODE_DPAD_DOWN:
// Remove shadow over topShelfImage at here
if (mTeamSclFragment != null) {
mTeamSclFragment.startBackgroundTimer();
}
default:
return super.onKeyUp(keyCode, event);
}
}
#Override
public boolean onKeyDown(int keyCode, KeyEvent event) {
if (keyCode == KeyEvent.KEYCODE_DPAD_LEFT || keyCode == KeyEvent.KEYCODE_DPAD_RIGHT
|| keyCode == KeyEvent.KEYCODE_DPAD_DOWN || keyCode == KeyEvent.KEYCODE_DPAD_UP) {
// Add shadow over topShelfImage at here
topShelfImg.setAlpha(0.3f);
}
if (mTeamSclFragment != null) {
mTeamSclFragment.onMyKeyDown(keyCode, event);
}
return false;
}
public ImageView getTopShelfImg() {
return topShelfImg;
}
public void setTopShelfMask() {
if (Utils.SHOW_TOP_SHELF_MASK) {
topShelfMask.setBackground(ContextCompat.getDrawable(TeamSclActivity.this, R.drawable.ic_mask_bottom));
}
}
}
My Fragment code -
package com.directsportsnetwork.tv.ui;
import static androidx.leanback.app.BackgroundManager.getInstance;
import android.app.AlertDialog;
import android.content.DialogInterface;
import android.content.Intent;
import android.graphics.Color;
import android.graphics.drawable.Drawable;
import android.os.Bundle;
import android.os.Handler;
import android.util.DisplayMetrics;
import android.util.Log;
import android.view.KeyEvent;
import android.view.View;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.core.content.ContextCompat;
import androidx.leanback.app.BackgroundManager;
import androidx.leanback.app.BrowseFragment;
import androidx.leanback.widget.ArrayObjectAdapter;
import androidx.leanback.widget.FocusHighlight;
import androidx.leanback.widget.HeaderItem;
import androidx.leanback.widget.ListRow;
import androidx.leanback.widget.ListRowPresenter;
import androidx.leanback.widget.OnItemViewClickedListener;
import androidx.leanback.widget.OnItemViewSelectedListener;
import androidx.leanback.widget.Presenter;
import androidx.leanback.widget.Row;
import androidx.leanback.widget.RowPresenter;
import com.bumptech.glide.Glide;
import com.bumptech.glide.request.target.CustomTarget;
import com.bumptech.glide.request.transition.Transition;
import com.directsportsnetwork.tv.R;
import com.directsportsnetwork.tv.api.OnResponseReceived;
import com.directsportsnetwork.tv.api.TvApplication;
import com.directsportsnetwork.tv.api.Utils;
import com.directsportsnetwork.tv.model.Team;
import com.directsportsnetwork.tv.presenter.TeamPresenter;
import com.directsportsnetwork.tv.provider.DataBaseHelper;
import org.json.JSONArray;
import org.json.JSONObject;
import java.net.URI;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Random;
import java.util.Timer;
import java.util.TimerTask;
public class TeamSclFragment extends BrowseFragment implements OnResponseReceived {
private final String TAGS = "TeamSclFragment";
private final Handler mHandler = new Handler();
private Drawable mDefaultBackground;
private DisplayMetrics mMetrics;
private Timer mBackgroundTimer;
private URI mBackgroundURI;
private URI defaultBackgroundURI;
public Team selectedTeam;
private JSONArray teamData;
private HashMap<String, Integer> teamTrnMap;
#Override
public void onActivityCreated(Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
}
private boolean isFavoriteDisable(String teamId) {
return !(teamTrnMap != null && teamTrnMap.get(teamId) != null);
}
private int getTrnByTeamId(String teamId) {
return teamTrnMap.get(teamId);
}
#Override
public void onResponseData(JSONArray data, HashMap<String, Integer> teamTrnMap) {
try {
Log.e(TAGS, "apiResponse: " + data);
teamData = data;
this.teamTrnMap = teamTrnMap;
prepareBackgroundManager();
setupUIElements();
// Set rows as per data fetched form API
loadTeamRows(teamData);
setupEventListeners();
} catch (Exception e) {
e.printStackTrace();
}
}
#Override
public void onDestroy() {
super.onDestroy();
if (null != mBackgroundTimer) {
mBackgroundTimer.cancel();
}
}
#Override
public void onResume() {
super.onResume();
if (TvApplication.isFavChanged && teamData != null) {
loadTeamRows(teamData);
TvApplication.isFavChanged = false;
if (getView() != null) {
getView().requestFocus();
setSelectedPosition(0, true);
startBackgroundTimer();
}
}
}
#Override
public void onPause() {
super.onPause();
}
public void onMyKeyDown(int keyCode, KeyEvent event) {
//do whatever you want here
switch (keyCode) {
case KeyEvent.KEYCODE_BACK:
getActivity().finish();
getActivity().overridePendingTransition(android.R.anim.fade_in, android.R.anim.fade_out);
break;
}
}
private void loadTeamRows(JSONArray teamCategoryList) {
try {
ArrayList<Team> favTeamList = new ArrayList<>();
if (Utils.isStoragePermissionGranted(getActivity())) {
DataBaseHelper dataBase = DataBaseHelper.getInstance(getActivity());
favTeamList = dataBase.getAllFavorites();
} else {
favTeamList.add(null);
Utils.showToast(getActivity(), getResources().getString(R.string.no_storage_permission));
}
ListRowPresenter mListRowPresenter = new ListRowPresenter(FocusHighlight.ZOOM_FACTOR_NONE, true);
ArrayObjectAdapter mRowsAdapter = new ArrayObjectAdapter(mListRowPresenter);
TeamPresenter teamPresenter = new TeamPresenter();
for (int i = 0; i < teamCategoryList.length() + 1; i++) {
ArrayObjectAdapter listRowAdapter = new ArrayObjectAdapter(teamPresenter);
if (i == 0) {
// This is to create Favorite card row
for (int index = 0; index < favTeamList.size(); index++) {
if (favTeamList.get(index) == null) {
listRowAdapter.add(getResources().getString(R.string.favorites));
} else {
Team team = favTeamList.get(index);
team.setIsFavorite(1);
if (isFavoriteDisable(team.getId())) {
// TODO: Team is disabled, remove it from favorites
DataBaseHelper dataBase = DataBaseHelper.getInstance(getActivity());
dataBase.removeFavorite(team.getId());
TvApplication.isFavChanged = true;
continue;
} else {
team.setReleaseNo(getTrnByTeamId(team.getId()));
}
listRowAdapter.add(team);
}
}
HeaderItem header = new HeaderItem(i, "Favorites");
mRowsAdapter.add(new ListRow(header, listRowAdapter));
} else {
JSONArray teamList = teamCategoryList.getJSONObject(i - 1).getJSONArray("team");
String category = teamCategoryList.getJSONObject(i - 1).getString("name");
String categoryId = teamCategoryList.getJSONObject(i - 1).getString("id");
for (int index = 0; index < teamList.length(); index++) {
JSONObject teamObj = teamList.getJSONObject(index);
String id = teamObj.getString("id");
String name = teamObj.getString("name");
String shortdesc = teamObj.getString("shortdesc");
String longdesc = teamObj.getString("longdesc");
int trn = teamObj.getInt("trn");
//trn stands for Team Release Number
Team team = new Team();
team.setCatId(categoryId);
team.setCatName(category);
team.setId(id);
team.setName(name);
team.setShortdesc(shortdesc);
team.setLongdesc(longdesc);
team.setIsFavorite(0);
team.setReleaseNo(trn);
if (category.equalsIgnoreCase("NASCAR")) {
team.setIsNascar(1);
} else {
team.setIsNascar(0);
}
listRowAdapter.add(team);
}
HeaderItem header = new HeaderItem(i, category);
mRowsAdapter.add(new ListRow(header, listRowAdapter));
}
}
setAdapter(mRowsAdapter);
} catch (Exception e) {
e.printStackTrace();
}
}
private void prepareBackgroundManager() {
BackgroundManager mBackgroundManager = getInstance(getActivity());
mBackgroundManager.attach(getActivity().getWindow());
mDefaultBackground = ContextCompat.getDrawable(getActivity(), R.drawable.default_background);
mBackgroundManager.setColor(Color.BLACK);
mMetrics = new DisplayMetrics();
getActivity().getWindowManager().getDefaultDisplay().getMetrics(mMetrics);
}
private void setupUIElements() {
getTitleView().setVisibility(View.GONE);
// To hide left side header for BrowseFragment
setHeadersState(HEADERS_DISABLED);
setHeadersTransitionOnBackEnabled(true);
}
private void setupEventListeners() {
setOnItemViewClickedListener(new ItemViewClickedListener());
setOnItemViewSelectedListener(new ItemViewSelectedListener());
}
protected void updateBackground(String uri) {
try {
int width = mMetrics.widthPixels;
int height = mMetrics.heightPixels;
final TeamSclActivity activity = ((TeamSclActivity) getActivity());
if (activity.getTopShelfImg().getDrawable().getConstantState() == getResources().getDrawable(R.drawable.ic_start).getConstantState() && (uri == defaultBackgroundURI.toString())) {
} else {
//start
if (activity != null) {
Glide.with(activity).load(uri).error(mDefaultBackground).placeholder(R.drawable.teamblank).into(new CustomTarget<Drawable>(width, height) {
#Override
public void onResourceReady(#NonNull Drawable resource, #Nullable Transition<? super Drawable> transition) {
activity.getTopShelfImg().setImageDrawable(resource);
Utils.crossfade(activity.getTopShelfImg());
}
#Override
public void onLoadCleared(#Nullable Drawable placeholder) {
}
});
}
//end
}
mBackgroundTimer.cancel();
} catch (Exception e) {
e.printStackTrace();
}
}
public void startBackgroundTimer() {
if (mBackgroundTimer != null) {
mBackgroundTimer.cancel();
}
mBackgroundTimer = new Timer();
mBackgroundTimer.schedule(new UpdateBackgroundTask(), Utils.BACKGROUND_UPDATE_DELAY);
}
private final class ItemViewClickedListener implements OnItemViewClickedListener {
#Override
public void onItemClicked(Presenter.ViewHolder itemViewHolder, Object item, RowPresenter.ViewHolder rowViewHolder, Row row) {
if (item instanceof Team) {
Team team = (Team) item;
Intent intent = new Intent(getActivity(), TeamChnlActivity.class);
intent.putExtra(Utils.EXTRA_TEAM, team);
startActivity(intent);
} else if (item instanceof String) {
AlertDialog.Builder builder = new AlertDialog.Builder(getActivity());
builder.setMessage(getResources().getString(R.string.favorite_alert_msg));
builder.setCancelable(true);
builder.setPositiveButton("Ok", new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int id) {
dialog.cancel();
}
});
AlertDialog alert = builder.create();
alert.show();
}
}
}
private final class ItemViewSelectedListener implements OnItemViewSelectedListener {
#Override
public void onItemSelected(Presenter.ViewHolder itemViewHolder, Object item, RowPresenter.ViewHolder rowViewHolder, Row row) {
if (item instanceof Team) {
Team team = ((Team) item);
try {
selectedTeam = team;
mBackgroundURI = new URI(team.getTopShelfImageUrl(team.getId(), team.getReleaseNo()));
defaultBackgroundURI = new URI(Utils.MEDIA_PREFIX_URL + "/tv/images/app/start.jpg?");
if (team.getIsFavorite() == 1) {
startBackgroundTimer();
}
} catch (Exception e) {
e.printStackTrace();
}
} else if (item instanceof String) {
try {
selectedTeam = null;
Random random = new Random();
mBackgroundURI = new URI(Utils.MEDIA_PREFIX_URL + "/tv/images/app/start.jpg?" + random.nextInt(100));
defaultBackgroundURI = mBackgroundURI;
startBackgroundTimer();
} catch (Exception e) {
e.printStackTrace();
}
}
}
}
private class UpdateBackgroundTask extends TimerTask {
#Override
public void run() {
mHandler.post(new Runnable() {
#Override
public void run() {
if (mBackgroundURI != null) {
updateBackground(mBackgroundURI.toString());
}
}
});
}
}
}
My activity_teamscl.xml code -
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent">
<fragment
android:id="#+id/main_browse_fragment"
android:name="com.directsportsnetwork.tv.ui.TeamSclFragment"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_alignParentBottom="true"
android:layout_alignTop="#+id/center_baseline"
tools:context=".ui.TeamSclActivity"
tools:deviceIds="tv"
tools:ignore="MergeRootFrame" />
</RelativeLayout>
Related
I'm doing a Simple Media Recorder/Player App and the recording part is successfully done. But now I'm having problems with the media player's part. Let me tell you the issues:
When I try to play a media file with the Media Player it says a preparing error like this:
java.io.IOException: Prepare failed.: status=0x1
How can I solve this problem?
My Three Classes:
-RecordFragment.java:
import android.Manifest;
import android.annotation.SuppressLint;
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.media.MediaRecorder;
import android.net.Uri;
import android.os.Build;
import android.os.Bundle;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.appcompat.app.AlertDialog;
import androidx.core.content.ContextCompat;
import androidx.core.content.res.ResourcesCompat;
import androidx.fragment.app.Fragment;
import android.os.Environment;
import android.os.SystemClock;
import android.provider.Settings;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.Chronometer;
import android.widget.TextView;
import android.widget.Toast;
import com.airbnb.lottie.LottieAnimationView;
import com.google.android.material.floatingactionbutton.FloatingActionButton;
import com.venomapps.voicerecorder.R;
import com.venomapps.voicerecorder.Utils.Constants;
import java.io.File;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Locale;
public class RecordFragment extends Fragment {
private TextView textViewInformation;
private FloatingActionButton floatingActionButtonStartRecording;
private FloatingActionButton floatingActionButtonFinishRecording;
private FloatingActionButton floatingActionButtonCancelRecording;
private int recordingStatus = 0;
private String fileName = "";
private Context context;
String[] permissions = {Manifest.permission.RECORD_AUDIO, Manifest.permission.WRITE_EXTERNAL_STORAGE};
private MediaRecorder mediaRecorder;
private String outPutFilePath;
private Chronometer chronometerRecord;
private boolean running;
private long pauseOffset;
private LottieAnimationView lottieAnimationViewVoice;
public RecordFragment() {
}
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
return inflater.inflate(R.layout.fragment_record, container, false);
}
#Override
public void onViewCreated(#NonNull View view, #Nullable Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
context = getActivity();
bindUI(view);
setListeners();
}
private void bindUI(View view) {
textViewInformation = view.findViewById(R.id.textViewInformation);
floatingActionButtonStartRecording = view.findViewById(R.id.floatingActionButtonStartRecording);
floatingActionButtonFinishRecording = view.findViewById(R.id.floatingActionButtonFinishRecording);
floatingActionButtonCancelRecording = view.findViewById(R.id.floatingActionButtonCancelRecording);
chronometerRecord = view.findViewById(R.id.chronometerRecord);
lottieAnimationViewVoice = view.findViewById(R.id.lottieAnimationViewVoice);
}
private void setListeners() {
floatingActionButtonStartRecording.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
if (ContextCompat.checkSelfPermission(context,
Manifest.permission.WRITE_EXTERNAL_STORAGE) == PackageManager.PERMISSION_GRANTED && ContextCompat.checkSelfPermission(context,
Manifest.permission.RECORD_AUDIO) == PackageManager.PERMISSION_GRANTED) {
switch (recordingStatus) {
case 0:
startRecording();
break;
case 1:
if (Build.VERSION.SDK_INT >= 24) {
pauseRecording();
} else {
finishRecording();
}
break;
case 2:
resumeRecording();
case 3:
break;
}
} else {
askPermissions();
}
}
});
floatingActionButtonFinishRecording.setOnClickListener(new View.OnClickListener() {
#SuppressLint("SetTextI18n")
#Override
public void onClick(View view) {
if (recordingStatus == 1 || recordingStatus == 2) {
finishRecording();
} else {
Toast.makeText(getActivity(), getString(R.string.not_recording), Toast.LENGTH_SHORT).show();
}
}
});
floatingActionButtonCancelRecording.setOnClickListener(new View.OnClickListener() {
#SuppressLint("SetTextI18n")
#Override
public void onClick(View view) {
if (recordingStatus == 1 || recordingStatus == 2) {
cancelRecording();
} else {
Toast.makeText(getActivity(), getString(R.string.not_recording), Toast.LENGTH_SHORT).show();
}
}
});
chronometerRecord.setOnChronometerTickListener(new Chronometer.OnChronometerTickListener() {
#Override
public void onChronometerTick(Chronometer chronometer) {
long time = SystemClock.elapsedRealtime() - chronometer.getBase();
int h = (int) (time / 3600000);
int m = (int) (time - h * 3600000) / 60000;
int s = (int) (time - h * 3600000 - m * 60000) / 1000;
String t = (h < 10 ? "0" + h : h) + ":" + (m < 10 ? "0" + m : m) + ":" + (s < 10 ? "0" + s : s);
chronometer.setText(t);
}
});
}
#SuppressLint("SetTextI18n")
private void startRecording() {
String basePath = Environment.getExternalStorageDirectory().toString();
String date = getCurrentDateFormatted();
String myDirectory = "Voice Recorder";
fileName = getString(R.string.recording_file) + date;
fileName = fileName.replace(" ", "");
fileName = fileName.replace("|", "");
fileName = fileName + ".mp3";
outPutFilePath = basePath + File.separator + myDirectory + File.separator + fileName;
String filePath = basePath + File.separator + myDirectory;
File newFolder = new File(filePath);
if (!newFolder.exists()) {
boolean createFolder = newFolder.mkdirs();
if (createFolder) {
Log.d("VOICE_RECORDER", "Created folder successfully!");
}
}
recordingStatus = 1;
mediaRecorder = new MediaRecorder();
if (Build.VERSION.SDK_INT >= 24) {
floatingActionButtonStartRecording.setImageDrawable(ResourcesCompat.getDrawable(getResources(), R.drawable.ic_pause_orange, null));
} else {
floatingActionButtonStartRecording.setImageDrawable(ResourcesCompat.getDrawable(getResources(), R.drawable.ic_stop_red, null));
}
textViewInformation.setText(getString(R.string.recording));
lottieAnimationViewVoice.playAnimation();
lottieAnimationViewVoice.setVisibility(View.VISIBLE);
mediaRecorder.setAudioSource(MediaRecorder.AudioSource.MIC);
mediaRecorder.setOutputFormat(MediaRecorder.OutputFormat.MPEG_4);
mediaRecorder.setOutputFile(outPutFilePath);
mediaRecorder.setAudioEncoder(MediaRecorder.AudioEncoder.AAC);
mediaRecorder.setAudioEncodingBitRate(16 * 44100);
mediaRecorder.setAudioSamplingRate(44100);
try {
mediaRecorder.prepare();
mediaRecorder.start();
if (!running) {
chronometerRecord.setVisibility(View.VISIBLE);
chronometerRecord.setBase(SystemClock.elapsedRealtime());
chronometerRecord.start();
running = true;
}
} catch (Exception e) {
e.printStackTrace();
}
}
private void pauseRecording() {
if (Build.VERSION.SDK_INT >= 24) {
mediaRecorder.pause();
}
if (running) {
chronometerRecord.stop();
pauseOffset = SystemClock.elapsedRealtime() - chronometerRecord.getBase();
running = false;
}
lottieAnimationViewVoice.cancelAnimation();
lottieAnimationViewVoice.setFrame(0);
lottieAnimationViewVoice.setVisibility(View.INVISIBLE);
recordingStatus = 2;
floatingActionButtonStartRecording.setImageDrawable(ResourcesCompat.getDrawable(getResources(), R.drawable.ic_play_green, null));
textViewInformation.setText(getString(R.string.tap_to_resume));
Toast.makeText(context, getString(R.string.paused), Toast.LENGTH_SHORT).show();
}
private void resumeRecording() {
if (Build.VERSION.SDK_INT >= 24) {
mediaRecorder.resume();
}
chronometerRecord.setBase(SystemClock.elapsedRealtime() - pauseOffset);
chronometerRecord.start();
lottieAnimationViewVoice.playAnimation();
lottieAnimationViewVoice.setVisibility(View.VISIBLE);
recordingStatus = 1;
floatingActionButtonStartRecording.setImageDrawable(ResourcesCompat.getDrawable(getResources(), R.drawable.ic_pause_orange, null));
textViewInformation.setText(getString(R.string.recording));
Toast.makeText(context, getString(R.string.resume), Toast.LENGTH_SHORT).show();
}
#SuppressLint("SetTextI18n")
private void finishRecording() {
chronometerRecord.setVisibility(View.INVISIBLE);
chronometerRecord.stop();
chronometerRecord.setBase(SystemClock.elapsedRealtime());
pauseOffset = 0;
mediaRecorder.stop();
mediaRecorder = null;
recordingStatus = 3;
floatingActionButtonStartRecording.setImageDrawable(ResourcesCompat.getDrawable(getResources(), R.drawable.ic_app, null));
Toast.makeText(context, getString(R.string.saved) + " " + fileName, Toast.LENGTH_LONG).show();
textViewInformation.setText(getString(R.string.tap_to_record));
lottieAnimationViewVoice.cancelAnimation();
lottieAnimationViewVoice.setFrame(0);
lottieAnimationViewVoice.setVisibility(View.INVISIBLE);
recordingStatus = 0;
}
#SuppressLint("SetTextI18n")
private void cancelRecording() {
chronometerRecord.setVisibility(View.INVISIBLE);
chronometerRecord.stop();
chronometerRecord.setBase(SystemClock.elapsedRealtime());
pauseOffset = 0;
try {
mediaRecorder.stop();
} catch (RuntimeException e) {
e.printStackTrace();
mediaRecorder = null;
mediaRecorder = new MediaRecorder();
} finally {
if (mediaRecorder != null) {
mediaRecorder = null;
}
}
File file = new File(outPutFilePath);
if (file.exists()) {
boolean deleted = file.delete();
if (deleted) {
Log.d("Voice Recorder", "Deleted file successfully!");
}
}
recordingStatus = 3;
floatingActionButtonStartRecording.setImageDrawable(ResourcesCompat.getDrawable(getResources(), R.drawable.ic_app, null));
Toast.makeText(context, getString(R.string.cancelled) + " " + fileName, Toast.LENGTH_LONG).show();
textViewInformation.setText(getString(R.string.tap_to_record));
lottieAnimationViewVoice.cancelAnimation();
lottieAnimationViewVoice.setFrame(0);
lottieAnimationViewVoice.setVisibility(View.INVISIBLE);
recordingStatus = 0;
}
private String getCurrentDateFormatted() {
return new SimpleDateFormat("dd-MM-yy|hh:mm:ss", Locale.getDefault()).format(new Date());
}
private void askPermissions() {
if (ContextCompat.checkSelfPermission(context,
Manifest.permission.WRITE_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED || ContextCompat.checkSelfPermission(context,
Manifest.permission.RECORD_AUDIO) != PackageManager.PERMISSION_GRANTED) {
assert getParentFragment() != null;
requestPermissions(permissions, Constants.RECORD_AUDIO_AND_WRITE_EXTERNAL_STORAGE_PERMISSION_REQUEST_CODE);
}
}
#Override
public void onRequestPermissionsResult(int requestCode, #NonNull final String[] permissions, #NonNull int[] grantResults) {
super.onRequestPermissionsResult(requestCode, permissions, grantResults);
if (ContextCompat.checkSelfPermission(context,
Manifest.permission.WRITE_EXTERNAL_STORAGE) == PackageManager.PERMISSION_GRANTED && ContextCompat.checkSelfPermission(context,
Manifest.permission.RECORD_AUDIO) == PackageManager.PERMISSION_GRANTED) {
Toast.makeText(context, getString(R.string.permission_granted), Toast.LENGTH_SHORT).show();
} else {
AlertDialog.Builder builder = new AlertDialog.Builder(context);
builder.setMessage(getString(R.string.no_read_permission))
.setPositiveButton(getString(R.string.ok), new DialogInterface.OnClickListener() {
#Override
public void onClick(DialogInterface dialogInterface, int i) {
dialogInterface.dismiss();
if (ContextCompat.checkSelfPermission(context,
Manifest.permission.WRITE_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED || ContextCompat.checkSelfPermission(context,
Manifest.permission.RECORD_AUDIO) != PackageManager.PERMISSION_GRANTED) {
requestPermissions(permissions, Constants.RECORD_AUDIO_AND_WRITE_EXTERNAL_STORAGE_PERMISSION_REQUEST_CODE);
}
}
}).setNegativeButton(getString(R.string.go_to_settings), new DialogInterface.OnClickListener() {
#Override
public void onClick(DialogInterface dialog, int which) {
Intent intent = new Intent();
intent.setAction(Settings.ACTION_APPLICATION_DETAILS_SETTINGS);
Uri uri = Uri.fromParts("package", "com.venomapps.voicerecorder", null);
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK);
intent.setData(uri);
context.startActivity(intent);
requireActivity().finish();
}
});
builder.create();
builder.show();
}
}
}
PlaylistFragment.java:
import android.content.Context;
import android.media.AudioAttributes;
import android.media.AudioManager;
import android.media.MediaPlayer;
import android.net.Uri;
import android.os.Build;
import android.os.Bundle;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.constraintlayout.widget.ConstraintLayout;
import androidx.fragment.app.Fragment;
import androidx.recyclerview.widget.DividerItemDecoration;
import androidx.recyclerview.widget.LinearLayoutManager;
import androidx.recyclerview.widget.RecyclerView;
import android.os.Environment;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import com.google.android.material.bottomsheet.BottomSheetBehavior;
import com.venomapps.voicerecorder.Adapters.PlaylistAdapter;
import com.venomapps.voicerecorder.R;
import java.io.File;
import java.io.IOException;
public class PlaylistFragment extends Fragment implements PlaylistAdapter.onItemListClick {
private BottomSheetBehavior bottomSheetBehavior;
private RecyclerView recyclerViewPlaylist;
private File[] files;
private PlaylistAdapter playlistAdapter;
private MediaPlayer mediaPlayer = null;
private boolean isPlaying = false;
private File fileToPlay;
public PlaylistFragment() {
}
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
getFiles();
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.fragment_playlist_item_list, container, false);
// Set the adapter
if (view instanceof RecyclerView) {
Context context = view.getContext();
RecyclerView recyclerView = (RecyclerView) view;
LinearLayoutManager linearLayoutManager = new LinearLayoutManager(context);
recyclerView.setLayoutManager(linearLayoutManager);
}
return view;
}
#Override
public void onViewCreated(#NonNull View view, #Nullable Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
bindUI(view);
setListeners();
setAdapter();
}
private void bindUI(View view) {
ConstraintLayout constraintLayoutMediaPlayer = view.findViewById(R.id.constraintLayoutMediaPlayer);
bottomSheetBehavior = BottomSheetBehavior.from(constraintLayoutMediaPlayer);
recyclerViewPlaylist = view.findViewById(R.id.recyclerViewPlaylist);
}
private void setListeners() {
bottomSheetBehavior.addBottomSheetCallback(new BottomSheetBehavior.BottomSheetCallback() {
#Override
public void onStateChanged(#NonNull View bottomSheet, int newState) {
if (newState == BottomSheetBehavior.STATE_HIDDEN) {
bottomSheetBehavior.setState(BottomSheetBehavior.STATE_COLLAPSED);
}
}
#Override
public void onSlide(#NonNull View bottomSheet, float slideOffset) {
}
});
}
private void getFiles() {
String path = Environment.getExternalStorageDirectory().toString() + File.separator + "Voice Recorder";
File directory = new File(path);
files = directory.listFiles();
}
private void setAdapter() {
playlistAdapter = new PlaylistAdapter(files, this);
recyclerViewPlaylist.setHasFixedSize(true);
recyclerViewPlaylist.setLayoutManager(new LinearLayoutManager(getContext()));
recyclerViewPlaylist.setAdapter(playlistAdapter);
}
#Override
public void onClickListener(File file, int position) throws IOException {
if(isPlaying){
stopAudio();
playAudio(fileToPlay);
}else{
fileToPlay = file;
playAudio(fileToPlay);
}
}
private void playAudio(File fileToPlay) {
mediaPlayer = new MediaPlayer();
try {
mediaPlayer.setDataSource(fileToPlay.getAbsolutePath());
mediaPlayer.prepare();
mediaPlayer.start();
}catch (Exception e){
e.printStackTrace();
}
isPlaying = true;
}
private void stopAudio(){
isPlaying = false;
}
}
-PlaylistAdapter.java:
import android.content.Context;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ImageButton;
import android.widget.TextView;
import androidx.annotation.NonNull;
import androidx.recyclerview.widget.RecyclerView;
import com.google.android.material.floatingactionbutton.FloatingActionButton;
import com.venomapps.voicerecorder.Utils.TimeAgo;
import com.venomapps.voicerecorder.R;
import java.io.File;
import java.io.IOException;
public class PlaylistAdapter extends RecyclerView.Adapter<PlaylistAdapter.PlaylistViewHolder> {
private static File[] files;
private TimeAgo timeAgo;
private Context context;
private static onItemListClick onItemListClick;
public PlaylistAdapter(File[] files, onItemListClick onItemListClick) {
PlaylistAdapter.files = files;
PlaylistAdapter.onItemListClick = onItemListClick;
}
#NonNull
#Override
public PlaylistViewHolder onCreateViewHolder(#NonNull ViewGroup parent, int viewType) {
View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.fragment_playlist_item, parent, false);
context = parent.getContext();
timeAgo = new TimeAgo();
return new PlaylistViewHolder(view);
}
#Override
public void onBindViewHolder(#NonNull PlaylistViewHolder holder, int position) {
holder.textViewPlaylistFileName.setText(files[position].getName());
holder.textViewPlaylistStats.setText(timeAgo.getTimeAgo(files[position].lastModified(), context));
if(position == getItemCount() - 1){
holder.playlistSeparator.setVisibility(View.INVISIBLE);
}
}
#Override
public int getItemCount() {
return files.length;
}
public static class PlaylistViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener {
private final TextView textViewPlaylistFileName;
private final TextView textViewPlaylistStats;
private final View playlistSeparator;
private final FloatingActionButton floatingActionButtonPlaylistPlay;
private final ImageButton imageButtonPlaylistItem;
public PlaylistViewHolder(#NonNull View itemView) {
super(itemView);
textViewPlaylistFileName = itemView.findViewById(R.id.textViewPlaylistFileName);
textViewPlaylistStats = itemView.findViewById(R.id.textViewPlaylistStats);
playlistSeparator = itemView.findViewById(R.id.playlistSeparator);
floatingActionButtonPlaylistPlay = itemView.findViewById(R.id.floatingActionButtonPlaylistPlay);
imageButtonPlaylistItem = itemView.findViewById(R.id.imageButtonPlaylistItem);
floatingActionButtonPlaylistPlay.setOnClickListener(this);
}
#Override
public void onClick(View v) {
try {
onItemListClick.onClickListener(files[getAdapterPosition()], getAdapterPosition());
} catch (IOException e) {
e.printStackTrace();
}
}
}
public interface onItemListClick{
void onClickListener(File file, int position) throws IOException;
}
}
Firstly, I suggest you to post full error log, and only the code which create the problem (and not your entire project ...)
There is 3 possibilities which can create your problem :
File problem (path or file not exist).
Wrong format (or not supported one).
Not permission. Do file.setReadable(true); to fix this
More informations here : https://stackoverflow.com/a/11977292/10952503
I am working on GoogleFit Api for daily steps count. I am getting the correct result. But when i sign out the application (In this case, app exit the Googlefit fragment's parent activity)
After sign in again, i access the same fragment again, but Googlefit returns the stepsCount as zero and getting times out at result.await.
Here is my Code.
GoogleFitFragment.java
package com.example.mudasirrao.mvvm.Fragments.GoogleFitFragments;
import android.databinding.DataBindingUtil;
import android.os.Bundle;
import android.support.v4.app.Fragment;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import com.example.mudasirrao.mvvm.R;
import com.example.mudasirrao.mvvm.ViewModel.GoogleFitViewModels.GoogleFitViewModel;
import com.example.mudasirrao.mvvm.databinding.FragmentGoogleFitBinding;
import com.google.android.gms.common.api.PendingResult;
import com.google.android.gms.common.api.Status;
import com.google.android.gms.fitness.ConfigApi;
import com.google.android.gms.fitness.Fitness;
import com.google.android.gms.fitness.result.DataTypeResult;
public class GoogleFitFragment extends Fragment {
GoogleFitViewModel googleFitViewModel;
public GoogleFitFragment() {
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
FragmentGoogleFitBinding fragmentGoogleFitBinding = DataBindingUtil.inflate(inflater, R.layout.fragment_google_fit, container, false);
View view = fragmentGoogleFitBinding.getRoot();
googleFitViewModel = new GoogleFitViewModel(getActivity(), fragmentGoogleFitBinding);
fragmentGoogleFitBinding.setGoogleFitFragmentViewModel(googleFitViewModel);
return view;
}
}
GoogleFitViewModel.java
package com.example.mudasirrao.mvvm.ViewModel.GoogleFitViewModels;
import android.content.Context;
import android.content.SharedPreferences;
import android.databinding.ObservableField;
import android.os.AsyncTask;
import android.util.Log;
import android.view.View;
import android.widget.Toast;
import com.example.mudasirrao.mvvm.CallBacks.CallBackGoogleFitClient;
import com.example.mudasirrao.mvvm.DataManager.GoogleFitDataManager;
import com.example.mudasirrao.mvvm.databinding.FragmentGoogleFitBinding;
import com.google.android.gms.common.api.GoogleApiClient;
import com.google.android.gms.common.api.PendingResult;
import com.google.android.gms.fitness.ConfigApi;
import com.google.android.gms.fitness.Fitness;
import com.google.android.gms.fitness.data.DataSet;
import com.google.android.gms.fitness.data.DataType;
import com.google.android.gms.fitness.data.Field;
import com.google.android.gms.fitness.result.DailyTotalResult;
import java.util.concurrent.TimeUnit;
import static android.content.Context.MODE_PRIVATE;
public class GoogleFitViewModel {
private Context context;
private FragmentGoogleFitBinding fragmentGoogleFitBinding;
public final ObservableField<String> steps = new ObservableField<>();
public GoogleApiClient localGoogleApiClient;
String dailySteps;
public GoogleFitViewModel(Context context, final FragmentGoogleFitBinding fragmentGoogleFitBinding) {
this.context = context;
this.fragmentGoogleFitBinding = fragmentGoogleFitBinding;
SharedPreferences prefs = context.getSharedPreferences("dailySteps", MODE_PRIVATE);
dailySteps = prefs.getString("daily_steps", null);
if (dailySteps != null) {
steps.set(dailySteps);
GoogleFitDataManager.singletonObject(context).buildFitnessClient(new CallBackGoogleFitClient() {
#Override
public void onResponse(GoogleApiClient googleApiClient) {
localGoogleApiClient = googleApiClient;
if (googleApiClient != null) {
new VerifyDataTask().execute(localGoogleApiClient);
fragmentGoogleFitBinding.setGoalLayout.animate().alpha(0.2f).setDuration(1000);
enableDisableLayout(false);
fragmentGoogleFitBinding.previewImage.setVisibility(View.GONE);
fragmentGoogleFitBinding.saveButton.setText("Edit");
fragmentGoogleFitBinding.saveButton.setTag("disabled_edit");
fragmentGoogleFitBinding.goalProgressLayout.setVisibility(View.VISIBLE);
fragmentGoogleFitBinding.goalText.setText("Take " + steps.get() + " steps a day");
}
}
});
} else {
steps.set("0000");
fragmentGoogleFitBinding.setGoalLayout.animate().alpha(1.0f).setDuration(3000);
}
}
public void onClickStepsButton1(View view) {
steps.set("2000");
}
public void onClickStepsButton2(View view) {
steps.set("8000");
}
public void onClickStepsButton3(View view) {
steps.set("10000");
}
public void onClickStepsButton4(View view) {
steps.set("13000");
}
public void onClickSave(View view) {
if ((Integer.valueOf(steps.get()) > 0)) {
if (fragmentGoogleFitBinding.saveButton.getTag() == null) {
GoogleFitDataManager.singletonObject(context).buildFitnessClient(new CallBackGoogleFitClient() {
#Override
public void onResponse(GoogleApiClient googleApiClient) {
localGoogleApiClient = googleApiClient;
if (googleApiClient != null) {
new VerifyDataTask().execute(localGoogleApiClient);
fragmentGoogleFitBinding.setGoalLayout.animate().alpha(0.2f).setDuration(1000);
enableDisableLayout(false);
fragmentGoogleFitBinding.previewImage.setVisibility(View.GONE);
fragmentGoogleFitBinding.saveButton.setText("Edit");
fragmentGoogleFitBinding.saveButton.setTag("disabled_edit");
fragmentGoogleFitBinding.goalProgressLayout.setVisibility(View.VISIBLE);
}
}
});
} else {
if (fragmentGoogleFitBinding.saveButton.getTag().equals("disabled_edit")) {
fragmentGoogleFitBinding.setGoalLayout.animate().alpha(1.0f).setDuration(1000);
enableDisableLayout(true);
fragmentGoogleFitBinding.saveButton.setTag("enabled_edit");
fragmentGoogleFitBinding.saveButton.setText("Save");
} else if (fragmentGoogleFitBinding.saveButton.getTag().equals("enabled_edit")) {
new VerifyDataTask().execute(localGoogleApiClient);
fragmentGoogleFitBinding.setGoalLayout.animate().alpha(0.2f).setDuration(1000);
enableDisableLayout(false);
fragmentGoogleFitBinding.saveButton.setText("Edit");
fragmentGoogleFitBinding.saveButton.setTag("disabled_edit");
}
}
fragmentGoogleFitBinding.goalText.setText("Take " + steps.get() + " steps a day");
} else
Toast.makeText(context, "Please Select Steps", Toast.LENGTH_SHORT).show();
}
protected void renderStepsProgress(int stepsTaken) {
saveDailyStepsInSharedPref(steps.get());
int percentage = (int) (((double) stepsTaken / (double) Integer.valueOf(steps.get())) * 100);
if (percentage > 100) {
percentage = 100;
}
fragmentGoogleFitBinding.waveLoadingView.setCenterTitle(String.valueOf(percentage) + " %");
fragmentGoogleFitBinding.waveLoadingView.setProgressValue(percentage);
fragmentGoogleFitBinding.stepsTakenText.setText("You have taken " + String.valueOf(stepsTaken) + " steps today");
}
private void enableDisableLayout(Boolean visibility) {
View child;
for (int i = 0; i < fragmentGoogleFitBinding.stepButtonLayout1.getChildCount(); i++) {
child = fragmentGoogleFitBinding.stepButtonLayout1.getChildAt(i);
child.setEnabled(visibility);
}
for (int i = 0; i < fragmentGoogleFitBinding.stepButtonLayout2.getChildCount(); i++) {
child = fragmentGoogleFitBinding.stepButtonLayout2.getChildAt(i);
child.setEnabled(visibility);
}
}
private void saveDailyStepsInSharedPref(String dailySteps) {
SharedPreferences.Editor editor = context.getSharedPreferences("dailySteps", MODE_PRIVATE).edit();
editor.putString("daily_steps", dailySteps);
editor.apply();
}
private class VerifyDataTask extends AsyncTask<GoogleApiClient, Void, Integer> {
#Override
protected Integer doInBackground(GoogleApiClient... params) {
int total = 0;
PendingResult<DailyTotalResult> result = Fitness.HistoryApi.readDailyTotal(params[0], DataType.TYPE_STEP_COUNT_DELTA);
DailyTotalResult totalResult = result.await(30, TimeUnit.SECONDS);
if (totalResult.getStatus().isSuccess()) {
DataSet totalSet = totalResult.getTotal();
total = totalSet.isEmpty()
? 0
: totalSet.getDataPoints().get(0).getValue(Field.FIELD_STEPS).asInt();
} else {
Log.d("steps_count_error", "There was a problem getting the step count!!");
}
return total;
}
protected void onPostExecute(Integer result) {
renderStepsProgress(result);
}
}
}
GoogleFitDataManager.java
package com.example.mudasirrao.mvvm.DataManager;
import android.content.Context;
import android.os.Bundle;
import android.support.annotation.Nullable;
import android.support.v4.app.FragmentActivity;
import android.util.Log;
import android.widget.Toast;
import com.example.mudasirrao.mvvm.CallBacks.CallBackGoogleFitClient;
import com.google.android.gms.common.ConnectionResult;
import com.google.android.gms.common.api.GoogleApiClient;
import com.google.android.gms.common.api.ResultCallback;
import com.google.android.gms.common.api.Status;
import com.google.android.gms.fitness.Fitness;
import com.google.android.gms.fitness.FitnessStatusCodes;
import com.google.android.gms.fitness.data.DataType;
import static com.bumptech.glide.gifdecoder.GifHeaderParser.TAG;
public class GoogleFitDataManager {
private static GoogleFitDataManager googleFitDataManager;
private GoogleApiClient googleApiClient = null;
private Context context;
public GoogleFitDataManager(Context context) {
this.context = context;
}
public static GoogleFitDataManager singletonObject(Context context) {
if (googleFitDataManager == null) {
googleFitDataManager = new GoogleFitDataManager(context);
}
return googleFitDataManager;
}
public void buildFitnessClient(final CallBackGoogleFitClient callBackGoogleFitClient) {
if (googleApiClient == null) {
googleApiClient = new GoogleApiClient.Builder(context)
.addApi(Fitness.HISTORY_API)
.addApi(Fitness.RECORDING_API)
.addApi(Fitness.CONFIG_API)
.addConnectionCallbacks(new GoogleApiClient.ConnectionCallbacks() {
#Override
public void onConnected(#Nullable Bundle bundle) {
subscribeGoogleFit(googleApiClient);
callBackGoogleFitClient.onResponse(googleApiClient);
}
#Override
public void onConnectionSuspended(int i) {
if (i == GoogleApiClient.ConnectionCallbacks.CAUSE_NETWORK_LOST) {
Toast.makeText(context, "Connection lost. Cause: Network Lost.", Toast.LENGTH_SHORT).show();
} else if (i == GoogleApiClient.ConnectionCallbacks.CAUSE_SERVICE_DISCONNECTED) {
Toast.makeText(context, "Connection lost. Reason: Service Disconnected", Toast.LENGTH_SHORT).show();
}
}
}
)
.enableAutoManage((FragmentActivity) context, 0, new GoogleApiClient.OnConnectionFailedListener() {
#Override
public void onConnectionFailed(ConnectionResult result) {
Log.i("TAG", "Google Play services connection failed. Cause: " + result.toString());
Toast.makeText(context, "Exception while connecting to Google Play services: " + result.getErrorMessage(), Toast.LENGTH_SHORT).show();
}
})
.build();
} else {
subscribeGoogleFit(googleApiClient);
callBackGoogleFitClient.onResponse(googleApiClient);
}
}
public void subscribeGoogleFit(GoogleApiClient client) {
Fitness.RecordingApi.subscribe(client, DataType.TYPE_STEP_COUNT_DELTA)
.setResultCallback(new ResultCallback<Status>() {
#Override
public void onResult(Status status) {
if (status.isSuccess()) {
if (status.getStatusCode() == FitnessStatusCodes.SUCCESS_ALREADY_SUBSCRIBED) {
Log.i(TAG, "Existing subscription for activity detected.");
} else {
Log.i(TAG, "Successfully subscribed!");
}
} else {
Log.i(TAG, "There was a problem subscribing.");
}
}
});
}
}
What I was doing that I was creating the static object of the class in which I was making the googlefit client. In this case, when I exit the Activity, the object was not destroying and googlefit client was getting disconnected due to the enableAutoManage in onDestroy of the fragment. And as per my checks, I was not connecting to the googleFit client again.
I removed the object as static and now I stick the API client class object with the life cycle of the activity in which my fragment resides. Also I removed enableAutoManage and now connecting and disconnecting the API client by myself.
I am creating an android camera app using opencv. First I make it like when I click the start button, it start taking pictures and in every second takes a picture and store it in storage. It works perfectly for me.
Then I tried to make it some tricky by forcing it to take 5 pictures in a second it works well.
But actually I faced problem when I make it to 20 pictures in 1 second. It did not work. The app hangs as soon as I click on the start button. I don't know why. But I think the problem is in threading.
Can someone help me how i will do it.
I have two java files in my project and here is the code.
package org.opencv.samples.tutorial3;
import java.io.FileOutputStream;
import java.util.List;
import org.opencv.android.JavaCameraView;
import android.content.Context;
import android.hardware.Camera;
import android.hardware.Camera.PictureCallback;
import android.hardware.Camera.Size;
import android.util.AttributeSet;
import android.util.Log;
public class Tutorial3View extends JavaCameraView implements PictureCallback {
private static final String TAG = "Sample::Tutorial3View";
private String mPictureFileName;
public Tutorial3View(Context context, AttributeSet attrs) {
super(context, attrs);
}
public List<String> getEffectList() {
return mCamera.getParameters().getSupportedColorEffects();
}
public boolean isEffectSupported() {
return (mCamera.getParameters().getColorEffect() != null);
}
public String getEffect() {
return mCamera.getParameters().getColorEffect();
}
public void setEffect(String effect) {
Camera.Parameters params = mCamera.getParameters();
params.setColorEffect(effect);
mCamera.setParameters(params);
}
public List<Size> getResolutionList() {
return mCamera.getParameters().getSupportedPreviewSizes();
}
public void setResolution(Size resolution) {
disconnectCamera();
mMaxHeight = resolution.height;
mMaxWidth = resolution.width;
connectCamera(getWidth(), getHeight());
}
public Size getResolution() {
return mCamera.getParameters().getPreviewSize();
}
public void takePicture(final String fileName) {
Log.i(TAG, "Taking picture");
this.mPictureFileName = fileName;
// Postview and jpeg are sent in the same buffers if the queue is not empty when performing a capture.
// Clear up buffers to avoid mCamera.takePicture to be stuck because of a memory issue
mCamera.setPreviewCallback(null);
// PictureCallback is implemented by the current class
mCamera.takePicture(null, null, this);
}
#Override
public void onPictureTaken(byte[] data, Camera camera) {
Log.i(TAG, "Saving a bitmap to file");
// The camera preview was automatically stopped. Start it again.
mCamera.startPreview();
mCamera.setPreviewCallback(this);
// Write the image in a file (in jpeg format)
try {
FileOutputStream fos = new FileOutputStream(mPictureFileName);
fos.write(data);
fos.close();
} catch (java.io.IOException e) {
Log.e("PictureDemo", "Exception in photoCallback", e);
}
}
}
And the second one is:
package org.opencv.samples.tutorial3;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.List;
import java.util.ListIterator;
import org.opencv.android.BaseLoaderCallback;
import org.opencv.android.CameraBridgeViewBase.CvCameraViewFrame;
import org.opencv.android.LoaderCallbackInterface;
import org.opencv.android.OpenCVLoader;
import org.opencv.core.Mat;
import org.opencv.android.CameraBridgeViewBase.CvCameraViewListener2;
import android.annotation.SuppressLint;
import android.app.Activity;
import android.hardware.Camera.Size;
import android.os.Bundle;
import android.os.Environment;
import android.util.Log;
import android.view.Menu;
import android.view.MenuItem;
import android.view.MotionEvent;
import android.view.SubMenu;
import android.view.SurfaceView;
import android.view.View;
import android.view.View.OnTouchListener;
import android.view.WindowManager;
import android.widget.Button;
import android.widget.Toast;
public class Tutorial3Activity extends Activity implements CvCameraViewListener2 {
private static final String TAG = "OCVSample::Activity";
private Tutorial3View mOpenCvCameraView;
private List<Size> mResolutionList;
private MenuItem[] mEffectMenuItems;
private SubMenu mColorEffectsMenu;
private MenuItem[] mResolutionMenuItems;
private SubMenu mResolutionMenu;
Thread thread;
Button start,stop;
boolean loop=false;
private BaseLoaderCallback mLoaderCallback = new BaseLoaderCallback(this) {
#Override
public void onManagerConnected(int status) {
switch (status) {
case LoaderCallbackInterface.SUCCESS:
{
Log.i(TAG, "OpenCV loaded successfully");
mOpenCvCameraView.enableView();
} break;
default:
{
super.onManagerConnected(status);
} break;
}
}
};
public Tutorial3Activity() {
Log.i(TAG, "Instantiated new " + this.getClass());
}
/** Called when the activity is first created. */
#Override
public void onCreate(Bundle savedInstanceState) {
Log.i(TAG, "called onCreate");
super.onCreate(savedInstanceState);
getWindow().addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
setContentView(R.layout.tutorial3_surface_view);
start=(Button)findViewById(R.id.button2) ;
start.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
loop=true;
thread = new Thread(new task());
thread.start();
}
});
stop=(Button) findViewById(R.id.button);
stop.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
loop=false;
}
});
mOpenCvCameraView = (Tutorial3View) findViewById(R.id.tutorial3_activity_java_surface_view);
mOpenCvCameraView.setVisibility(SurfaceView.VISIBLE);
mOpenCvCameraView.setCvCameraViewListener(this);
}
#Override
public void onPause()
{
super.onPause();
if (mOpenCvCameraView != null)
mOpenCvCameraView.disableView();
}
#Override
public void onResume()
{
super.onResume();
if (!OpenCVLoader.initDebug()) {
Log.d(TAG, "Internal OpenCV library not found. Using OpenCV Manager for initialization");
OpenCVLoader.initAsync(OpenCVLoader.OPENCV_VERSION_3_0_0, this, mLoaderCallback);
} else {
Log.d(TAG, "OpenCV library found inside package. Using it!");
mLoaderCallback.onManagerConnected(LoaderCallbackInterface.SUCCESS);
}
}
public void onDestroy() {
super.onDestroy();
if (mOpenCvCameraView != null)
mOpenCvCameraView.disableView();
}
public void onCameraViewStarted(int width, int height) {
}
public void onCameraViewStopped() {
}
public Mat onCameraFrame(CvCameraViewFrame inputFrame) {
return inputFrame.rgba();
}
#Override
public boolean onCreateOptionsMenu(Menu menu) {
List<String> effects = mOpenCvCameraView.getEffectList();
if (effects == null) {
Log.e(TAG, "Color effects are not supported by device!");
return true;
}
mColorEffectsMenu = menu.addSubMenu("Color Effect");
mEffectMenuItems = new MenuItem[effects.size()];
int idx = 0;
ListIterator<String> effectItr = effects.listIterator();
while(effectItr.hasNext()) {
String element = effectItr.next();
mEffectMenuItems[idx] = mColorEffectsMenu.add(1, idx, Menu.NONE, element);
idx++;
}
mResolutionMenu = menu.addSubMenu("Resolution");
mResolutionList = mOpenCvCameraView.getResolutionList();
mResolutionMenuItems = new MenuItem[mResolutionList.size()];
ListIterator<Size> resolutionItr = mResolutionList.listIterator();
idx = 0;
while(resolutionItr.hasNext()) {
Size element = resolutionItr.next();
mResolutionMenuItems[idx] = mResolutionMenu.add(2, idx, Menu.NONE,
Integer.valueOf(element.width).toString() + "x" + Integer.valueOf(element.height).toString());
idx++;
}
return true;
}
public boolean onOptionsItemSelected(MenuItem item) {
Log.i(TAG, "called onOptionsItemSelected; selected item: " + item);
if (item.getGroupId() == 1)
{
mOpenCvCameraView.setEffect((String) item.getTitle());
Toast.makeText(this, mOpenCvCameraView.getEffect(), Toast.LENGTH_SHORT).show();
}
else if (item.getGroupId() == 2)
{
int id = item.getItemId();
Size resolution = mResolutionList.get(id);
mOpenCvCameraView.setResolution(resolution);
resolution = mOpenCvCameraView.getResolution();
String caption = Integer.valueOf(resolution.width).toString() + "x" + Integer.valueOf(resolution.height).toString();
Toast.makeText(this, caption, Toast.LENGTH_SHORT).show();
}
return true;
}
class task implements Runnable {
public void run() {
while (loop) {
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd_HH-mm-ss");
String currentDateandTime = sdf.format(new Date());
final String fileName = Environment.getExternalStorageDirectory().getPath() +
"/sample_picture_" + currentDateandTime + ".jpg";
mOpenCvCameraView.takePicture(fileName);
runOnUiThread(new Runnable() {
#Override
public void run() {
Toast.makeText(Tutorial3Activity.this, fileName + " saved", Toast.LENGTH_SHORT).show();
}
});
try {
thread.sleep(200);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
}
Note: The above code works well for taking 5 pictures in 1 second. But when I change thread.sleep(200) to thread.sleep(50) for taking 20 pictures in 1 second it hangs.
I have been stuck for hours . I have integrated admob ads on my application and I add it when user write something in edit text but it takes time to load ads some times it comes while some times skip .So user type the text and move to the next activity and my ads not load in time .
Can you give me some solution how to solve this issue !
thanks in advance
PassValues.java
package com.logixcess.wordguessing;
import android.content.Context;
import android.media.MediaPlayer;
import android.net.ConnectivityManager;
import android.net.NetworkInfo;
import android.widget.Button;
import com.google.android.gms.ads.AdRequest;
import com.google.android.gms.ads.InterstitialAd;
import java.security.PrivateKey;
import java.util.ArrayList;
import java.util.LinkedList;
import java.util.List;
/**
* Created by ert on 17/04/2016.
*/
public class Passvalues {
public static String[] words , toCompare;
public static int score = 0,staticScore = 0,prevScore = 0,correctCount = 0;
public static String selectedWord;
public static List<String> repeated = null;
public static List<Button> buttonList = new ArrayList<Button>();
public static int[] hiscore = new int[5];
public static String[] hiscorename = new String[5];
public static MediaPlayer mediaPlayer;//sounds
public static MediaPlayer tones;//music
static float volLeft = 70,volRight = 70;
public static boolean sound = true,music=true;
public static boolean adCheck = false;
public static InterstitialAd interstitial;
public Passvalues()
{
words=null ; toCompare=null;
score = 0;prevScore = 0;correctCount = 0;
selectedWord="";
repeated = null;
buttonList = new ArrayList<Button>();
hiscore = new int[5];
hiscorename = new String[5];
adCheck = false;
}
public static void playMusic(Context context,int id)
{
if(Passvalues.music)
{
if(tones != null)
{
if (!tones.isPlaying()) {
tones = MediaPlayer.create(context, id);
tones.setLooping(true);
tones.start();
}
}
else {
tones = MediaPlayer.create(context, id);
tones.setLooping(true);
tones.start();
}
}
}
public static void stopMusic(){
/* if(!Passvalues.sound) {
if(tones != null)
{
if(tones.isPlaying()) {
stopPlaying(tones);
}
}
else
{
tones = null;
stopPlaying(tones);
}
}*/
if((!Passvalues.music)&&(!Passvalues.sound))
{
if(tones!=null)
{
stopPlaying(tones);
tones=null;
}
else
{
//pehlay se hi band hai music
}
if(mediaPlayer!=null)
{
stopPlaying(mediaPlayer);
mediaPlayer=null;
}
else
{
//peh;ay se hi sound band hai
}
}
}
public static void playSound(Context context,int id){
if(Passvalues.sound)
{
mediaPlayer = MediaPlayer.create(context, id);
mediaPlayer.start();
}
else if(mediaPlayer != null)
{
if(mediaPlayer.isPlaying()) {
stopPlaying(mediaPlayer);
}
if(mediaPlayer != null)
stopPlaying(mediaPlayer);
}
}
public static void stopPlaying(MediaPlayer mp)
{
if(mp!=null)
{
mp.stop();
mp.release();
mp=null;
}
}
public static boolean showad(Context context)
{
if(isNetworkAvailable(context))
{
if(interstitial == null)
interstitial = new InterstitialAd(context);
interstitial.setAdUnitId("ca-app-pub-7328520387956873/2174089947");
AdRequest adRequest = new AdRequest.Builder()
.addTestDevice(AdRequest.DEVICE_ID_EMULATOR)
.build();
interstitial.loadAd(adRequest);
return true;
}
return false;
}
private static boolean isNetworkAvailable(Context context) {
ConnectivityManager connectivityManager
= (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE);
NetworkInfo activeNetworkInfo = connectivityManager.getActiveNetworkInfo();
return activeNetworkInfo != null && activeNetworkInfo.isConnected();
}
}
EnterHighScore.java
this is the activity for ads
package com.logixcess.wordguessing;
import com.google.android.gms.ads.AdListener;
import com.google.android.gms.ads.AdRequest;
import com.google.android.gms.ads.InterstitialAd;
import com.logixcess.wordguessing.R;
import android.app.Activity;
import android.app.DialogFragment;
import android.content.Context;
import android.content.Intent;
import android.content.SharedPreferences;
import android.content.pm.ActivityInfo;
import android.graphics.drawable.Drawable;
import android.net.ConnectivityManager;
import android.net.NetworkInfo;
import android.os.Bundle;
import android.os.Handler;
import android.os.PowerManager.WakeLock;
import android.preference.PreferenceManager;
import android.text.Editable;
import android.text.TextWatcher;
import android.util.Log;
import android.view.KeyEvent;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.view.Window;
import android.view.WindowManager;
import android.view.View.OnClickListener;
import android.widget.AbsListView;
import android.widget.Button;
import android.widget.EditText;
import com.google.android.gms.ads.AdListener;
public class EnterHiscore extends Activity {
int score;
EditText namebox;
#Override
public boolean onKeyDown(int keyCode, KeyEvent event)
{
onBackPressed();
super.onKeyDown(keyCode, event);
return true;
}
#Override
public void onBackPressed() {
Intent setIntent = new Intent(EnterHiscore.this,MainScreen.class);
//setIntent.addCategory(Intent.CATEGORY_HOME);
//setIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
startActivity(setIntent);
}
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
//set screen full screen and no title
requestWindowFeature(Window.FEATURE_NO_TITLE);
getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN, WindowManager.LayoutParams.FLAG_FULLSCREEN);
//this.setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE);
setContentView(R.layout.enterhiscore);
Passvalues.showad(EnterHiscore.this);
View backgroundImage = findViewById(R.id.bak);
Drawable background = backgroundImage.getBackground();
background.setAlpha(90);
//get score
score = Passvalues.staticScore; //getIntent().getIntExtra("score", 0);
//declare views
namebox = (EditText) findViewById(R.id.namebox);
Button save = (Button) findViewById(R.id.save);
namebox.addTextChangedListener(new TextWatcher() {
#Override
public void beforeTextChanged(CharSequence s, int start, int count, int after) {
}
#Override
public void onTextChanged(CharSequence s, int start, int before, int count) {
if (!Passvalues.adCheck) {
Passvalues.interstitial.setAdListener(new AdListener() {
#Override
public void onAdLoaded() {
super.onAdLoaded();
if (Passvalues.interstitial.isLoaded()) {
Passvalues.interstitial.show();
}
}
#Override
public void onAdClosed() {
//finish();
Passvalues.interstitial = null;
}
});
Passvalues.adCheck = true;
}
}
#Override
public void afterTextChanged(Editable s) {
}
});
save.setOnClickListener(new OnClickListener() {
public void onClick(View v) {
process_highscore(score, namebox.getText().toString());
}
});
}
public void loadscore() {
// load preferences
SharedPreferences hiscores = PreferenceManager.getDefaultSharedPreferences(getApplicationContext());
for (int i = 0; i < 5; i++) {
Passvalues.hiscore[i] = hiscores.getInt("score" + i, 0);
Passvalues.hiscorename[i] = hiscores.getString("name" + i, "---");
}
}
public void savescore() {
//load preferences
SharedPreferences hiscores = PreferenceManager.getDefaultSharedPreferences(getApplicationContext());
SharedPreferences.Editor hiscores_editor = hiscores.edit();
for (int i = 0; i < 5; i++) {
hiscores_editor.putInt("score" + i, Passvalues.hiscore[i]);
hiscores_editor.putString("name" + i, Passvalues.hiscorename[i]);
}
hiscores_editor.commit();
loadscore();
}
public void process_highscore(int score, String name){
System.out.println("ll"+score + name);
loadscore();
boolean ready = false;
if (score > Passvalues.hiscore[0]) {
Passvalues.hiscore[4] = Passvalues.hiscore[3];
Passvalues.hiscorename[4] = Passvalues.hiscorename[3];
Passvalues.hiscore[3] = Passvalues.hiscore[2];
Passvalues.hiscorename[3] = Passvalues.hiscorename[2];
Passvalues.hiscore[2] = Passvalues.hiscore[1];
Passvalues.hiscorename[2] = Passvalues.hiscorename[1];
Passvalues.hiscore[1] = Passvalues.hiscore[0];
Passvalues.hiscorename[1] = Passvalues.hiscorename[0];
Passvalues.hiscore[0] = score;
Passvalues.hiscorename[0] = name;
ready = true;
}
if (score > Passvalues.hiscore[1] && score <= Passvalues.hiscore[0] && !ready) {
Passvalues.hiscore[4] = Passvalues.hiscore[3];
Passvalues.hiscorename[4] = Passvalues.hiscorename[3];
Passvalues.hiscore[3] = Passvalues.hiscore[2];
Passvalues.hiscorename[3] = Passvalues.hiscorename[2];
Passvalues.hiscore[2] = Passvalues.hiscore[1];
Passvalues.hiscorename[2] = Passvalues.hiscorename[1];
Passvalues.hiscore[1] = score;
Passvalues.hiscorename[1] = name;
ready = true;
}
if (score > Passvalues.hiscore[2] && score <= Passvalues.hiscore[1] && !ready) {
Passvalues.hiscore[4] = Passvalues.hiscore[3];
Passvalues.hiscorename[4] = Passvalues.hiscorename[3];
Passvalues.hiscore[3] = Passvalues.hiscore[2];
Passvalues.hiscorename[3] = Passvalues.hiscorename[2];
Passvalues.hiscore[2] = score;
Passvalues.hiscorename[2] = name;
ready = true;
}
if (score > Passvalues.hiscore[4] && score <= Passvalues.hiscore[3] && !ready) {
Passvalues.hiscore[4] = score;
Passvalues.hiscorename[4] = name;
}
savescore();
Intent i=new Intent(EnterHiscore.this,Highscore.class);
startActivity(i);
//go back to hiscores
finish();
}
}
Instead of displaying the ad in the #onAdLoaded() callback, display it in the natural break point in #onTextChanged():
#Override
public void onTextChanged(CharSequence s, int start, int before, int count) {
if (!Passvalues.adCheck) {
if (Passvalues.interstitial.isLoaded()) {
Passvalues.interstitial.show();
}
Passvalues.interstitial.setAdListener(new AdListener() {
#Override
public void onAdLoaded() {
super.onAdLoaded();
}
#Override
public void onAdClosed() {
//finish();
Passvalues.interstitial = null;
}
});
Passvalues.adCheck = true;
}
}
I have an activity with uses onOptionsItemSelected(MenuItem item) method in FolderActivity and I want to call this method on another activity (MainActivity)
the main activity uses CMU Sphinx - Speech Recognition Toolkit.
I need to call some methods from FolderActivity to MainActivity.
package com.evolution.filemanager.folders;
import static android.widget.Toast.makeText;
import java.io.File;
import java.util.ArrayList;
import android.annotation.TargetApi;
import android.app.ActionBar;
import android.app.Activity;
import android.app.Fragment;
import android.content.Intent;
import android.content.res.Configuration;
import android.os.Build;
import android.os.Bundle;
import android.support.v4.app.ActionBarDrawerToggle;
import android.support.v4.view.GravityCompat;
import android.support.v4.widget.DrawerLayout;
import android.util.Log;
import android.view.Gravity;
import android.view.KeyEvent;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.view.WindowManager;
import android.widget.AdapterView;
import android.widget.AdapterView.OnItemClickListener;
import android.widget.ListView;
import android.widget.Toast;
import com.evolution.filemanager.FileManagerApplication;
import com.evolution.filemanager.about.AboutActivity;
import com.evolution.filemanager.clipboard.Clipboard;
import com.evolution.filemanager.clipboard.Clipboard.ClipboardListener;
import com.evolution.filemanager.clipboard.ClipboardFileAdapter;
import com.evolution.filemanager.favourites.FavouritesManager;
import com.evolution.filemanager.favourites.FavouritesManager.FavouritesListener;
import com.evolution.filemanager.nav_drawer.NavDrawerAdapter;
import com.evolution.utils.FontApplicator;
import com.evolution.utils.ListViewUtils;
import edu.cmu.pocketsphinx.demo.R;
public class FolderActivity extends Activity implements OnItemClickListener, ClipboardListener, FavouritesListener
{
public static class FolderNotOpenException extends Exception
{
}
private static final String LOG_TAG = "Main Activity";
public static final String EXTRA_DIR = FolderFragment.EXTRA_DIR;
DrawerLayout drawerLayout;
ActionBarDrawerToggle actionBarDrawerToggle;
File lastFolder=null;
private FontApplicator fontApplicator;
public static Activity FOLDERACTIVITY;
protected void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main_folder);
setupDrawers();
Clipboard.getInstance().addListener(this);
FOLDERACTIVITY = this;
fontApplicator = new FontApplicator(getApplicationContext(), "Roboto_Light.ttf").applyFont(getWindow().getDecorView());
}
public FontApplicator getFontApplicator()
{
return fontApplicator;
}
#Override
protected void onDestroy()
{
Clipboard.getInstance().removeListener(this);
FileManagerApplication application = (FileManagerApplication) getApplication();
application.getFavouritesManager().removeFavouritesListener(this);
super.onDestroy();
}
public void setLastFolder(File lastFolder)
{
this.lastFolder = lastFolder;
}
#Override
protected void onPause()
{
if (lastFolder != null)
{
FileManagerApplication application = (FileManagerApplication) getApplication();
application.getAppPreferences().setStartFolder(lastFolder).saveChanges(getApplicationContext());
Log.d(LOG_TAG, "Saved last folder "+lastFolder.toString());
}
super.onPause();
}
public void setActionbarVisible(boolean visible)
{
ActionBar actionBar = getActionBar();
if (actionBar == null) return;
if (visible)
{
actionBar.show();
setSystemBarTranslucency(false);
}
else
{
actionBar.hide();
setSystemBarTranslucency(true);
}
}
#TargetApi(Build.VERSION_CODES.KITKAT)
protected void setSystemBarTranslucency(boolean translucent)
{
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.KITKAT) return;
if (translucent)
{
getWindow().setFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS, WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS);
}
else
{
WindowManager.LayoutParams params = getWindow().getAttributes();
params.flags &= (~WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS);
getWindow().setAttributes(params);
getWindow().clearFlags(WindowManager.LayoutParams.FLAG_LAYOUT_NO_LIMITS);
}
}
public void setupDrawers()
{
this.drawerLayout = (DrawerLayout) findViewById(R.id.drawer_layout);
actionBarDrawerToggle = new ActionBarDrawerToggle(this, drawerLayout, R.drawable.ic_drawer, R.string.open_drawer, R.string.close_drawer)
{
boolean actionBarShown = false;
#Override
public void onDrawerOpened(View drawerView)
{
makeText(getApplicationContext(), "drawer open", Toast.LENGTH_SHORT).show();
super.onDrawerOpened(drawerView);
setActionbarVisible(true);
invalidateOptionsMenu();
}
#Override
public void onDrawerClosed(View drawerView)
{
makeText(getApplicationContext(), "drawer close", Toast.LENGTH_SHORT).show();
actionBarShown=false;
super.onDrawerClosed(drawerView);
invalidateOptionsMenu();
}
#Override
public void onDrawerSlide(View drawerView, float slideOffset)
{
super.onDrawerSlide(drawerView, slideOffset);
if (slideOffset > 0 && actionBarShown == false)
{
actionBarShown = true;
setActionbarVisible(true);
}
else if (slideOffset <= 0) actionBarShown = false;
}
};
drawerLayout.setDrawerListener(actionBarDrawerToggle);
drawerLayout.setDrawerShadow(R.drawable.drawer_shadow, Gravity.START);
drawerLayout.setFocusableInTouchMode(false);
// drawerLayout.setDrawerShadow(R.drawable.drawer_shadow, Gravity.END);
getActionBar().setDisplayHomeAsUpEnabled(true);
getActionBar().setHomeButtonEnabled(true);
setupNavDrawer();
setupClipboardDrawer();
}
#Override
public void onBackPressed()
{
if (drawerLayout.isDrawerOpen(GravityCompat.START))
drawerLayout.closeDrawer(GravityCompat.START);
else if (drawerLayout.isDrawerOpen(GravityCompat.END))
drawerLayout.closeDrawer(GravityCompat.END);
else
super.onBackPressed();
}
void setupNavDrawer()
{
FileManagerApplication application = (FileManagerApplication) getApplication();
// add listview header to push items below the actionbar
ListView navListView = (ListView) findViewById(R.id.listNavigation);
ListViewUtils.addListViewPadding(navListView, this, true);
loadFavourites(application.getFavouritesManager());
application.getFavouritesManager().addFavouritesListener(this);
}
void setupClipboardDrawer()
{
// add listview header to push items below the actionbar
ListView clipboardListView = (ListView) findViewById(R.id.listClipboard);
ListViewUtils.addListViewHeader(clipboardListView, this);
onClipboardContentsChange(Clipboard.getInstance());
}
void loadFavourites(FavouritesManager favouritesManager)
{
ListView listNavigation = (ListView) findViewById(R.id.listNavigation);
NavDrawerAdapter navDrawerAdapter = new NavDrawerAdapter(this, new ArrayList<NavDrawerAdapter.NavDrawerItem>(favouritesManager.getFolders()));
navDrawerAdapter.setFontApplicator(fontApplicator);
listNavigation.setAdapter(navDrawerAdapter);
listNavigation.setOnItemClickListener(this);
}
#Override
protected void onPostCreate(Bundle savedInstanceState)
{
super.onPostCreate(savedInstanceState);
actionBarDrawerToggle.syncState();
if (getFragmentManager().findFragmentById(R.id.fragment) == null)
{
FolderFragment folderFragment = new FolderFragment();
if (getIntent().hasExtra(EXTRA_DIR))
{
Bundle args = new Bundle();
args.putString(FolderFragment.EXTRA_DIR, getIntent().getStringExtra(EXTRA_DIR));
folderFragment.setArguments(args);
}
getFragmentManager()
.beginTransaction()
.replace(R.id.fragment, folderFragment)
.commit();
}
}
#Override
public void onConfigurationChanged(Configuration newConfig)
{
makeText(getApplicationContext(), "unsa ni?", Toast.LENGTH_SHORT).show();
super.onConfigurationChanged(newConfig);
actionBarDrawerToggle.onConfigurationChanged(newConfig);
}
#Override
public boolean onOptionsItemSelected(MenuItem item)
{
makeText(getApplicationContext(), item.toString(), Toast.LENGTH_SHORT).show();
if (actionBarDrawerToggle.onOptionsItemSelected(item))
return true;
switch (item.getItemId())
{
case R.id.menu_about:
startActivity(new Intent(getApplicationContext(), AboutActivity.class));
return true;
}
return super.onOptionsItemSelected(item);
}
public void showFragment(Fragment fragment)
{
getFragmentManager()
.beginTransaction()
.addToBackStack(null)
.replace(R.id.fragment, fragment)
.commit();
}
public void goBack()
{
getFragmentManager().popBackStack();
}
#Override
public boolean onCreateOptionsMenu(Menu menu)
{
getMenuInflater().inflate(R.menu.main, menu);
return true;
}
public FolderFragment getFolderFragment()
{
Fragment fragment = getFragmentManager().findFragmentById(R.id.fragment);
if (fragment instanceof FolderFragment)
return (FolderFragment) fragment;
else return null;
}
public File getCurrentFolder() throws FolderNotOpenException
{
FolderFragment folderFragment = getFolderFragment();
if (folderFragment == null)
throw new FolderNotOpenException();
else return folderFragment.currentDir;
}
#Override
public void onItemClick(AdapterView<?> arg0, View arg1, int arg2, long arg3)
{
switch (arg0.getId())
{
case R.id.listNavigation:
NavDrawerAdapter.NavDrawerItem item = (NavDrawerAdapter.NavDrawerItem) arg0.getItemAtPosition(arg2);
if (item.onClicked(this))
drawerLayout.closeDrawers();
break;
case R.id.listClipboard:
FolderFragment folderFragment = getFolderFragment();
if (folderFragment != null)
{
// TODO: paste single file
}
break;
default:
break;
}
}
public File getLastFolder()
{
return lastFolder;
}
#Override
public void onClipboardContentsChange(Clipboard clipboard)
{
invalidateOptionsMenu();
ListView clipboardListView = (ListView) findViewById(R.id.listClipboard);
if (clipboard.isEmpty() && drawerLayout != null)
drawerLayout.setDrawerLockMode(DrawerLayout.LOCK_MODE_LOCKED_CLOSED, Gravity.END);
else
{
drawerLayout.setDrawerLockMode(DrawerLayout.LOCK_MODE_UNLOCKED, Gravity.END);
FileManagerApplication application = (FileManagerApplication) getApplication();
if (clipboardListView != null)
{
ClipboardFileAdapter clipboardFileAdapter = new ClipboardFileAdapter(this, clipboard, application.getFileIconResolver());
clipboardFileAdapter.setFontApplicator(fontApplicator);
clipboardListView.setAdapter(clipboardFileAdapter);
}
}
}
#Override
public void onFavouritesChanged(FavouritesManager favouritesManager)
{
loadFavourites(favouritesManager);
}
#Override
public boolean onKeyLongPress(int keyCode, KeyEvent event)
{
Log.d("Key Long Press", event.toString());
if (keyCode == KeyEvent.KEYCODE_BACK)
{
finish();
return true;
}
else return super.onKeyLongPress(keyCode, event);
}
}
and the activity where I want to call
package edu.cmu.pocketsphinx.demo;
import static android.widget.Toast.makeText;
import static edu.cmu.pocketsphinx.SpeechRecognizerSetup.defaultSetup;
import java.io.File;
import java.io.IOException;
import java.util.HashMap;
import android.app.Activity;
import android.content.Context;
import android.content.Intent;
import android.graphics.drawable.AnimationDrawable;
import android.os.AsyncTask;
import android.os.Bundle;
import android.widget.ImageView;
import android.widget.TextView;
import android.widget.Toast;
import com.evolution.filemanager.about.AboutActivity;
import com.evolution.filemanager.folders.FolderActivity;
import com.evolution.utils.DataClearer;
import edu.cmu.pocketsphinx.Assets;
import edu.cmu.pocketsphinx.Hypothesis;
import edu.cmu.pocketsphinx.RecognitionListener;
import edu.cmu.pocketsphinx.SpeechRecognizer;
public class MainActivity extends Activity implements
RecognitionListener {
public AnimationDrawable rocketAnimation;
private static final String KWS_SEARCH = "wakeup";
private static final String FORECAST_SEARCH = "forecast";
private static final String DIGITS_SEARCH = "digits";
private static final String MENU_SEARCH = "menu";
private static final String KEYPHRASE = "frost";
private static final String GO_BACK = "back";
private static final String PREVIOUS = "previous";
private static final String OPEN_FILE_MANAGER = "open file manager";
private static final String OPEN_ABOUT = "open about";
private static final String OPEN_MUSIC = "open music";
private static final String OPEN_PICTURES = "open pictures";
private static final String OPEN_VIDEOS = "open videos";
private static final String SHOW_COMMANDS = "show commands";
private static final String CLOSE_FILE_MANAGER = "close file manager";
private static final String CLOSE_ABOUT = "close about";
private static final String CLOSE_MUSIC = "close music";
private static final String CLOSE_PICTURES = "close pictures";
private static final String CLOSE_VIDEOS = "close videos";
private static final String CLOSE_COMMANDS = "close commands";
private static final String SHOW_DRAWER = "show drawer";
private static final String HIDE_DRAWER = "hide drawer";
public static boolean isOPEN_FILE_MANAGER = false;
private static boolean isOPEN_ABOUT = false;
private static boolean isOPEN_MUSIC = false;
private static boolean isOPEN_PICTURES = false;
private static boolean isOPEN_VIDEOS = false;
private static boolean isSHOW_COMMANDS = false;
private static boolean isSHOW_DRAWER = false;
private static String MENU_CAPTION;
private SpeechRecognizer recognizer;
private HashMap<String, Integer> captions;
#Override
public void onCreate(Bundle state) {
super.onCreate(state);
// Prepare the data for UI
captions = new HashMap<String, Integer>();
captions.put(KWS_SEARCH, R.string.kws_caption);
captions.put(MENU_SEARCH, R.string.menu_caption);
captions.put(DIGITS_SEARCH, R.string.digits_caption);
captions.put(FORECAST_SEARCH, R.string.forecast_caption);
setContentView(R.layout.main);
((TextView) findViewById(R.id.caption_text))
.setText("Preparing the recognizer");
ImageView rocketImage = (ImageView) findViewById(R.id.imageViewAnim);
rocketImage.setBackgroundResource(R.drawable.heart_animation);
rocketAnimation = (AnimationDrawable) rocketImage.getBackground();
// Recognizer initialization is a time-consuming and it involves IO,
// so we execute it in async task
new AsyncTask<Void, Void, Exception>() {
#Override
protected Exception doInBackground(Void... params) {
try {
Assets assets = new Assets(PocketSphinxActivity.this);
File assetDir = assets.syncAssets();
setupRecognizer(assetDir);
} catch (IOException e) {
return e;
}
return null;
}
#Override
protected void onPostExecute(Exception result) {
if (result != null) {
((TextView) findViewById(R.id.caption_text))
.setText("Failed to init recognizer " + result);
} else {
switchSearch(KWS_SEARCH);
}
}
}.execute();
}
#Override
public void onPartialResult(Hypothesis hypothesis) {
String text = hypothesis.getHypstr();
TextView tv = ((TextView) findViewById(R.id.caption_text));
if (text.equals(KEYPHRASE))
{
switchSearch(MENU_SEARCH);
rocketAnimation.start();
}
else if (text.equals(OPEN_FILE_MANAGER))
{
switchSearch(KWS_SEARCH);
Intent intent = new Intent (PocketSphinxActivity.this , FolderActivity.class);
startActivity(intent);
isOPEN_FILE_MANAGER = true;
}
else if (text.equals(CLOSE_FILE_MANAGER))
{
if(isOPEN_FILE_MANAGER == true)
{
switchSearch(KWS_SEARCH);
FolderActivity.FOLDERACTIVITY.finish();
isOPEN_FILE_MANAGER = false;
}
}
else if (text.equals(SHOW_COMMANDS))
{
switchSearch(KWS_SEARCH);
Intent intent = new Intent (PocketSphinxActivity.this , Commands.class);
startActivity(intent);
isSHOW_COMMANDS = true;
}
else if (text.equals(CLOSE_COMMANDS))
{
if(isSHOW_COMMANDS == true)
{
switchSearch(KWS_SEARCH);
Commands.SHOWCOMMANDS.finish();
}
}
else if (text.equals(OPEN_PICTURES))
{
switchSearch(KWS_SEARCH);
Intent intent = new Intent (PocketSphinxActivity.this , AboutActivity.class);
startActivity(intent);
}
else if(text.equals(OPEN_ABOUT))
{
switchSearch(KWS_SEARCH);
Intent intent = new Intent(PocketSphinxActivity.this, AboutActivity.class);
startActivity(intent);
isOPEN_ABOUT = true;
}
else if(text.equals(CLOSE_ABOUT))
{
if (isOPEN_ABOUT == true)
{
switchSearch(KWS_SEARCH);
AboutActivity.ABOUTACTIVITY.finish();
}
}
else if(text.equals(GO_BACK) || text.equals(PREVIOUS))
{
if(isOPEN_FILE_MANAGER == true )
{
FolderActivity.FOLDERACTIVITY//where i want to call onOptionsItemSelected
switchSearch(KWS_SEARCH);
}
}
else
{
switchSearch(KWS_SEARCH);
((TextView) findViewById(R.id.result_text)).setText(text);
}
}
#Override
public void onResult(Hypothesis hypothesis) {
((TextView) findViewById(R.id.result_text)).setText("");
if (hypothesis != null) {
String text = hypothesis.getHypstr();
makeText(getApplicationContext(), text, Toast.LENGTH_SHORT).show();
}
}
#Override
public void onBeginningOfSpeech() {
}
#Override
public void onEndOfSpeech() {
if (DIGITS_SEARCH.equals(recognizer.getSearchName())
|| FORECAST_SEARCH.equals(recognizer.getSearchName())
|| OPEN_FILE_MANAGER.equals(recognizer.getSearchName()))
switchSearch(KWS_SEARCH);
}
private void switchSearch(String searchName) {
recognizer.stop();
recognizer.startListening(searchName);
String caption = getResources().getString(captions.get(searchName));
((TextView) findViewById(R.id.caption_text)).setText(caption);
}
private void setupRecognizer(File assetsDir) {
File modelsDir = new File(assetsDir, "models");
recognizer = defaultSetup()
.setAcousticModel(new File(modelsDir, "hmm/en-us-semi"))
.setDictionary(new File(modelsDir, "dict/cmu07a.dic"))
.setRawLogDir(assetsDir).setKeywordThreshold(1e-20f)
.getRecognizer();
recognizer.addListener(this);
// Create keyword-activation search.
recognizer.addKeyphraseSearch(KWS_SEARCH, KEYPHRASE);
// Create grammar-based searches.
File menuGrammar = new File(modelsDir, "grammar/menu.gram");
recognizer.addGrammarSearch(MENU_SEARCH, menuGrammar);
File digitsGrammar = new File(modelsDir, "grammar/digits.gram");
recognizer.addGrammarSearch(DIGITS_SEARCH, digitsGrammar);
// Create language model search.
File languageModel = new File(modelsDir, "lm/weather.dmp");
recognizer.addNgramSearch(FORECAST_SEARCH, languageModel);
}
#Override
protected void onStop(){
super.onStop();
}
//Fires after the OnStop() state
#Override
protected void onDestroy() {
super.onDestroy();
try {
trimCache(this); //clear cache to minimize the app size
DataClearer.getInstance().clearApplicationData();
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
public static void trimCache(Context context) {
try {
File dir = context.getCacheDir();
if (dir != null && dir.isDirectory()) {
deleteDir(dir);
}
} catch (Exception e) {
// TODO: handle exception
}
}
public static boolean deleteDir(File dir) {
if (dir != null && dir.isDirectory()) {
String[] children = dir.list();
for (int i = 0; i < children.length; i++) {
boolean success = deleteDir(new File(dir, children[i]));
if (!success) {
return false;
}
}
}
// The directory is now empty so delete it
return dir.delete();
}
}
the FolderActivity runs on top of the MainActivty but the voice recognition in MainActivity is still active and I want the voice itself do some manipulation in the FolderActivity
Here's a few suggestions:
Have FolderActivity register a BroadcastReceiver as a listener for a certain Intent. When MainActivity wants to do something in FolderActivity, it can send a broadcast Intent which will be seen by the BroadcastReceiver in FolderActivity, which can then call the appropriate method in the `Activity.
When MainActivity wants to do something in FolderActivity, it can launch FolderActivity again using an Intent with flag Intent.FLAG_ACTIVITY_SINGLE_TOP and some "extra" that describes what FolderActivity should do. In FolderActivity override onNewIntent(), read the passed Intent parameter and use it to determine what method to call in FolderActivity. Because the Activity was launched withIntent.FLAG_ACTIVITY_SINGLE_TOP, Android won't create a new instance of the Activity, it will just callonNewIntent()` on the existing instance.
Have FolderActivity set a public static variable of type Activity to a reference to itself in onCreate(). MainActivity can then call a method on FolderActivity by doing something like FolderActivity.activityReference.doSomething()
Method 3 is not the preferred method, since you need to make sure that you set the public static variable to null in FolderActivity.onDestroy() and there are other concerns (timing issues, memory leaks, etc.) that need to be dealt with properly.
NOTE: You probably don't want to call onOptionsItemSelected() directly. This method is called by the Android framework when an options item is selected by the user. You should call directly the method that actually does something, not this framework callback method.