Java tutorial
/* Copyright (c) 2009-2016 Darshan-Josiah Barber This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. */ package com.stylovid.fastbattery; import android.app.Activity; import android.app.AlertDialog; import android.app.Dialog; import android.content.BroadcastReceiver; import android.content.ComponentName; import android.content.DialogInterface; import android.content.Intent; import android.content.IntentFilter; import android.content.pm.PackageManager; import android.content.res.Configuration; import android.content.SharedPreferences; import android.net.Uri; import android.os.Bundle; import android.os.Handler; import android.os.IBinder; import android.os.Message; import android.os.Messenger; import android.util.DisplayMetrics; import android.util.Log; import android.view.LayoutInflater; import android.view.Menu; import android.view.MenuInflater; import android.view.MenuItem; import android.view.View; import android.view.View.OnClickListener; import android.view.ViewGroup; import android.widget.Button; import android.widget.ImageView; import android.widget.LinearLayout; import android.widget.TextView; import android.widget.Toast; import android.support.v4.app.DialogFragment; import android.support.v4.app.Fragment; public class CurrentInfoFragment extends Fragment { private static PersistentFragment pfrag; private float dpScale; private static final Intent batteryUseIntent = new Intent(Intent.ACTION_POWER_USAGE_SUMMARY) .setFlags(Intent.FLAG_ACTIVITY_NEW_TASK); private static final IntentFilter batteryChangedFilter = new IntentFilter(Intent.ACTION_BATTERY_CHANGED); private View view; private Button battery_use_b; private BatteryLevel bl; private ImageView blv; private View current_icon; private TextView tv_temp; private TextView tv_health; private TextView tv_voltage; private TextView tv_current; private ImageView plugged_icon; private BatteryInfo info = new BatteryInfo(); private CurrentHack currentHack; public static boolean awaitingNotificationUnblock; public static boolean showingNotificationBlockDialog; private static final String LOG_TAG = "BatteryBot"; private final Handler mHandler = new Handler(); private final Runnable mARefresher = new Runnable() { public void run() { refreshCurrent(); mHandler.postDelayed(mARefresher, 2000); } }; @Override public void onConfigurationChanged(Configuration newConfig) { setSizes(newConfig); } @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { view = inflater.inflate(R.layout.current_info, container, false); bl = BatteryLevel.getInstance(getActivity(), pfrag.res.getInteger(R.integer.bl_inSampleSize)); blv = (ImageView) view.findViewById(R.id.battery_level_view); blv.setImageBitmap(bl.getBitmap()); battery_use_b = (Button) view.findViewById(R.id.battery_use_b); view.findViewById(R.id.vital_stats).setOnClickListener(vsListener); current_icon = view.findViewById(R.id.current_icon); tv_temp = (TextView) view.findViewById(R.id.temp); tv_health = (TextView) view.findViewById(R.id.health); tv_voltage = (TextView) view.findViewById(R.id.voltage); tv_current = (TextView) view.findViewById(R.id.current); plugged_icon = (ImageView) view.findViewById(R.id.plugged_icon); bindButtons(); setSizes(getActivity().getResources().getConfiguration()); if (!android.support.v4.app.NotificationManagerCompat.from(getActivity()).areNotificationsEnabled() && !showingNotificationBlockDialog) { showingNotificationBlockDialog = true; DialogFragment df = new NotificationsDisabledDialogFragment(); df.setTargetFragment(this, 0); df.show(getFragmentManager(), "TODO: What is this string for?3"); } return view; } @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); pfrag = PersistentFragment.getInstance(getFragmentManager()); dpScale = getActivity().getResources().getDisplayMetrics().density; currentHack = CurrentHack.getInstance(getActivity()); currentHack.setPreferFS(pfrag.settings.getBoolean(SettingsActivity.KEY_CURRENT_HACK_PREFER_FS, pfrag.res.getBoolean(R.bool.default_prefer_fs_current_hack))); setHasOptionsMenu(true); } @Override public void onStart() { super.onStart(); pfrag.setCIF(this); pfrag.sendServiceMessage(BatteryInfoService.RemoteConnection.SERVICE_REGISTER_CLIENT); if (awaitingNotificationUnblock) { awaitingNotificationUnblock = false; pfrag.sendServiceMessage( BatteryInfoService.RemoteConnection.SERVICE_CANCEL_NOTIFICATION_AND_RELOAD_SETTINGS); } Intent bc_intent = getActivity().registerReceiver(null, batteryChangedFilter); info.load(bc_intent); info.load(pfrag.sp_service); handleUpdatedBatteryInfo(); if (pfrag.settings.getBoolean(SettingsActivity.KEY_ENABLE_CURRENT_HACK, false) && pfrag.settings.getBoolean(SettingsActivity.KEY_DISPLAY_CURRENT_IN_MAIN_WINDOW, false) && pfrag.settings.getBoolean(SettingsActivity.KEY_AUTO_REFRESH_CURRENT_IN_MAIN_WINDOW, false)) mHandler.postDelayed(mARefresher, 2000); } @Override public void onStop() { super.onStop(); mHandler.removeCallbacks(mARefresher); pfrag.setCIF(null); } @Override public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) { super.onCreateOptionsMenu(menu, inflater); inflater.inflate(R.menu.main, menu); } public void showNotificationWizard() { new NotificationWizard().show(getFragmentManager(), "nwf"); } @Override public boolean onOptionsItemSelected(MenuItem item) { switch (item.getItemId()) { /* case R.id.menu_settings: mStartActivity(SettingsActivity.class); return true;*/ case R.id.menu_close: DialogFragment df = new ConfirmCloseDialogFragment(); // Setting target to this leaks the Fragment, but that's sort of good, as it allows pressing Okay // to work even if the screen rotates. Even if it rotates many times back and forth, only the // first Fragment is leaked, which will do the closing if Okay is pressed. Once the dialog is // gone (even if canceled), then the it and the leaked Fragment will be garbage collected. df.setTargetFragment(this, 0); df.show(getFragmentManager(), "TODO: What is this string for?2"); return true; case R.id.menu_help: mStartActivity(HelpActivity.class); return true; case R.id.menu_notification_wizard: showNotificationWizard(); return true; case R.id.menu_rate_and_review: try { startActivity(new Intent(Intent.ACTION_VIEW, Uri.parse("market://details?id=com.stylovid"))); } catch (Exception e) { Toast.makeText(getActivity(), "Sorry, can't launch Market!", Toast.LENGTH_SHORT).show(); } return true; default: return super.onOptionsItemSelected(item); } } @Override public void onActivityResult(int requestCode, int resultCode, Intent data) { super.onActivityResult(requestCode, resultCode, data); } public static class NotificationsDisabledDialogFragment extends DialogFragment { @Override public Dialog onCreateDialog(Bundle savedInstanceState) { return new AlertDialog.Builder(getActivity()) .setTitle(pfrag.res.getString(R.string.notifications_disabled)) .setMessage(pfrag.res.getString(R.string.notifications_disabled_message)) .setPositiveButton(pfrag.res.getString(android.R.string.ok), new DialogInterface.OnClickListener() { public void onClick(DialogInterface di, int id) { final Intent i = new Intent(); i.setAction(android.provider.Settings.ACTION_APPLICATION_DETAILS_SETTINGS); i.addCategory(Intent.CATEGORY_DEFAULT); i.setData(Uri.parse("package:" + getActivity().getPackageName())); i.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); //i.addFlags(Intent.FLAG_ACTIVITY_NO_HISTORY); i.addFlags(Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS); getActivity().startActivity(i); CurrentInfoFragment.awaitingNotificationUnblock = true; CurrentInfoFragment.showingNotificationBlockDialog = false; di.cancel(); } }) .setNegativeButton(pfrag.res.getString(R.string.cancel), new DialogInterface.OnClickListener() { public void onClick(DialogInterface di, int id) { CurrentInfoFragment.awaitingNotificationUnblock = false; CurrentInfoFragment.showingNotificationBlockDialog = false; di.cancel(); } }).create(); } } public static class ConfirmCloseDialogFragment extends DialogFragment { @Override public Dialog onCreateDialog(Bundle savedInstanceState) { return new AlertDialog.Builder(getActivity()).setTitle(pfrag.res.getString(R.string.confirm_close)) .setMessage(pfrag.res.getString(R.string.confirm_close_hint)) .setPositiveButton(pfrag.res.getString(R.string.yes), new DialogInterface.OnClickListener() { public void onClick(DialogInterface di, int id) { pfrag.closeApp(); di.cancel(); } }) .setNegativeButton(pfrag.res.getString(R.string.cancel), new DialogInterface.OnClickListener() { public void onClick(DialogInterface di, int id) { di.cancel(); } }).create(); } } public void batteryInfoUpdated(Bundle bundle) { info.loadBundle(bundle); handleUpdatedBatteryInfo(); } private void handleUpdatedBatteryInfo() { bl.setLevel(info.percent); blv.invalidate(); TextView tv = (TextView) view.findViewById(R.id.level); tv.setText("" + info.percent + pfrag.res.getString(R.string.percent_symbol)); tv = (TextView) view.findViewById(R.id.time_remaining); tv.setText(pfrag.str.timeRemainingMainScreen(info)); tv = (TextView) view.findViewById(R.id.until_what); tv.setText(pfrag.str.untilWhat(info)); int secs = (int) ((System.currentTimeMillis() - info.last_status_cTM) / 1000); int hours = secs / (60 * 60); int mins = (secs / 60) % 60; String s = pfrag.str.statuses[info.last_status]; if (info.last_status == BatteryInfo.STATUS_CHARGING) s += " " + pfrag.str.pluggeds[info.last_plugged]; tv = (TextView) view.findViewById(R.id.status); tv.setText(s); if (info.last_percent >= 0) { s = "Since "; // TODO: Translatable if (info.last_status != BatteryInfo.STATUS_FULLY_CHARGED) s += info.last_percent + pfrag.str.percent_symbol + ", "; s += hours + "h " + mins + "m ago"; // TODO: Translatable tv = (TextView) view.findViewById(R.id.status_duration); tv.setText(s); } Boolean convertF = pfrag.settings.getBoolean(SettingsActivity.KEY_CONVERT_F, pfrag.res.getBoolean(R.bool.default_convert_to_fahrenheit)); tv_health.setText(pfrag.str.healths[info.health]); tv_temp.setText(pfrag.str.formatTemp(info.temperature, convertF)); if (info.voltage > 500) tv_voltage.setText(pfrag.str.formatVoltage(info.voltage)); if (info.last_status == BatteryInfo.STATUS_UNPLUGGED) plugged_icon.setImageResource(R.drawable.unplugged); else plugged_icon.setImageResource(R.drawable.not_unplugged); refreshCurrent(); } private void refreshCurrent() { String s = ""; if (pfrag.settings.getBoolean(SettingsActivity.KEY_ENABLE_CURRENT_HACK, false) && pfrag.settings.getBoolean(SettingsActivity.KEY_DISPLAY_CURRENT_IN_MAIN_WINDOW, false)) { current_icon.setVisibility(View.VISIBLE); Long current = null; if (pfrag.settings.getBoolean(SettingsActivity.KEY_PREFER_CURRENT_AVG_IN_MAIN_WINDOW, false)) current = currentHack.getAvgCurrent(); if (current == null) // Either don't prefer avg or avg isn't available current = currentHack.getCurrent(); if (current != null) s += String.valueOf(current) + "mA"; } else { current_icon.setVisibility(View.INVISIBLE); } // User may have just turned off hack or main window display of it, so we need to always set the text tv_current.setText(s); } /* mA TextView */ private final OnClickListener vsListener = new OnClickListener() { public void onClick(View v) { refreshCurrent(); } }; /* Battery Use */ private final OnClickListener buButtonListener = new OnClickListener() { public void onClick(View v) { try { startActivity(batteryUseIntent); } catch (Exception e) { battery_use_b.setEnabled(false); } } }; private void mStartActivity(Class c) { ComponentName comp = new ComponentName(getActivity().getPackageName(), c.getName()); //startActivity(new Intent().setComponent(comp)); startActivityForResult(new Intent().setComponent(comp), 1); //getActivity().finish(); } private void bindButtons() { if (getActivity().getPackageManager().resolveActivity(batteryUseIntent, 0) == null) { battery_use_b.setEnabled(false); /* TODO: change how the disabled button looks */ } else { battery_use_b.setOnClickListener(buButtonListener); } } // Sets sizes of most Views based on current dimensions // Must be called from onCreateView() after inflation and from onConfigurationChanged() private void setSizes(Configuration config) { boolean portrait = config.orientation == Configuration.ORIENTATION_PORTRAIT; int screenWidth, screenHeight; if (android.os.Build.VERSION.SDK_INT < 13) { DisplayMetrics metrics = new DisplayMetrics(); getActivity().getWindowManager().getDefaultDisplay().getMetrics(metrics); screenWidth = metrics.widthPixels; screenHeight = (int) (metrics.heightPixels * 0.95); } else { screenWidth = (int) (config.screenWidthDp * dpScale); screenHeight = (int) (config.screenHeightDp * dpScale); } int minDimen = Math.min(screenWidth, screenHeight); float aspectRatio = (float) screenWidth / screenHeight; // System.out.println("...................................................." + // "\n config.screenWidthDp: " + config.screenWidthDp + // "\n config.screenHeightDp: " + config.screenHeightDp + // "\n config figured pixel width: " + screenWidth + // "\n config figured pixel height: " + screenHeight + // "\n aspectRatio: " + aspectRatio + // "\n portrait: " + portrait // ); int plugged_icon_height; int time_remaining_text_height, until_what_text_height; int status_text_height; int bu_height, bu_text_height; int vital_icon_height, vital_text_height; if (portrait) { plugged_icon_height = (int) (screenHeight * 0.1); time_remaining_text_height = (int) (screenHeight * 0.048); until_what_text_height = (int) (screenHeight * 0.032); status_text_height = (int) (screenHeight * 0.04); bu_height = (int) (screenHeight * 0.14); bu_text_height = (int) (screenHeight * 0.035); vital_icon_height = (int) (screenHeight * 0.05); vital_text_height = (int) (screenHeight * 0.03); } else { plugged_icon_height = (int) (screenHeight * 0.11); time_remaining_text_height = (int) (screenHeight * 0.06); until_what_text_height = (int) (screenHeight * 0.04); status_text_height = (int) (screenHeight * 0.05); bu_height = (int) (screenHeight * 0.18); bu_text_height = (int) (screenHeight * 0.045); vital_icon_height = (int) (screenHeight * 0.08); vital_text_height = (int) (screenHeight * 0.05); } TextView level = (TextView) view.findViewById(R.id.level); level.setTextSize(android.util.TypedValue.COMPLEX_UNIT_PX, plugged_icon_height); View clock = view.findViewById(R.id.clock); clock.setLayoutParams( new LinearLayout.LayoutParams(plugged_icon_height, ViewGroup.LayoutParams.MATCH_PARENT)); TextView time_remaining = (TextView) view.findViewById(R.id.time_remaining); time_remaining.setTextSize(android.util.TypedValue.COMPLEX_UNIT_PX, time_remaining_text_height); TextView until_what = (TextView) view.findViewById(R.id.until_what); until_what.setTextSize(android.util.TypedValue.COMPLEX_UNIT_PX, until_what_text_height); TextView status = (TextView) view.findViewById(R.id.status); status.setTextSize(android.util.TypedValue.COMPLEX_UNIT_PX, status_text_height); TextView status_duration = (TextView) view.findViewById(R.id.status_duration); status_duration.setTextSize(android.util.TypedValue.COMPLEX_UNIT_PX, until_what_text_height); View plugged_icon = view.findViewById(R.id.plugged_icon); plugged_icon.setLayoutParams( new LinearLayout.LayoutParams(plugged_icon_height, ViewGroup.LayoutParams.MATCH_PARENT)); View plugged_spacer = view.findViewById(R.id.plugged_spacer); plugged_spacer.setLayoutParams(new LinearLayout.LayoutParams(plugged_icon_height, plugged_icon_height)); Button bu_button = (Button) view.findViewById(R.id.battery_use_b); bu_button.setLayoutParams(new LinearLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, bu_height)); bu_button.setTextSize(android.util.TypedValue.COMPLEX_UNIT_PX, bu_text_height); View temp_icon = view.findViewById(R.id.temp_icon); temp_icon.setLayoutParams(new LinearLayout.LayoutParams(vital_icon_height, vital_icon_height)); TextView temp_text = (TextView) view.findViewById(R.id.temp); temp_text.setLayoutParams(new LinearLayout.LayoutParams(0, vital_icon_height, 0.5f)); temp_text.setTextSize(android.util.TypedValue.COMPLEX_UNIT_PX, vital_text_height); View health_icon = view.findViewById(R.id.health_icon); health_icon.setLayoutParams(new LinearLayout.LayoutParams(vital_icon_height, vital_icon_height)); TextView health_text = (TextView) view.findViewById(R.id.health); health_text.setLayoutParams(new LinearLayout.LayoutParams(0, vital_icon_height, 0.5f)); health_text.setTextSize(android.util.TypedValue.COMPLEX_UNIT_PX, vital_text_height); View voltage_icon = view.findViewById(R.id.voltage_icon); voltage_icon.setLayoutParams(new LinearLayout.LayoutParams(vital_icon_height, vital_icon_height)); TextView voltage_text = (TextView) view.findViewById(R.id.voltage); voltage_text.setLayoutParams(new LinearLayout.LayoutParams(0, vital_icon_height, 0.5f)); voltage_text.setTextSize(android.util.TypedValue.COMPLEX_UNIT_PX, vital_text_height); View current_icon = view.findViewById(R.id.current_icon); current_icon.setLayoutParams(new LinearLayout.LayoutParams(vital_icon_height, vital_icon_height)); TextView current_text = (TextView) view.findViewById(R.id.current); current_text.setLayoutParams(new LinearLayout.LayoutParams(0, vital_icon_height, 0.5f)); current_text.setTextSize(android.util.TypedValue.COMPLEX_UNIT_PX, vital_text_height); // When in landscape but close to square, plugged icon gets cramped and cut off; make more room: if (!portrait && aspectRatio < 1.32) plugged_spacer.setVisibility(View.GONE); else plugged_spacer.setVisibility(View.INVISIBLE); } }