/* * Copyright (c) 2013 Menny Even-Danan * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.anysoftkeyboard.ui.dev; import android.app.Activity; import android.app.AlertDialog; import android.content.Intent; import android.net.Uri; import android.os.Bundle; import android.support.annotation.NonNull; import android.support.v4.app.Fragment; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; import android.widget.Button; import android.widget.TextView; import android.widget.Toast; import com.anysoftkeyboard.utils.Log; import com.menny.android.anysoftkeyboard.R; import net.evendanan.pushingpixels.AsyncTaskWithProgressWindow; import net.evendanan.pushingpixels.FragmentChauffeurActivity; import net.evendanan.pushingpixels.PassengerFragmentSupport; import java.io.File; public class DeveloperToolsFragment extends Fragment implements AsyncTaskWithProgressWindow.AsyncTaskOwner, View.OnClickListener { private abstract static class DeveloperAsyncTask<Params, Progress, Result> extends AsyncTaskWithProgressWindow<Params, Progress, Result, DeveloperToolsFragment> { public DeveloperAsyncTask(DeveloperToolsFragment mainDeveloperActivity) { super(mainDeveloperActivity); } } @NonNull private Button mFlipper; @NonNull private View mProgressIndicator; @NonNull private View mShareButton; @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { return inflater.inflate(R.layout.developer_tools, container, false); } @Override public void onViewCreated(View view, Bundle savedInstanceState) { super.onViewCreated(view, savedInstanceState); ((TextView) view.findViewById(R.id.dev_title)).setText(DeveloperUtils.getAppDetails(getActivity().getApplicationContext())); mFlipper = (Button) view.findViewById(R.id.dev_flip_trace_file); mProgressIndicator = view.findViewById(R.id.dev_tracing_running_progress_bar); mShareButton = view.findViewById(R.id.dev_share_trace_file); view.findViewById(R.id.memory_dump_button).setOnClickListener(this); view.findViewById(R.id.dev_share_mem_file).setOnClickListener(this); view.findViewById(R.id.dev_flip_trace_file).setOnClickListener(this); view.findViewById(R.id.dev_share_trace_file).setOnClickListener(this); view.findViewById(R.id.show_logcat_button).setOnClickListener(this); view.findViewById(R.id.share_logcat_button).setOnClickListener(this); } @Override public void onStart() { super.onStart(); updateTracingState(); PassengerFragmentSupport.setActivityTitle(this, getString(R.string.developer_tools)); } private void updateTracingState() { if (DeveloperUtils.hasTracingRequested(getActivity().getApplicationContext())) { mFlipper.setText("Disable tracing"); } else { mFlipper.setText("Enable tracing"); } if (DeveloperUtils.hasTracingStarted()) { mProgressIndicator.setVisibility(View.VISIBLE); } else { mProgressIndicator.setVisibility(View.INVISIBLE); } if (!DeveloperUtils.hasTracingStarted() && DeveloperUtils.getTraceFile().exists()) { mShareButton.setEnabled(true); } else { mShareButton.setEnabled(false); } } @Override public void onClick(View v) { switch (v.getId()) { case R.id.memory_dump_button: onUserClickedMemoryDump(); break; case R.id.dev_share_mem_file: onUserClickedShareMemoryDump(v); break; case R.id.dev_flip_trace_file: onUserClickedFlipTracing(); break; case R.id.dev_share_trace_file: onUserClickedShareTracingFile(); break; case R.id.show_logcat_button: onUserClickedShowLogCat(v); break; case R.id.share_logcat_button: onUserClickedShareLogCat(); break; } } private void onUserClickedMemoryDump() { DeveloperAsyncTask<Void, Void, File> task = new DeveloperAsyncTask<Void, Void, File>( this) { @Override protected File doAsyncTask(Void[] params) throws Exception { return DeveloperUtils.createMemoryDump(); } @Override protected void applyResults(File result, Exception backgroundException) { Activity activity = getActivity(); if (activity == null) return; View rootView = getView(); if (rootView == null) return; if (backgroundException != null) { Toast.makeText(activity.getApplicationContext(), getString(R.string.failed_to_create_mem_dump, backgroundException.getMessage()), Toast.LENGTH_LONG).show(); } else { Toast.makeText(activity.getApplicationContext(), getString(R.string.created_mem_dump_file, result.getAbsolutePath()), Toast.LENGTH_LONG).show(); View shareMemFile = rootView.findViewById(R.id.dev_share_mem_file); shareMemFile.setTag(result); shareMemFile.setEnabled(result.exists() && result.isFile()); } } }; task.execute(); } private void onUserClickedShareMemoryDump(View v) { File memDump = (File) v.getTag(); StringBuilder sb = new StringBuilder( "Hi! Here is a memory dump file for "); sb.append(DeveloperUtils.getAppDetails(getActivity().getApplicationContext())); sb.append(DeveloperUtils.NEW_LINE); sb.append(DeveloperUtils.getSysInfo()); shareFile(memDump, "AnySoftKeyboard Memory Dump File", sb.toString()); } private void onUserClickedFlipTracing() { final boolean enable = !DeveloperUtils .hasTracingRequested(getActivity().getApplicationContext()); DeveloperUtils.setTracingRequested(getActivity().getApplicationContext(), enable); updateTracingState(); if (enable) { // Just a few words to the user AlertDialog info = new AlertDialog.Builder(getActivity()) .setIcon(R.drawable.notification_icon_beta_version) .setTitle("How to use Tracing") .setMessage( "Tracing is now enabled, but not started!" + DeveloperUtils.NEW_LINE + "To start tracing, you'll need to restart AnySoftKeyboard. How? Either reboot your phone, or switch to another keyboard app (like the stock)." + DeveloperUtils.NEW_LINE + "To stop tracing, first disable it, and then restart AnySoftkeyboard (as above)." + DeveloperUtils.NEW_LINE + "Thanks!!") .setPositiveButton("Got it!", null).create(); info.show(); } else if (DeveloperUtils.hasTracingStarted()) { // the tracing is running now, so I'll explain how to stop it AlertDialog info = new AlertDialog.Builder(getActivity()) .setIcon(R.drawable.notification_icon_beta_version) .setTitle("How to stop Tracing") .setMessage( "Tracing is now disabled, but not ended!" + DeveloperUtils.NEW_LINE + "To end tracing (and to be able to send the file), you'll need to restart AnySoftKeyboard. How? Either reboot your phone (preferable), or switch to another keyboard app (like the stock)." + DeveloperUtils.NEW_LINE + "Thanks!!") .setPositiveButton("Got it!", null).create(); info.show(); } } private void onUserClickedShareTracingFile() { StringBuilder sb = new StringBuilder("Hi! Here is a tracing file for "); sb.append(DeveloperUtils.getAppDetails(getActivity().getApplicationContext())); sb.append(DeveloperUtils.NEW_LINE); sb.append(DeveloperUtils.getSysInfo()); shareFile(DeveloperUtils.getTraceFile(), "AnySoftKeyboard Trace File", sb.toString()); } private void onUserClickedShowLogCat(View v) { ((FragmentChauffeurActivity) getActivity()).addFragmentToUi(new LogCatViewFragment(), FragmentChauffeurActivity.FragmentUiContext.ExpandedItem, v); } private void onUserClickedShareLogCat() { StringBuilder sb = new StringBuilder("Hi! Here is a LogCat snippet for "); sb.append(DeveloperUtils.getAppDetails(getActivity().getApplicationContext())); sb.append(DeveloperUtils.NEW_LINE); sb.append(DeveloperUtils.getSysInfo()); sb.append(DeveloperUtils.NEW_LINE); sb.append(Log.getAllLogLines()); shareFile(null, "AnySoftKeyboard LogCat", sb.toString()); } private void shareFile(File fileToShare, String title, String message) { Intent sendMail = new Intent(); sendMail.setAction(Intent.ACTION_SEND); sendMail.setType("plain/text"); sendMail.putExtra(Intent.EXTRA_SUBJECT, title); sendMail.putExtra(Intent.EXTRA_TEXT, message); if (fileToShare != null) { sendMail.putExtra(Intent.EXTRA_STREAM, Uri.fromFile(fileToShare)); } try { Intent sender = Intent.createChooser(sendMail, "Share"); sender.putExtra(Intent.EXTRA_SUBJECT, title); sender.putExtra(Intent.EXTRA_TEXT, message); startActivity(sender); } catch (android.content.ActivityNotFoundException ex) { Toast.makeText(getActivity().getApplicationContext(), "Unable to send bug report via e-mail!", Toast.LENGTH_LONG) .show(); } } }