initial implementation of rewriting the app in kotlin

This commit is contained in:
tibbi 2017-11-05 22:37:47 +01:00
parent a856156f76
commit 18b5c9de46
34 changed files with 1040 additions and 1458 deletions

View File

@ -16,10 +16,10 @@
android:label="@string/app_launcher_name"
android:supportsRtl="true"
android:theme="@style/AppTheme">
<activity
android:name=".activities.MainActivity"
android:screenOrientation="portrait"
android:theme="@style/BlackSplashScreen.Dark">
android:name=".activities.SplashActivity"
android:theme="@style/SplashTheme">
<intent-filter>
<action android:name="android.intent.action.MAIN"/>
@ -27,6 +27,11 @@
</intent-filter>
</activity>
<activity
android:name=".activities.MainActivity"
android:screenOrientation="portrait"
android:theme="@style/BlackSplashScreen.Dark"/>
<activity
android:name=".activities.WidgetConfigureActivity"
android:screenOrientation="portrait"
@ -36,16 +41,6 @@
</intent-filter>
</activity>
<activity
android:name=".activities.AboutActivity"
android:label="@string/about"
android:parentActivityName=".activities.MainActivity"/>
<activity
android:name=".activities.LicenseActivity"
android:label="@string/third_party_licences"
android:parentActivityName=".activities.AboutActivity"/>
<activity
android:name=".activities.BrightDisplayActivity"
android:screenOrientation="portrait"/>
@ -55,6 +50,21 @@
android:label="@string/settings"
android:parentActivityName=".activities.MainActivity"/>
<activity
android:name="com.simplemobiletools.commons.activities.AboutActivity"
android:label="@string/about"
android:parentActivityName=".activities.MainActivity"/>
<activity
android:name="com.simplemobiletools.commons.activities.LicenseActivity"
android:label="@string/third_party_licences"
android:parentActivityName="com.simplemobiletools.commons.activities.AboutActivity"/>
<activity
android:name="com.simplemobiletools.commons.activities.CustomizationActivity"
android:label="@string/customize_colors"
android:parentActivityName=".activities.SettingsActivity"/>
<receiver
android:name=".helpers.MyWidgetProvider"
android:icon="@drawable/circles_small">

View File

@ -1,110 +0,0 @@
package com.simplemobiletools.flashlight.activities;
import android.content.ActivityNotFoundException;
import android.content.Intent;
import android.content.res.Resources;
import android.net.Uri;
import android.os.Bundle;
import android.text.Html;
import android.text.method.LinkMovementMethod;
import android.view.View;
import android.widget.TextView;
import com.simplemobiletools.flashlight.BuildConfig;
import com.simplemobiletools.flashlight.helpers.Config;
import com.simplemobiletools.flashlight.R;
import java.util.Calendar;
import butterknife.BindView;
import butterknife.ButterKnife;
import butterknife.OnClick;
public class AboutActivity extends SimpleActivity {
@BindView(R.id.about_copyright) TextView mCopyright;
@BindView(R.id.about_email) TextView mEmailTV;
@BindView(R.id.about_rate_us) View mRateUs;
private static Resources mRes;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_about);
ButterKnife.bind(this);
mRes = getResources();
setupEmail();
setupCopyright();
setupRateUs();
}
private void setupEmail() {
final String email = mRes.getString(R.string.email);
final String appName = mRes.getString(R.string.app_name);
final String href = "<a href=\"mailto:" + email + "?subject=" + appName + "\">" + email + "</a>";
mEmailTV.setText(Html.fromHtml(href));
mEmailTV.setMovementMethod(LinkMovementMethod.getInstance());
}
private void setupCopyright() {
final String versionName = BuildConfig.VERSION_NAME;
final int year = Calendar.getInstance().get(Calendar.YEAR);
final String copyrightText = String.format(mRes.getString(R.string.copyright), versionName, year);
mCopyright.setText(copyrightText);
}
private void setupRateUs() {
if (Config.newInstance(getApplicationContext()).getIsFirstRun()) {
mRateUs.setVisibility(View.GONE);
}
}
@OnClick(R.id.about_invite)
public void inviteFriend() {
final Intent intent = new Intent();
final String text = String.format(getString(R.string.share_text), getString(R.string.app_name), getStoreUrl());
intent.setAction(Intent.ACTION_SEND);
intent.putExtra(Intent.EXTRA_SUBJECT, getString(R.string.app_name));
intent.putExtra(Intent.EXTRA_TEXT, text);
intent.setType("text/plain");
startActivity(Intent.createChooser(intent, getString(R.string.invite_via)));
}
@OnClick(R.id.about_rate_us)
public void rateUsClicked() {
final Uri uri = Uri.parse("market://details?id=" + getPackageName());
try {
startActivity(new Intent(Intent.ACTION_VIEW, uri));
} catch (ActivityNotFoundException ignored) {
startActivity(new Intent(Intent.ACTION_VIEW, Uri.parse(getStoreUrl())));
}
}
@OnClick(R.id.about_license)
public void licenseClicked() {
final Intent intent = new Intent(getApplicationContext(), LicenseActivity.class);
startActivity(intent);
}
@OnClick(R.id.about_facebook)
public void facebookClicked() {
String link = "https://www.facebook.com/simplemobiletools";
try {
getPackageManager().getPackageInfo("com.facebook.katana", 0);
link = "fb://page/150270895341774";
} catch (Exception ignored) {
}
startActivity(new Intent(Intent.ACTION_VIEW, Uri.parse(link)));
}
@OnClick(R.id.about_gplus)
public void googlePlusClicked() {
final String link = "https://plus.google.com/communities/104880861558693868382";
startActivity(new Intent(Intent.ACTION_VIEW, Uri.parse(link)));
}
private String getStoreUrl() {
return "https://play.google.com/store/apps/details?id=" + getPackageName();
}
}

View File

@ -1,38 +0,0 @@
package com.simplemobiletools.flashlight.activities;
import android.os.Bundle;
import android.support.annotation.Nullable;
import android.view.WindowManager;
import com.simplemobiletools.flashlight.R;
public class BrightDisplayActivity extends SimpleActivity {
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_bright_display);
if (getSupportActionBar() != null)
getSupportActionBar().hide();
}
@Override
protected void onResume() {
super.onResume();
getWindow().addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
toggleBrightness(true);
}
@Override
protected void onPause() {
super.onPause();
getWindow().clearFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
toggleBrightness(false);
}
private void toggleBrightness(boolean increase) {
final WindowManager.LayoutParams layout = getWindow().getAttributes();
layout.screenBrightness = (increase ? 1 : 0);
getWindow().setAttributes(layout);
}
}

View File

@ -1,41 +0,0 @@
package com.simplemobiletools.flashlight.activities;
import android.content.Intent;
import android.net.Uri;
import android.os.Bundle;
import com.simplemobiletools.flashlight.R;
import butterknife.ButterKnife;
import butterknife.OnClick;
public class LicenseActivity extends SimpleActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_license);
ButterKnife.bind(this);
}
@OnClick(R.id.license_butterknife_title)
public void butterKnifeClicked() {
openUrl(R.string.butterknife_url);
}
@OnClick(R.id.license_ambilwarna_title)
public void ambilwarnaClicked() {
openUrl(R.string.ambilwarna_url);
}
@OnClick(R.id.license_otto_title)
public void ottoClicked() {
openUrl(R.string.otto_url);
}
private void openUrl(int id) {
final String url = getResources().getString(id);
final Intent browserIntent = new Intent(Intent.ACTION_VIEW, Uri.parse(url));
startActivity(browserIntent);
}
}

View File

@ -1,227 +0,0 @@
package com.simplemobiletools.flashlight.activities;
import android.Manifest;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.graphics.PorterDuff;
import android.os.Bundle;
import android.support.v4.app.ActivityCompat;
import android.support.v4.content.ContextCompat;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.view.WindowManager;
import android.widget.ImageView;
import android.widget.SeekBar;
import com.simplemobiletools.flashlight.helpers.BusProvider;
import com.simplemobiletools.flashlight.helpers.Config;
import com.simplemobiletools.flashlight.models.Events;
import com.simplemobiletools.flashlight.helpers.MyCameraImpl;
import com.simplemobiletools.flashlight.R;
import com.simplemobiletools.flashlight.helpers.Utils;
import com.squareup.otto.Bus;
import com.squareup.otto.Subscribe;
import butterknife.BindView;
import butterknife.ButterKnife;
import butterknife.OnClick;
public class MainActivity extends SimpleActivity {
private static final int CAMERA_PERMISSION = 1;
private static final int MAX_STROBO_DELAY = 2000;
private static final int MIN_STROBO_DELAY = 30;
@BindView(R.id.toggle_btn) ImageView mToggleBtn;
@BindView(R.id.bright_display_btn) ImageView mBrightDisplayBtn;
@BindView(R.id.stroboscope_btn) ImageView mStroboscopeBtn;
@BindView(R.id.stroboscope_bar) SeekBar mStroboscopeBar;
private static Bus mBus;
private MyCameraImpl mCameraImpl;
private boolean mJustGrantedPermission;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
ButterKnife.bind(this);
mBus = BusProvider.getInstance();
changeIconColor(R.color.translucent_white, mBrightDisplayBtn);
changeIconColor(R.color.translucent_white, mStroboscopeBtn);
mStroboscopeBar.setMax(MAX_STROBO_DELAY - MIN_STROBO_DELAY);
mStroboscopeBar.setProgress(mStroboscopeBar.getMax() / 2);
mStroboscopeBar.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener() {
@Override
public void onProgressChanged(SeekBar seekBar, int progress, boolean b) {
final int frequency = mStroboscopeBar.getMax() - progress + MIN_STROBO_DELAY;
if (mCameraImpl != null)
mCameraImpl.setStroboFrequency(frequency);
}
@Override
public void onStartTrackingTouch(SeekBar seekBar) {
}
@Override
public void onStopTrackingTouch(SeekBar seekBar) {
}
});
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
getMenuInflater().inflate(R.menu.menu, menu);
return true;
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()) {
case R.id.settings:
startActivity(new Intent(getApplicationContext(), SettingsActivity.class));
return true;
case R.id.about:
startActivity(new Intent(getApplicationContext(), AboutActivity.class));
return true;
default:
return super.onOptionsItemSelected(item);
}
}
private void setupCameraImpl() {
mCameraImpl = new MyCameraImpl(this);
mCameraImpl.enableFlashlight();
}
@OnClick(R.id.toggle_btn)
public void toggleFlashlight() {
mCameraImpl.toggleFlashlight();
}
@OnClick(R.id.bright_display_btn)
public void launchBrightDisplay() {
startActivity(new Intent(getApplicationContext(), BrightDisplayActivity.class));
}
@OnClick(R.id.stroboscope_btn)
public void tryToggleStroboscope() {
toggleStroboscope();
}
private void toggleStroboscope() {
// use the old Camera API for stroboscope, the new Camera Manager is way too slow
if (isCameraPermissionGranted() || Utils.isNougat()) {
if (mCameraImpl.toggleStroboscope()) {
mStroboscopeBar.setVisibility(mStroboscopeBar.getVisibility() == View.VISIBLE ? View.INVISIBLE : View.VISIBLE);
changeIconColor(mStroboscopeBar.getVisibility() == View.VISIBLE ? R.color.colorPrimary : R.color.translucent_white, mStroboscopeBtn);
}
} else {
final String[] permissions = {Manifest.permission.CAMERA};
ActivityCompat.requestPermissions(this, permissions, CAMERA_PERMISSION);
}
}
@Override
public void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults) {
super.onRequestPermissionsResult(requestCode, permissions, grantResults);
if (requestCode == CAMERA_PERMISSION) {
mJustGrantedPermission = true;
if (isCameraPermissionGranted()) {
toggleStroboscope();
} else {
Utils.showToast(getApplicationContext(), R.string.camera_permission);
}
}
}
@Override
protected void onStart() {
super.onStart();
mBus.register(this);
if (mCameraImpl == null) {
setupCameraImpl();
}
}
@Override
protected void onResume() {
super.onResume();
if (mJustGrantedPermission) {
mJustGrantedPermission = false;
return;
}
mCameraImpl.handleCameraSetup();
mCameraImpl.checkFlashlight();
mBrightDisplayBtn.setVisibility(mConfig.getBrightDisplay() ? View.VISIBLE : View.GONE);
mStroboscopeBtn.setVisibility(mConfig.getStroboscope() ? View.VISIBLE : View.GONE);
if (!mConfig.getStroboscope()) {
mCameraImpl.stopStroboscope();
mStroboscopeBar.setVisibility(View.INVISIBLE);
}
}
@Override
protected void onStop() {
super.onStop();
mBus.unregister(this);
}
@Override
protected void onDestroy() {
super.onDestroy();
Config.newInstance(getApplicationContext()).setIsFirstRun(false);
releaseCamera();
}
private void releaseCamera() {
if (mCameraImpl != null) {
mCameraImpl.releaseCamera();
mCameraImpl = null;
}
}
private boolean isCameraPermissionGranted() {
return ContextCompat.checkSelfPermission(getApplicationContext(), Manifest.permission.CAMERA) == PackageManager.PERMISSION_GRANTED;
}
@Subscribe
public void stateChangedEvent(Events.StateChanged event) {
if (event.getIsEnabled()) {
enableFlashlight();
} else {
disableFlashlight();
}
}
public void enableFlashlight() {
changeIconColor(R.color.colorPrimary, mToggleBtn);
getWindow().addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
changeIconColor(R.color.translucent_white, mStroboscopeBtn);
mStroboscopeBar.setVisibility(View.INVISIBLE);
}
public void disableFlashlight() {
changeIconColor(R.color.translucent_white, mToggleBtn);
getWindow().clearFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
}
private void changeIconColor(int colorId, ImageView imageView) {
final int appColor = getResources().getColor(colorId);
imageView.getBackground().mutate().setColorFilter(appColor, PorterDuff.Mode.SRC_IN);
}
@Subscribe
public void cameraUnavailable(Events.CameraUnavailable event) {
Utils.showToast(this, R.string.camera_error);
disableFlashlight();
}
}

View File

@ -1,67 +0,0 @@
package com.simplemobiletools.flashlight.activities;
import android.os.Bundle;
import android.support.v4.app.TaskStackBuilder;
import android.support.v7.widget.SwitchCompat;
import com.simplemobiletools.flashlight.helpers.Config;
import com.simplemobiletools.flashlight.R;
import butterknife.BindView;
import butterknife.ButterKnife;
import butterknife.OnClick;
public class SettingsActivity extends SimpleActivity {
@BindView(R.id.settings_dark_theme) SwitchCompat mDarkThemeSwitch;
@BindView(R.id.settings_bright_display) SwitchCompat mBrightDisplaySwitch;
@BindView(R.id.settings_stroboscope) SwitchCompat mStroboscopeSwitch;
private static Config mConfig;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_settings);
mConfig = Config.newInstance(getApplicationContext());
ButterKnife.bind(this);
setupDarkTheme();
setupBrightDisplay();
setupStroboscope();
}
private void setupDarkTheme() {
mDarkThemeSwitch.setChecked(mConfig.getIsDarkTheme());
}
private void setupBrightDisplay() {
mBrightDisplaySwitch.setChecked(mConfig.getBrightDisplay());
}
private void setupStroboscope() {
mStroboscopeSwitch.setChecked(mConfig.getStroboscope());
}
@OnClick(R.id.settings_dark_theme_holder)
public void handleDarkTheme() {
mDarkThemeSwitch.setChecked(!mDarkThemeSwitch.isChecked());
mConfig.setIsDarkTheme(mDarkThemeSwitch.isChecked());
restartActivity();
}
@OnClick(R.id.settings_bright_display_holder)
public void handleBrightDisplay() {
mBrightDisplaySwitch.setChecked(!mBrightDisplaySwitch.isChecked());
mConfig.setBrightDisplay(mBrightDisplaySwitch.isChecked());
}
@OnClick(R.id.settings_stroboscope_holder)
public void handleStroboscope() {
mStroboscopeSwitch.setChecked(!mStroboscopeSwitch.isChecked());
mConfig.setStroboscope(mStroboscopeSwitch.isChecked());
}
private void restartActivity() {
TaskStackBuilder.create(getApplicationContext()).addNextIntentWithParentStack(getIntent()).startActivities();
}
}

View File

@ -1,35 +0,0 @@
package com.simplemobiletools.flashlight.activities;
import android.os.Bundle;
import android.support.annotation.Nullable;
import android.support.v7.app.AppCompatActivity;
import android.view.MenuItem;
import com.simplemobiletools.flashlight.helpers.Config;
import com.simplemobiletools.flashlight.R;
public class SimpleActivity extends AppCompatActivity {
protected Config mConfig;
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
mConfig = Config.newInstance(getApplicationContext());
int theme = mConfig.getIsDarkTheme() ? R.style.AppTheme_Dark : R.style.AppTheme;
if (this instanceof MainActivity) {
theme = R.style.BlackSplashScreen_Dark;
}
setTheme(theme);
super.onCreate(savedInstanceState);
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()) {
case android.R.id.home:
finish();
return true;
default:
return super.onOptionsItemSelected(item);
}
}
}

View File

@ -1,142 +0,0 @@
package com.simplemobiletools.flashlight.activities;
import android.appwidget.AppWidgetManager;
import android.content.Context;
import android.content.Intent;
import android.content.SharedPreferences;
import android.graphics.Color;
import android.graphics.PorterDuff;
import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.view.View;
import android.widget.ImageView;
import android.widget.RemoteViews;
import android.widget.SeekBar;
import com.simplemobiletools.flashlight.helpers.Constants;
import com.simplemobiletools.flashlight.helpers.MyWidgetProvider;
import com.simplemobiletools.flashlight.R;
import butterknife.BindView;
import butterknife.ButterKnife;
import butterknife.OnClick;
import yuku.ambilwarna.AmbilWarnaDialog;
public class WidgetConfigureActivity extends AppCompatActivity {
@BindView(R.id.config_widget_seekbar) SeekBar mWidgetSeekBar;
@BindView(R.id.config_widget_color) View mWidgetColorPicker;
@BindView(R.id.config_image) ImageView mImage;
private static float mWidgetAlpha;
private static int mWidgetId;
private static int mWidgetColor;
private static int mWidgetColorWithoutTransparency;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setResult(RESULT_CANCELED);
setContentView(R.layout.widget_config);
ButterKnife.bind(this);
initVariables();
final Intent intent = getIntent();
final Bundle extras = intent.getExtras();
if (extras != null)
mWidgetId = extras.getInt(AppWidgetManager.EXTRA_APPWIDGET_ID, AppWidgetManager.INVALID_APPWIDGET_ID);
if (mWidgetId == AppWidgetManager.INVALID_APPWIDGET_ID)
finish();
}
private void initVariables() {
final SharedPreferences prefs = getSharedPreferences(Constants.PREFS_KEY, Context.MODE_PRIVATE);
mWidgetColor = prefs.getInt(Constants.WIDGET_COLOR, 1);
if (mWidgetColor == 1) {
mWidgetColor = getResources().getColor(R.color.colorPrimary);
mWidgetAlpha = 1.f;
} else {
mWidgetAlpha = Color.alpha(mWidgetColor) / (float) 255;
}
mWidgetColorWithoutTransparency = Color.rgb(Color.red(mWidgetColor), Color.green(mWidgetColor), Color.blue(mWidgetColor));
mWidgetSeekBar.setOnSeekBarChangeListener(seekbarChangeListener);
mWidgetSeekBar.setProgress((int) (mWidgetAlpha * 100));
updateColors();
}
@OnClick(R.id.config_save)
public void saveConfig() {
final AppWidgetManager appWidgetManager = AppWidgetManager.getInstance(this);
final RemoteViews views = new RemoteViews(getPackageName(), R.layout.widget);
appWidgetManager.updateAppWidget(mWidgetId, views);
storeWidgetColors();
requestWidgetUpdate();
final Intent resultValue = new Intent();
resultValue.putExtra(AppWidgetManager.EXTRA_APPWIDGET_ID, mWidgetId);
setResult(RESULT_OK, resultValue);
finish();
}
@OnClick(R.id.config_widget_color)
public void pickBackgroundColor() {
AmbilWarnaDialog dialog = new AmbilWarnaDialog(this, mWidgetColorWithoutTransparency, new AmbilWarnaDialog.OnAmbilWarnaListener() {
@Override
public void onCancel(AmbilWarnaDialog dialog) {
}
@Override
public void onOk(AmbilWarnaDialog dialog, int color) {
mWidgetColorWithoutTransparency = color;
updateColors();
}
});
dialog.show();
}
private void storeWidgetColors() {
final SharedPreferences prefs = getSharedPreferences(Constants.PREFS_KEY, Context.MODE_PRIVATE);
prefs.edit().putInt(Constants.WIDGET_COLOR, mWidgetColor).apply();
}
private void requestWidgetUpdate() {
final Intent intent = new Intent(AppWidgetManager.ACTION_APPWIDGET_UPDATE, null, this, MyWidgetProvider.class);
intent.putExtra(AppWidgetManager.EXTRA_APPWIDGET_IDS, new int[]{mWidgetId});
sendBroadcast(intent);
}
private void updateColors() {
mWidgetColor = adjustAlpha(mWidgetColorWithoutTransparency, mWidgetAlpha);
mWidgetColorPicker.setBackgroundColor(mWidgetColor);
mImage.getBackground().mutate().setColorFilter(mWidgetColor, PorterDuff.Mode.SRC_IN);
}
private SeekBar.OnSeekBarChangeListener seekbarChangeListener = new SeekBar.OnSeekBarChangeListener() {
@Override
public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) {
mWidgetAlpha = (float) progress / (float) 100;
updateColors();
}
@Override
public void onStartTrackingTouch(SeekBar seekBar) {
}
@Override
public void onStopTrackingTouch(SeekBar seekBar) {
}
};
private int adjustAlpha(int color, float factor) {
final int alpha = Math.round(Color.alpha(color) * factor);
final int red = Color.red(color);
final int green = Color.green(color);
final int blue = Color.blue(color);
return Color.argb(alpha, red, green, blue);
}
}

View File

@ -1,11 +0,0 @@
package com.simplemobiletools.flashlight.helpers;
import com.squareup.otto.Bus;
public class BusProvider {
private static final Bus BUS = new Bus();
public static Bus getInstance() {
return BUS;
}
}

View File

@ -1,48 +0,0 @@
package com.simplemobiletools.flashlight.helpers;
import android.content.Context;
import android.content.SharedPreferences;
public class Config {
private SharedPreferences mPrefs;
public static Config newInstance(Context context) {
return new Config(context);
}
private Config(Context context) {
mPrefs = context.getSharedPreferences(Constants.PREFS_KEY, Context.MODE_PRIVATE);
}
public boolean getIsFirstRun() {
return mPrefs.getBoolean(Constants.IS_FIRST_RUN, true);
}
public void setIsFirstRun(boolean firstRun) {
mPrefs.edit().putBoolean(Constants.IS_FIRST_RUN, firstRun).apply();
}
public boolean getIsDarkTheme() {
return mPrefs.getBoolean(Constants.IS_DARK_THEME, false);
}
public void setIsDarkTheme(boolean isDarkTheme) {
mPrefs.edit().putBoolean(Constants.IS_DARK_THEME, isDarkTheme).apply();
}
public boolean getBrightDisplay() {
return mPrefs.getBoolean(Constants.BRIGHT_DISPLAY, true);
}
public void setBrightDisplay(boolean brightDisplay) {
mPrefs.edit().putBoolean(Constants.BRIGHT_DISPLAY, brightDisplay).apply();
}
public boolean getStroboscope() {
return mPrefs.getBoolean(Constants.STROBOSCOPE, true);
}
public void setStroboscope(boolean stroboscope) {
mPrefs.edit().putBoolean(Constants.STROBOSCOPE, stroboscope).apply();
}
}

View File

@ -1,11 +0,0 @@
package com.simplemobiletools.flashlight.helpers;
public class Constants {
// shared preferences
public static final String PREFS_KEY = "Flashlight";
public static final String IS_FIRST_RUN = "is_first_run";
public static final String IS_DARK_THEME = "is_dark_theme";
public static final String BRIGHT_DISPLAY = "bright_display";
public static final String STROBOSCOPE = "stroboscope";
public static final String WIDGET_COLOR = "widget_color";
}

View File

@ -1,48 +0,0 @@
package com.simplemobiletools.flashlight.helpers;
import android.annotation.TargetApi;
import android.content.Context;
import android.hardware.camera2.CameraAccessException;
import android.hardware.camera2.CameraManager;
import android.os.Build;
import android.os.Handler;
import android.util.Log;
import com.simplemobiletools.flashlight.models.Events;
import com.squareup.otto.Bus;
class MarshmallowCamera {
private static final String TAG = MyCameraImpl.class.getSimpleName();
private CameraManager manager;
private String cameraId;
private Context mContext;
@TargetApi(Build.VERSION_CODES.M)
MarshmallowCamera(Context context) {
mContext = context;
manager = (CameraManager) context.getSystemService(Context.CAMERA_SERVICE);
try {
final String[] list = manager.getCameraIdList();
cameraId = list[0];
} catch (CameraAccessException ignored) {
}
}
@TargetApi(Build.VERSION_CODES.M)
void toggleMarshmallowFlashlight(final Bus bus, boolean enable) {
try {
manager.setTorchMode(cameraId, enable);
} catch (CameraAccessException e) {
Log.e(TAG, "toggle marshmallow flashlight " + e.getMessage());
Runnable mainRunnable = new Runnable() {
@Override
public void run() {
bus.post(new Events.CameraUnavailable());
}
};
new Handler(mContext.getMainLooper()).post(mainRunnable);
}
}
}

View File

@ -1,275 +0,0 @@
package com.simplemobiletools.flashlight.helpers;
import android.content.Context;
import android.graphics.SurfaceTexture;
import android.hardware.Camera;
import android.os.Handler;
import android.util.Log;
import com.simplemobiletools.flashlight.R;
import com.simplemobiletools.flashlight.models.Events;
import com.squareup.otto.Bus;
import java.io.IOException;
public class MyCameraImpl {
private static final String TAG = MyCameraImpl.class.getSimpleName();
private static Camera mCamera;
private static Camera.Parameters mParams;
private static Bus mBus;
private Context mContext;
private MarshmallowCamera mMarshmallowCamera;
private volatile boolean mShouldStroboscopeStop;
private volatile boolean mIsStroboscopeRunning;
private static boolean mIsFlashlightOn;
private static boolean mIsMarshmallow;
private static boolean mShouldEnableFlashlight;
private static int mStroboFrequency;
public MyCameraImpl(Context cxt) {
mContext = cxt;
mIsMarshmallow = isMarshmallow();
mStroboFrequency = 1000;
if (mBus == null) {
mBus = BusProvider.getInstance();
mBus.register(this);
}
handleCameraSetup();
checkFlashlight();
}
public void toggleFlashlight() {
mIsFlashlightOn = !mIsFlashlightOn;
handleCameraSetup();
}
public void setStroboFrequency(int frequency) {
mStroboFrequency = frequency;
}
public boolean toggleStroboscope() {
if (!mIsStroboscopeRunning)
disableFlashlight();
if (!Utils.isNougat()) {
if (mCamera == null) {
initCamera();
}
if (mCamera == null) {
Utils.showToast(mContext, R.string.camera_error);
return false;
}
}
if (mIsStroboscopeRunning) {
stopStroboscope();
} else {
new Thread(stroboscope).start();
}
return true;
}
public void stopStroboscope() {
mShouldStroboscopeStop = true;
}
public void handleCameraSetup() {
if (mIsMarshmallow) {
setupMarshmallowCamera();
} else {
setupCamera();
}
checkFlashlight();
}
private void setupMarshmallowCamera() {
if (mMarshmallowCamera == null) {
mMarshmallowCamera = new MarshmallowCamera(mContext);
}
}
private void setupCamera() {
if (mIsMarshmallow)
return;
if (mCamera == null) {
initCamera();
}
}
private void initCamera() {
try {
mCamera = Camera.open();
mParams = mCamera.getParameters();
mParams.setFlashMode(Camera.Parameters.FLASH_MODE_OFF);
mCamera.setParameters(mParams);
} catch (Exception e) {
Log.e(TAG, "setup mCamera " + e.getMessage());
mBus.post(new Events.CameraUnavailable());
}
}
public void checkFlashlight() {
if (mIsFlashlightOn) {
enableFlashlight();
} else {
disableFlashlight();
}
}
public void enableFlashlight() {
mShouldStroboscopeStop = true;
if (mIsStroboscopeRunning) {
mShouldEnableFlashlight = true;
return;
}
mIsFlashlightOn = true;
if (mIsMarshmallow) {
toggleMarshmallowFlashlight(true);
} else {
if (mCamera == null || mParams == null) {
return;
}
mParams.setFlashMode(Camera.Parameters.FLASH_MODE_TORCH);
mCamera.setParameters(mParams);
mCamera.startPreview();
}
Runnable mainRunnable = new Runnable() {
@Override
public void run() {
mBus.post(new Events.StateChanged(true));
}
};
new Handler(mContext.getMainLooper()).post(mainRunnable);
}
private void disableFlashlight() {
if (mIsStroboscopeRunning) {
return;
}
mIsFlashlightOn = false;
if (mIsMarshmallow) {
toggleMarshmallowFlashlight(false);
} else {
if (mCamera == null || mParams == null) {
return;
}
mParams.setFlashMode(Camera.Parameters.FLASH_MODE_OFF);
mCamera.setParameters(mParams);
}
mBus.post(new Events.StateChanged(false));
}
private void toggleMarshmallowFlashlight(boolean enable) {
mMarshmallowCamera.toggleMarshmallowFlashlight(mBus, enable);
}
public void releaseCamera() {
if (mIsFlashlightOn) {
disableFlashlight();
}
if (mCamera != null) {
mCamera.release();
mCamera = null;
}
if (mBus != null) {
mBus.unregister(this);
}
mIsFlashlightOn = false;
mShouldStroboscopeStop = true;
}
private boolean isMarshmallow() {
return android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.M;
}
private Runnable stroboscope = new Runnable() {
@Override
public void run() {
if (mIsStroboscopeRunning) {
return;
}
mShouldStroboscopeStop = false;
mIsStroboscopeRunning = true;
if (Utils.isNougat()) {
while (!mShouldStroboscopeStop) {
try {
mMarshmallowCamera.toggleMarshmallowFlashlight(mBus, true);
Thread.sleep(mStroboFrequency);
mMarshmallowCamera.toggleMarshmallowFlashlight(mBus, false);
Thread.sleep(mStroboFrequency);
} catch (InterruptedException ignored) {
mShouldStroboscopeStop = true;
} catch (RuntimeException ignored) {
mShouldStroboscopeStop = true;
}
}
} else {
if (mCamera == null) {
initCamera();
}
Camera.Parameters torchOn = mCamera.getParameters();
Camera.Parameters torchOff = mCamera.getParameters();
torchOn.setFlashMode(Camera.Parameters.FLASH_MODE_TORCH);
torchOff.setFlashMode(Camera.Parameters.FLASH_MODE_OFF);
SurfaceTexture dummy = new SurfaceTexture(1);
try {
mCamera.setPreviewTexture(dummy);
} catch (IOException e) {
Log.e(TAG, "setup stroboscope1 " + e.getMessage());
}
mCamera.startPreview();
while (!mShouldStroboscopeStop) {
try {
mCamera.setParameters(torchOn);
Thread.sleep(mStroboFrequency);
mCamera.setParameters(torchOff);
Thread.sleep(mStroboFrequency);
} catch (InterruptedException ignored) {
mShouldStroboscopeStop = true;
} catch (RuntimeException ignored) {
mShouldStroboscopeStop = true;
}
}
try {
if (mCamera != null) {
mCamera.setParameters(torchOff);
if (!mShouldEnableFlashlight || mIsMarshmallow) {
mCamera.release();
mCamera = null;
}
}
} catch (RuntimeException e) {
Log.e(TAG, "setup stroboscope2 " + e.getMessage());
}
}
mIsStroboscopeRunning = false;
mShouldStroboscopeStop = false;
if (mShouldEnableFlashlight) {
enableFlashlight();
mShouldEnableFlashlight = false;
}
}
};
}

View File

@ -1,152 +0,0 @@
package com.simplemobiletools.flashlight.helpers;
import android.app.PendingIntent;
import android.appwidget.AppWidgetManager;
import android.appwidget.AppWidgetProvider;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.SharedPreferences;
import android.content.res.Resources;
import android.graphics.Bitmap;
import android.graphics.Color;
import android.graphics.PorterDuff;
import android.graphics.drawable.Drawable;
import android.widget.RemoteViews;
import com.simplemobiletools.flashlight.R;
import com.simplemobiletools.flashlight.models.Events;
import com.squareup.otto.Bus;
import com.squareup.otto.Subscribe;
public class MyWidgetProvider extends AppWidgetProvider {
private static final String TOGGLE = "toggle";
private static MyCameraImpl mCameraImpl;
private static RemoteViews mRemoteViews;
private static AppWidgetManager mWidgetManager;
private static Bitmap mColoredBmp;
private static Bitmap mWhiteBmp;
private static Bus mBus;
private static Context mContext;
private static int[] mWidgetIds;
@Override
public void onUpdate(Context context, AppWidgetManager appWidgetManager, int[] appWidgetIds) {
initVariables(context);
appWidgetManager.updateAppWidget(appWidgetIds, mRemoteViews);
}
private void initVariables(Context context) {
mContext = context;
final ComponentName component = new ComponentName(context, MyWidgetProvider.class);
mWidgetManager = AppWidgetManager.getInstance(context);
mWidgetIds = mWidgetManager.getAppWidgetIds(component);
final Intent intent = new Intent(context, MyWidgetProvider.class);
intent.setAction(TOGGLE);
final PendingIntent pendingIntent = PendingIntent.getBroadcast(context, 0, intent, 0);
mRemoteViews = new RemoteViews(context.getPackageName(), R.layout.widget);
mRemoteViews.setOnClickPendingIntent(R.id.toggle_btn, pendingIntent);
mCameraImpl = new MyCameraImpl(context);
final SharedPreferences prefs = initPrefs(context);
final Resources res = context.getResources();
final int defaultColor = res.getColor(R.color.colorPrimary);
final int selectedColor = prefs.getInt(Constants.WIDGET_COLOR, defaultColor);
final int alpha = Color.alpha(selectedColor);
mColoredBmp = getColoredCircles(selectedColor, alpha);
mWhiteBmp = getColoredCircles(Color.WHITE, alpha);
mRemoteViews.setImageViewBitmap(R.id.toggle_btn, mWhiteBmp);
if (mBus == null) {
mBus = BusProvider.getInstance();
}
registerBus();
}
@Override
public void onReceive(Context context, Intent intent) {
final String action = intent.getAction();
if (action.equals(TOGGLE)) {
if (mCameraImpl == null || mBus == null) {
initVariables(context);
}
mCameraImpl.toggleFlashlight();
} else
super.onReceive(context, intent);
}
private Bitmap getColoredCircles(int color, int alpha) {
final Drawable drawable = mContext.getResources().getDrawable(R.drawable.circles_small);
drawable.mutate().setColorFilter(color, PorterDuff.Mode.SRC_ATOP);
drawable.mutate().setAlpha(alpha);
return Utils.drawableToBitmap(drawable);
}
public void enableFlashlight() {
mRemoteViews.setImageViewBitmap(R.id.toggle_btn, mColoredBmp);
for (int widgetId : mWidgetIds) {
mWidgetManager.updateAppWidget(widgetId, mRemoteViews);
}
}
public void disableFlashlight() {
mRemoteViews.setImageViewBitmap(R.id.toggle_btn, mWhiteBmp);
for (int widgetId : mWidgetIds) {
mWidgetManager.updateAppWidget(widgetId, mRemoteViews);
}
}
private SharedPreferences initPrefs(Context context) {
return context.getSharedPreferences(Constants.PREFS_KEY, Context.MODE_PRIVATE);
}
@Subscribe
public void cameraUnavailable(Events.CameraUnavailable event) {
if (mContext != null) {
Utils.showToast(mContext, R.string.camera_error);
disableFlashlight();
}
}
@Subscribe
public void stateChangedEvent(Events.StateChanged event) {
if (event.getIsEnabled()) {
enableFlashlight();
} else {
disableFlashlight();
}
}
@Override
public void onDeleted(Context context, int[] appWidgetIds) {
super.onDeleted(context, appWidgetIds);
unregisterBus();
releaseCamera(context);
}
private void releaseCamera(Context context) {
if (mCameraImpl == null)
initVariables(context);
mCameraImpl.releaseCamera();
}
private void registerBus() {
try {
mBus.register(this);
} catch (Exception ignored) {
}
}
private void unregisterBus() {
try {
mBus.unregister(this);
} catch (Exception ignored) {
}
}
}

View File

@ -1,28 +0,0 @@
package com.simplemobiletools.flashlight.helpers;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.graphics.drawable.Drawable;
import android.os.Build;
import android.widget.Toast;
public class Utils {
public static Bitmap drawableToBitmap(Drawable drawable) {
final int width = drawable.getIntrinsicWidth();
final int height = drawable.getIntrinsicHeight();
final Bitmap mutableBitmap = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888);
final Canvas canvas = new Canvas(mutableBitmap);
drawable.setBounds(0, 0, width, height);
drawable.draw(canvas);
return mutableBitmap;
}
public static void showToast(Context context, int resId) {
Toast.makeText(context, context.getResources().getString(resId), Toast.LENGTH_SHORT).show();
}
public static boolean isNougat() {
return Build.VERSION.SDK_INT >= Build.VERSION_CODES.N;
}
}

View File

@ -1,18 +0,0 @@
package com.simplemobiletools.flashlight.models;
public class Events {
public static class StateChanged {
private static boolean mIsEnabled;
public StateChanged(boolean isEnabled) {
mIsEnabled = isEnabled;
}
public boolean getIsEnabled() {
return mIsEnabled;
}
}
public static class CameraUnavailable {
}
}

View File

@ -0,0 +1,32 @@
package com.simplemobiletools.flashlight.activities
import android.os.Bundle
import android.view.WindowManager
import com.simplemobiletools.flashlight.R
class BrightDisplayActivity : SimpleActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_bright_display)
supportActionBar?.hide()
}
override fun onResume() {
super.onResume()
window.addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON)
toggleBrightness(true)
}
override fun onPause() {
super.onPause()
window.clearFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON)
toggleBrightness(false)
}
private fun toggleBrightness(increase: Boolean) {
val layout = window.attributes
layout.screenBrightness = (if (increase) 1 else 0).toFloat()
window.attributes = layout
}
}

View File

@ -0,0 +1,224 @@
package com.simplemobiletools.flashlight.activities
import android.Manifest
import android.content.Intent
import android.content.pm.PackageManager
import android.graphics.PorterDuff
import android.os.Bundle
import android.support.v4.app.ActivityCompat
import android.support.v4.content.ContextCompat
import android.view.Menu
import android.view.MenuItem
import android.view.View
import android.view.WindowManager
import android.widget.ImageView
import android.widget.SeekBar
import butterknife.ButterKnife
import butterknife.OnClick
import com.simplemobiletools.commons.activities.AboutActivity
import com.simplemobiletools.commons.extensions.beInvisible
import com.simplemobiletools.commons.helpers.LICENSE_KOTLIN
import com.simplemobiletools.commons.helpers.LICENSE_OTTO
import com.simplemobiletools.flashlight.BuildConfig
import com.simplemobiletools.flashlight.R
import com.simplemobiletools.flashlight.extensions.config
import com.simplemobiletools.flashlight.helpers.BusProvider
import com.simplemobiletools.flashlight.helpers.MyCameraImpl
import com.simplemobiletools.flashlight.helpers.Utils
import com.simplemobiletools.flashlight.models.Events
import com.squareup.otto.Bus
import com.squareup.otto.Subscribe
import kotlinx.android.synthetic.main.activity_main.*
class MainActivity : SimpleActivity() {
companion object {
private val CAMERA_PERMISSION = 1
private val MAX_STROBO_DELAY = 2000
private val MIN_STROBO_DELAY = 30
private var mBus: Bus? = null
}
private var mCameraImpl: MyCameraImpl? = null
private var mJustGrantedPermission: Boolean = false
private val isCameraPermissionGranted: Boolean
get() = ContextCompat.checkSelfPermission(applicationContext, Manifest.permission.CAMERA) == PackageManager.PERMISSION_GRANTED
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
ButterKnife.bind(this)
mBus = BusProvider.instance
changeIconColor(R.color.translucent_white, bright_display_btn)
changeIconColor(R.color.translucent_white, stroboscope_btn)
stroboscope_bar.max = MAX_STROBO_DELAY - MIN_STROBO_DELAY
stroboscope_bar.progress = stroboscope_bar.max / 2
stroboscope_bar.setOnSeekBarChangeListener(object : SeekBar.OnSeekBarChangeListener {
override fun onProgressChanged(seekBar: SeekBar, progress: Int, b: Boolean) {
val frequency = stroboscope_bar.max - progress + MIN_STROBO_DELAY
if (mCameraImpl != null)
mCameraImpl!!.setStroboFrequency(frequency)
}
override fun onStartTrackingTouch(seekBar: SeekBar) {
}
override fun onStopTrackingTouch(seekBar: SeekBar) {
}
})
}
override fun onCreateOptionsMenu(menu: Menu): Boolean {
menuInflater.inflate(R.menu.menu, menu)
return true
}
override fun onOptionsItemSelected(item: MenuItem): Boolean {
when (item.itemId) {
R.id.settings -> {
startActivity(Intent(applicationContext, SettingsActivity::class.java))
return true
}
R.id.about -> {
startActivity(Intent(applicationContext, AboutActivity::class.java))
return true
}
else -> return super.onOptionsItemSelected(item)
}
}
private fun launchSettings() {
startActivity(Intent(applicationContext, SettingsActivity::class.java))
}
private fun launchAbout() {
startAboutActivity(R.string.app_name, LICENSE_KOTLIN or LICENSE_OTTO, BuildConfig.VERSION_NAME)
}
private fun setupCameraImpl() {
mCameraImpl = MyCameraImpl(this)
mCameraImpl!!.enableFlashlight()
}
@OnClick(R.id.toggle_btn)
fun toggleFlashlight() {
mCameraImpl!!.toggleFlashlight()
}
@OnClick(R.id.bright_display_btn)
fun launchBrightDisplay() {
startActivity(Intent(applicationContext, BrightDisplayActivity::class.java))
}
@OnClick(R.id.stroboscope_btn)
fun tryToggleStroboscope() {
toggleStroboscope()
}
private fun toggleStroboscope() {
// use the old Camera API for stroboscope, the new Camera Manager is way too slow
if (isCameraPermissionGranted || Utils.isNougat) {
if (mCameraImpl!!.toggleStroboscope()) {
stroboscope_bar.visibility = if (stroboscope_bar.visibility == View.VISIBLE) View.INVISIBLE else View.VISIBLE
changeIconColor(if (stroboscope_bar.visibility == View.VISIBLE) R.color.colorPrimary else R.color.translucent_white, stroboscope_btn)
}
} else {
val permissions = arrayOf(Manifest.permission.CAMERA)
ActivityCompat.requestPermissions(this, permissions, CAMERA_PERMISSION)
}
}
override fun onRequestPermissionsResult(requestCode: Int, permissions: Array<String>, grantResults: IntArray) {
super.onRequestPermissionsResult(requestCode, permissions, grantResults)
if (requestCode == CAMERA_PERMISSION) {
mJustGrantedPermission = true
if (isCameraPermissionGranted) {
toggleStroboscope()
} else {
Utils.showToast(applicationContext, R.string.camera_permission)
}
}
}
override fun onStart() {
super.onStart()
mBus!!.register(this)
if (mCameraImpl == null) {
setupCameraImpl()
}
}
override fun onResume() {
super.onResume()
if (mJustGrantedPermission) {
mJustGrantedPermission = false
return
}
mCameraImpl!!.handleCameraSetup()
mCameraImpl!!.checkFlashlight()
bright_display_btn!!.visibility = if (config.brightDisplay) View.VISIBLE else View.GONE
stroboscope_btn!!.visibility = if (config.stroboscope) View.VISIBLE else View.GONE
if (!config.stroboscope) {
mCameraImpl!!.stopStroboscope()
stroboscope_bar.visibility = View.INVISIBLE
}
}
override fun onStop() {
super.onStop()
mBus!!.unregister(this)
}
override fun onDestroy() {
super.onDestroy()
releaseCamera()
}
private fun releaseCamera() {
if (mCameraImpl != null) {
mCameraImpl!!.releaseCamera()
mCameraImpl = null
}
}
@Subscribe
fun stateChangedEvent(event: Events.StateChanged) {
if (event.isEnabled) {
enableFlashlight()
} else {
disableFlashlight()
}
}
fun enableFlashlight() {
changeIconColor(R.color.colorPrimary, toggle_btn)
window.addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON)
changeIconColor(R.color.translucent_white, stroboscope_btn)
stroboscope_bar.beInvisible()
}
fun disableFlashlight() {
changeIconColor(R.color.translucent_white, toggle_btn)
window.clearFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON)
}
private fun changeIconColor(colorId: Int, imageView: ImageView?) {
val appColor = resources.getColor(colorId)
imageView!!.background.mutate().setColorFilter(appColor, PorterDuff.Mode.SRC_IN)
}
@Subscribe
fun cameraUnavailable(event: Events.CameraUnavailable) {
Utils.showToast(this, R.string.camera_error)
disableFlashlight()
}
}

View File

@ -0,0 +1,54 @@
package com.simplemobiletools.flashlight.activities
import android.os.Bundle
import android.support.v4.app.TaskStackBuilder
import android.support.v7.widget.SwitchCompat
import butterknife.BindView
import butterknife.ButterKnife
import butterknife.OnClick
import com.simplemobiletools.flashlight.R
import com.simplemobiletools.flashlight.helpers.Config
class SettingsActivity : SimpleActivity() {
@BindView(R.id.settings_bright_display) internal var mBrightDisplaySwitch: SwitchCompat? = null
@BindView(R.id.settings_stroboscope) internal var mStroboscopeSwitch: SwitchCompat? = null
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_settings)
mConfig = Config.newInstance(applicationContext)
ButterKnife.bind(this)
setupBrightDisplay()
setupStroboscope()
}
private fun setupBrightDisplay() {
mBrightDisplaySwitch!!.isChecked = mConfig!!.brightDisplay
}
private fun setupStroboscope() {
mStroboscopeSwitch!!.isChecked = mConfig!!.stroboscope
}
@OnClick(R.id.settings_bright_display_holder)
fun handleBrightDisplay() {
mBrightDisplaySwitch!!.isChecked = !mBrightDisplaySwitch!!.isChecked
mConfig!!.brightDisplay = mBrightDisplaySwitch!!.isChecked
}
@OnClick(R.id.settings_stroboscope_holder)
fun handleStroboscope() {
mStroboscopeSwitch!!.isChecked = !mStroboscopeSwitch!!.isChecked
mConfig!!.stroboscope = mStroboscopeSwitch!!.isChecked
}
private fun restartActivity() {
TaskStackBuilder.create(applicationContext).addNextIntentWithParentStack(intent).startActivities()
}
companion object {
private var mConfig: Config? = null
}
}

View File

@ -0,0 +1,5 @@
package com.simplemobiletools.flashlight.activities
import com.simplemobiletools.commons.activities.BaseSimpleActivity
open class SimpleActivity : BaseSimpleActivity()

View File

@ -0,0 +1,13 @@
package com.simplemobiletools.flashlight.activities
import android.content.Intent
import android.os.Bundle
import android.support.v7.app.AppCompatActivity
class SplashActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
startActivity(Intent(this, MainActivity::class.java))
finish()
}
}

View File

@ -0,0 +1,137 @@
package com.simplemobiletools.flashlight.activities
import android.app.Activity
import android.appwidget.AppWidgetManager
import android.content.Context
import android.content.Intent
import android.graphics.Color
import android.graphics.PorterDuff
import android.os.Bundle
import android.support.v7.app.AppCompatActivity
import android.view.View
import android.widget.ImageView
import android.widget.RemoteViews
import android.widget.SeekBar
import butterknife.BindView
import butterknife.ButterKnife
import butterknife.OnClick
import com.simplemobiletools.commons.helpers.PREFS_KEY
import com.simplemobiletools.flashlight.R
import com.simplemobiletools.flashlight.helpers.MyWidgetProvider
import com.simplemobiletools.flashlight.helpers.WIDGET_COLOR
import yuku.ambilwarna.AmbilWarnaDialog
class WidgetConfigureActivity : AppCompatActivity() {
@BindView(R.id.config_widget_seekbar) internal var mWidgetSeekBar: SeekBar? = null
@BindView(R.id.config_widget_color) internal var mWidgetColorPicker: View? = null
@BindView(R.id.config_image) internal var mImage: ImageView? = null
private val seekbarChangeListener = object : SeekBar.OnSeekBarChangeListener {
override fun onProgressChanged(seekBar: SeekBar, progress: Int, fromUser: Boolean) {
mWidgetAlpha = progress.toFloat() / 100.toFloat()
updateColors()
}
override fun onStartTrackingTouch(seekBar: SeekBar) {
}
override fun onStopTrackingTouch(seekBar: SeekBar) {
}
}
public override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setResult(Activity.RESULT_CANCELED)
setContentView(R.layout.widget_config)
ButterKnife.bind(this)
initVariables()
val intent = intent
val extras = intent.extras
if (extras != null)
mWidgetId = extras.getInt(AppWidgetManager.EXTRA_APPWIDGET_ID, AppWidgetManager.INVALID_APPWIDGET_ID)
if (mWidgetId == AppWidgetManager.INVALID_APPWIDGET_ID)
finish()
}
private fun initVariables() {
val prefs = getSharedPreferences(PREFS_KEY, Context.MODE_PRIVATE)
mWidgetColor = prefs.getInt(WIDGET_COLOR, 1)
if (mWidgetColor == 1) {
mWidgetColor = resources.getColor(R.color.colorPrimary)
mWidgetAlpha = 1f
} else {
mWidgetAlpha = Color.alpha(mWidgetColor) / 255.toFloat()
}
mWidgetColorWithoutTransparency = Color.rgb(Color.red(mWidgetColor), Color.green(mWidgetColor), Color.blue(mWidgetColor))
mWidgetSeekBar!!.setOnSeekBarChangeListener(seekbarChangeListener)
mWidgetSeekBar!!.progress = (mWidgetAlpha * 100).toInt()
updateColors()
}
@OnClick(R.id.config_save)
fun saveConfig() {
val appWidgetManager = AppWidgetManager.getInstance(this)
val views = RemoteViews(packageName, R.layout.widget)
appWidgetManager.updateAppWidget(mWidgetId, views)
storeWidgetColors()
requestWidgetUpdate()
val resultValue = Intent()
resultValue.putExtra(AppWidgetManager.EXTRA_APPWIDGET_ID, mWidgetId)
setResult(Activity.RESULT_OK, resultValue)
finish()
}
@OnClick(R.id.config_widget_color)
fun pickBackgroundColor() {
val dialog = AmbilWarnaDialog(this, mWidgetColorWithoutTransparency, object : AmbilWarnaDialog.OnAmbilWarnaListener {
override fun onCancel(dialog: AmbilWarnaDialog) {}
override fun onOk(dialog: AmbilWarnaDialog, color: Int) {
mWidgetColorWithoutTransparency = color
updateColors()
}
})
dialog.show()
}
private fun storeWidgetColors() {
val prefs = getSharedPreferences(PREFS_KEY, Context.MODE_PRIVATE)
prefs.edit().putInt(WIDGET_COLOR, mWidgetColor).apply()
}
private fun requestWidgetUpdate() {
val intent = Intent(AppWidgetManager.ACTION_APPWIDGET_UPDATE, null, this, MyWidgetProvider::class.java)
intent.putExtra(AppWidgetManager.EXTRA_APPWIDGET_IDS, intArrayOf(mWidgetId))
sendBroadcast(intent)
}
private fun updateColors() {
mWidgetColor = adjustAlpha(mWidgetColorWithoutTransparency, mWidgetAlpha)
mWidgetColorPicker!!.setBackgroundColor(mWidgetColor)
mImage!!.background.mutate().setColorFilter(mWidgetColor, PorterDuff.Mode.SRC_IN)
}
private fun adjustAlpha(color: Int, factor: Float): Int {
val alpha = Math.round(Color.alpha(color) * factor)
val red = Color.red(color)
val green = Color.green(color)
val blue = Color.blue(color)
return Color.argb(alpha, red, green, blue)
}
companion object {
private var mWidgetAlpha: Float = 0.toFloat()
private var mWidgetId: Int = 0
private var mWidgetColor: Int = 0
private var mWidgetColorWithoutTransparency: Int = 0
}
}

View File

@ -0,0 +1,6 @@
package com.simplemobiletools.flashlight.extensions
import android.content.Context
import com.simplemobiletools.flashlight.helpers.Config
val Context.config: Config get() = Config.newInstance(this)

View File

@ -0,0 +1,7 @@
package com.simplemobiletools.flashlight.helpers
import com.squareup.otto.Bus
object BusProvider {
val instance = Bus()
}

View File

@ -0,0 +1,18 @@
package com.simplemobiletools.flashlight.helpers
import android.content.Context
import com.simplemobiletools.commons.helpers.BaseConfig
class Config(context: Context) : BaseConfig(context) {
companion object {
fun newInstance(context: Context) = Config(context)
}
var brightDisplay: Boolean
get() = prefs.getBoolean(BRIGHT_DISPLAY, true)
set(brightDisplay) = prefs.edit().putBoolean(BRIGHT_DISPLAY, brightDisplay).apply()
var stroboscope: Boolean
get() = prefs.getBoolean(STROBOSCOPE, true)
set(stroboscope) = prefs.edit().putBoolean(STROBOSCOPE, stroboscope).apply()
}

View File

@ -0,0 +1,5 @@
package com.simplemobiletools.flashlight.helpers
val BRIGHT_DISPLAY = "bright_display"
val STROBOSCOPE = "stroboscope"
val WIDGET_COLOR = "widget_color"

View File

@ -0,0 +1,46 @@
package com.simplemobiletools.flashlight.helpers
import android.annotation.TargetApi
import android.content.Context
import android.hardware.camera2.CameraAccessException
import android.hardware.camera2.CameraManager
import android.os.Build
import android.os.Handler
import android.util.Log
import com.simplemobiletools.flashlight.models.Events
import com.squareup.otto.Bus
internal class MarshmallowCamera @TargetApi(Build.VERSION_CODES.M)
constructor(private val mContext: Context) {
private val manager: CameraManager
private var cameraId: String? = null
init {
manager = mContext.getSystemService(Context.CAMERA_SERVICE) as CameraManager
try {
val list = manager.cameraIdList
cameraId = list[0]
} catch (ignored: CameraAccessException) {
}
}
@TargetApi(Build.VERSION_CODES.M)
fun toggleMarshmallowFlashlight(bus: Bus, enable: Boolean) {
try {
manager.setTorchMode(cameraId!!, enable)
} catch (e: CameraAccessException) {
Log.e(TAG, "toggle marshmallow flashlight " + e.message)
val mainRunnable = Runnable { bus.post(Events.CameraUnavailable()) }
Handler(mContext.mainLooper).post(mainRunnable)
}
}
companion object {
private val TAG = MyCameraImpl::class.java.simpleName
}
}

View File

@ -0,0 +1,271 @@
package com.simplemobiletools.flashlight.helpers
import android.content.Context
import android.graphics.SurfaceTexture
import android.hardware.Camera
import android.os.Handler
import android.util.Log
import com.simplemobiletools.flashlight.R
import com.simplemobiletools.flashlight.models.Events
import com.squareup.otto.Bus
import java.io.IOException
class MyCameraImpl(private val mContext: Context) {
companion object {
private val TAG = MyCameraImpl::class.java.simpleName
private var mCamera: Camera? = null
private var mParams: Camera.Parameters? = null
private var mBus: Bus? = null
private var mIsFlashlightOn: Boolean = false
private var mIsMarshmallow: Boolean = false
private var mShouldEnableFlashlight: Boolean = false
private var mStroboFrequency: Int = 0
}
private var mMarshmallowCamera: MarshmallowCamera? = null
@Volatile private var mShouldStroboscopeStop: Boolean = false
@Volatile private var mIsStroboscopeRunning: Boolean = false
private val isMarshmallow: Boolean
get() = android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.M
private val stroboscope = Runnable {
if (mIsStroboscopeRunning) {
return@Runnable
}
mShouldStroboscopeStop = false
mIsStroboscopeRunning = true
if (Utils.isNougat) {
while (!mShouldStroboscopeStop) {
try {
mMarshmallowCamera!!.toggleMarshmallowFlashlight(mBus!!, true)
Thread.sleep(mStroboFrequency.toLong())
mMarshmallowCamera!!.toggleMarshmallowFlashlight(mBus!!, false)
Thread.sleep(mStroboFrequency.toLong())
} catch (ignored: InterruptedException) {
mShouldStroboscopeStop = true
} catch (ignored: RuntimeException) {
mShouldStroboscopeStop = true
}
}
} else {
if (mCamera == null) {
initCamera()
}
val torchOn = mCamera!!.parameters
val torchOff = mCamera!!.parameters
torchOn.flashMode = Camera.Parameters.FLASH_MODE_TORCH
torchOff.flashMode = Camera.Parameters.FLASH_MODE_OFF
val dummy = SurfaceTexture(1)
try {
mCamera!!.setPreviewTexture(dummy)
} catch (e: IOException) {
Log.e(TAG, "setup stroboscope1 " + e.message)
}
mCamera!!.startPreview()
while (!mShouldStroboscopeStop) {
try {
mCamera!!.parameters = torchOn
Thread.sleep(mStroboFrequency.toLong())
mCamera!!.parameters = torchOff
Thread.sleep(mStroboFrequency.toLong())
} catch (ignored: InterruptedException) {
mShouldStroboscopeStop = true
} catch (ignored: RuntimeException) {
mShouldStroboscopeStop = true
}
}
try {
if (mCamera != null) {
mCamera!!.parameters = torchOff
if (!mShouldEnableFlashlight || mIsMarshmallow) {
mCamera!!.release()
mCamera = null
}
}
} catch (e: RuntimeException) {
Log.e(TAG, "setup stroboscope2 " + e.message)
}
}
mIsStroboscopeRunning = false
mShouldStroboscopeStop = false
if (mShouldEnableFlashlight) {
enableFlashlight()
mShouldEnableFlashlight = false
}
}
init {
mIsMarshmallow = isMarshmallow
mStroboFrequency = 1000
if (mBus == null) {
mBus = BusProvider.instance
mBus!!.register(this)
}
handleCameraSetup()
checkFlashlight()
}
fun toggleFlashlight() {
mIsFlashlightOn = !mIsFlashlightOn
handleCameraSetup()
}
fun setStroboFrequency(frequency: Int) {
mStroboFrequency = frequency
}
fun toggleStroboscope(): Boolean {
if (!mIsStroboscopeRunning)
disableFlashlight()
if (!Utils.isNougat) {
if (mCamera == null) {
initCamera()
}
if (mCamera == null) {
Utils.showToast(mContext, R.string.camera_error)
return false
}
}
if (mIsStroboscopeRunning) {
stopStroboscope()
} else {
Thread(stroboscope).start()
}
return true
}
fun stopStroboscope() {
mShouldStroboscopeStop = true
}
fun handleCameraSetup() {
if (mIsMarshmallow) {
setupMarshmallowCamera()
} else {
setupCamera()
}
checkFlashlight()
}
private fun setupMarshmallowCamera() {
if (mMarshmallowCamera == null) {
mMarshmallowCamera = MarshmallowCamera(mContext)
}
}
private fun setupCamera() {
if (mIsMarshmallow)
return
if (mCamera == null) {
initCamera()
}
}
private fun initCamera() {
try {
mCamera = Camera.open()
mParams = mCamera!!.parameters
mParams!!.flashMode = Camera.Parameters.FLASH_MODE_OFF
mCamera!!.parameters = mParams
} catch (e: Exception) {
Log.e(TAG, "setup mCamera " + e.message)
mBus!!.post(Events.CameraUnavailable())
}
}
fun checkFlashlight() {
if (mIsFlashlightOn) {
enableFlashlight()
} else {
disableFlashlight()
}
}
fun enableFlashlight() {
mShouldStroboscopeStop = true
if (mIsStroboscopeRunning) {
mShouldEnableFlashlight = true
return
}
mIsFlashlightOn = true
if (mIsMarshmallow) {
toggleMarshmallowFlashlight(true)
} else {
if (mCamera == null || mParams == null) {
return
}
mParams!!.flashMode = Camera.Parameters.FLASH_MODE_TORCH
mCamera!!.parameters = mParams
mCamera!!.startPreview()
}
val mainRunnable = Runnable { mBus!!.post(Events.StateChanged(true)) }
Handler(mContext.mainLooper).post(mainRunnable)
}
private fun disableFlashlight() {
if (mIsStroboscopeRunning) {
return
}
mIsFlashlightOn = false
if (mIsMarshmallow) {
toggleMarshmallowFlashlight(false)
} else {
if (mCamera == null || mParams == null) {
return
}
mParams!!.flashMode = Camera.Parameters.FLASH_MODE_OFF
mCamera!!.parameters = mParams
}
mBus!!.post(Events.StateChanged(false))
}
private fun toggleMarshmallowFlashlight(enable: Boolean) {
mMarshmallowCamera!!.toggleMarshmallowFlashlight(mBus!!, enable)
}
fun releaseCamera() {
if (mIsFlashlightOn) {
disableFlashlight()
}
if (mCamera != null) {
mCamera!!.release()
mCamera = null
}
if (mBus != null) {
mBus!!.unregister(this)
}
mIsFlashlightOn = false
mShouldStroboscopeStop = true
}
}

View File

@ -0,0 +1,152 @@
package com.simplemobiletools.flashlight.helpers
import android.app.PendingIntent
import android.appwidget.AppWidgetManager
import android.appwidget.AppWidgetProvider
import android.content.ComponentName
import android.content.Context
import android.content.Intent
import android.content.SharedPreferences
import android.graphics.Bitmap
import android.graphics.Color
import android.graphics.PorterDuff
import android.widget.RemoteViews
import com.simplemobiletools.commons.helpers.PREFS_KEY
import com.simplemobiletools.flashlight.R
import com.simplemobiletools.flashlight.models.Events
import com.squareup.otto.Bus
import com.squareup.otto.Subscribe
class MyWidgetProvider : AppWidgetProvider() {
override fun onUpdate(context: Context, appWidgetManager: AppWidgetManager, appWidgetIds: IntArray) {
initVariables(context)
appWidgetManager.updateAppWidget(appWidgetIds, mRemoteViews)
}
private fun initVariables(context: Context) {
mContext = context
val component = ComponentName(context, MyWidgetProvider::class.java)
mWidgetManager = AppWidgetManager.getInstance(context)
mWidgetIds = mWidgetManager!!.getAppWidgetIds(component)
val intent = Intent(context, MyWidgetProvider::class.java)
intent.action = TOGGLE
val pendingIntent = PendingIntent.getBroadcast(context, 0, intent, 0)
mRemoteViews = RemoteViews(context.packageName, R.layout.widget)
mRemoteViews!!.setOnClickPendingIntent(R.id.toggle_btn, pendingIntent)
mCameraImpl = MyCameraImpl(context)
val prefs = initPrefs(context)
val res = context.resources
val defaultColor = res.getColor(R.color.colorPrimary)
val selectedColor = prefs.getInt(WIDGET_COLOR, defaultColor)
val alpha = Color.alpha(selectedColor)
mColoredBmp = getColoredCircles(selectedColor, alpha)
mWhiteBmp = getColoredCircles(Color.WHITE, alpha)
mRemoteViews!!.setImageViewBitmap(R.id.toggle_btn, mWhiteBmp)
if (mBus == null) {
mBus = BusProvider.instance
}
registerBus()
}
override fun onReceive(context: Context, intent: Intent) {
val action = intent.action
if (action == TOGGLE) {
if (mCameraImpl == null || mBus == null) {
initVariables(context)
}
mCameraImpl!!.toggleFlashlight()
} else
super.onReceive(context, intent)
}
private fun getColoredCircles(color: Int, alpha: Int): Bitmap {
val drawable = mContext!!.resources.getDrawable(R.drawable.circles_small)
drawable.mutate().setColorFilter(color, PorterDuff.Mode.SRC_ATOP)
drawable.mutate().alpha = alpha
return Utils.drawableToBitmap(drawable)
}
fun enableFlashlight() {
mRemoteViews!!.setImageViewBitmap(R.id.toggle_btn, mColoredBmp)
for (widgetId in mWidgetIds!!) {
mWidgetManager!!.updateAppWidget(widgetId, mRemoteViews)
}
}
fun disableFlashlight() {
mRemoteViews!!.setImageViewBitmap(R.id.toggle_btn, mWhiteBmp)
for (widgetId in mWidgetIds!!) {
mWidgetManager!!.updateAppWidget(widgetId, mRemoteViews)
}
}
private fun initPrefs(context: Context): SharedPreferences {
return context.getSharedPreferences(PREFS_KEY, Context.MODE_PRIVATE)
}
@Subscribe
fun cameraUnavailable(event: Events.CameraUnavailable) {
if (mContext != null) {
Utils.showToast(mContext!!, R.string.camera_error)
disableFlashlight()
}
}
@Subscribe
fun stateChangedEvent(event: Events.StateChanged) {
if (event.isEnabled) {
enableFlashlight()
} else {
disableFlashlight()
}
}
override fun onDeleted(context: Context, appWidgetIds: IntArray) {
super.onDeleted(context, appWidgetIds)
unregisterBus()
releaseCamera(context)
}
private fun releaseCamera(context: Context) {
if (mCameraImpl == null)
initVariables(context)
mCameraImpl!!.releaseCamera()
}
private fun registerBus() {
try {
mBus!!.register(this)
} catch (ignored: Exception) {
}
}
private fun unregisterBus() {
try {
mBus!!.unregister(this)
} catch (ignored: Exception) {
}
}
companion object {
private val TOGGLE = "toggle"
private var mCameraImpl: MyCameraImpl? = null
private var mRemoteViews: RemoteViews? = null
private var mWidgetManager: AppWidgetManager? = null
private var mColoredBmp: Bitmap? = null
private var mWhiteBmp: Bitmap? = null
private var mBus: Bus? = null
private var mContext: Context? = null
private var mWidgetIds: IntArray? = null
}
}

View File

@ -0,0 +1,28 @@
package com.simplemobiletools.flashlight.helpers
import android.content.Context
import android.graphics.Bitmap
import android.graphics.Canvas
import android.graphics.drawable.Drawable
import android.os.Build
import android.widget.Toast
object Utils {
val isNougat: Boolean
get() = Build.VERSION.SDK_INT >= Build.VERSION_CODES.N
fun drawableToBitmap(drawable: Drawable): Bitmap {
val width = drawable.intrinsicWidth
val height = drawable.intrinsicHeight
val mutableBitmap = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888)
val canvas = Canvas(mutableBitmap)
drawable.setBounds(0, 0, width, height)
drawable.draw(canvas)
return mutableBitmap
}
fun showToast(context: Context, resId: Int) {
Toast.makeText(context, context.resources.getString(resId), Toast.LENGTH_SHORT).show()
}
}

View File

@ -0,0 +1,19 @@
package com.simplemobiletools.flashlight.models
class Events {
class StateChanged(isEnabled: Boolean) {
val isEnabled: Boolean
get() = mIsEnabled
init {
mIsEnabled = isEnabled
}
companion object {
private var mIsEnabled: Boolean = false
}
}
class CameraUnavailable
}

View File

@ -1,105 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<ScrollView
android:id="@+id/about_scrollview"
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:fillViewport="true">
<RelativeLayout
android:id="@+id/about_holder"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:paddingBottom="@dimen/activity_margin"
android:paddingLeft="@dimen/activity_margin"
android:paddingTop="@dimen/activity_margin">
<TextView
android:id="@+id/about_website"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:autoLink="web"
android:text="@string/website"/>
<TextView
android:id="@+id/about_email_label"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_below="@+id/about_website"
android:layout_marginTop="@dimen/activity_margin"
android:text="@string/email_label"/>
<TextView
android:id="@+id/about_email"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_below="@+id/about_email_label"
android:paddingBottom="@dimen/activity_margin"
android:text="@string/email"/>
<TextView
android:id="@+id/about_invite"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_below="@+id/about_email"
android:paddingBottom="@dimen/activity_margin"
android:paddingTop="@dimen/activity_margin"
android:text="@string/invite_friends_underlined"
android:textColor="@color/colorPrimary"/>
<TextView
android:id="@+id/about_rate_us"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_below="@+id/about_invite"
android:paddingBottom="@dimen/activity_margin"
android:paddingTop="@dimen/activity_margin"
android:text="@string/rate_us_underlined"
android:textColor="@color/colorPrimary"/>
<TextView
android:id="@+id/about_license"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_below="@+id/about_rate_us"
android:paddingBottom="@dimen/activity_margin"
android:paddingTop="@dimen/activity_margin"
android:text="@string/third_party_licences_underlined"
android:textColor="@color/colorPrimary"/>
<TextView
android:id="@+id/about_follow_us"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_below="@+id/about_license"
android:paddingBottom="@dimen/social_padding"
android:paddingTop="@dimen/activity_margin"
android:text="@string/follow_us"/>
<ImageView
android:id="@+id/about_facebook"
android:layout_width="@dimen/social_logo"
android:layout_height="@dimen/social_logo"
android:layout_below="@+id/about_follow_us"
android:src="@mipmap/facebook"/>
<ImageView
android:id="@+id/about_gplus"
android:layout_width="@dimen/social_logo"
android:layout_height="@dimen/social_logo"
android:layout_below="@+id/about_follow_us"
android:layout_marginLeft="@dimen/social_padding"
android:layout_toRightOf="@+id/about_facebook"
android:src="@mipmap/gplus"/>
<TextView
android:id="@+id/about_copyright"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_alignParentBottom="true"
android:layout_below="@+id/about_gplus"
android:gravity="center_horizontal|bottom"
android:paddingTop="@dimen/activity_margin"
android:text="v1.0\nCopyright © Simple Mobile Tools 2016"/>
</RelativeLayout>
</ScrollView>

View File

@ -1,63 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<ScrollView
android:id="@+id/license_holder"
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent">
<LinearLayout
android:id="@+id/license"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
android:padding="@dimen/activity_margin">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/notice"/>
<TextView
android:id="@+id/license_butterknife_title"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:paddingTop="@dimen/activity_margin"
android:text="@string/butterknife_title"
android:textColor="@color/colorPrimary"/>
<TextView
android:id="@+id/license_butterknife_text"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/butterknife_text"/>
<TextView
android:id="@+id/license_ambilwarna_title"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:paddingTop="@dimen/activity_margin"
android:text="@string/ambilwarna_title"
android:textColor="@color/colorPrimary"/>
<TextView
android:id="@+id/license_ambilwarna_text"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/ambilwarna_text"/>
<TextView
android:id="@+id/license_otto_title"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:paddingTop="@dimen/activity_margin"
android:text="@string/otto_title"
android:textColor="@color/colorPrimary"/>
<TextView
android:id="@+id/license_otto_text"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/otto_text"/>
</LinearLayout>
</ScrollView>

View File

@ -11,32 +11,6 @@
android:layout_height="wrap_content"
android:orientation="vertical">
<RelativeLayout
android:id="@+id/settings_dark_theme_holder"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="@dimen/settings_padding"
android:background="?attr/selectableItemBackground"
android:padding="@dimen/activity_margin">
<TextView
android:id="@+id/settings_dark_theme_label"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerVertical="true"
android:paddingLeft="@dimen/settings_padding"
android:text="@string/dark_theme"/>
<android.support.v7.widget.SwitchCompat
android:id="@+id/settings_dark_theme"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentRight="true"
android:background="@null"
android:clickable="false"/>
</RelativeLayout>
<RelativeLayout
android:id="@+id/settings_bright_display_holder"
android:layout_width="match_parent"