kopia lustrzana https://github.com/xdsopl/robot36
498 wiersze
18 KiB
Java
498 wiersze
18 KiB
Java
|
|
/*
|
|
Copyright 2014 Ahmet Inan <xdsopl@googlemail.com>
|
|
|
|
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 xdsopl.robot36;
|
|
|
|
import android.Manifest;
|
|
import android.app.AlertDialog;
|
|
import android.app.NotificationChannel;
|
|
import android.app.NotificationManager;
|
|
import android.app.PendingIntent;
|
|
import android.content.ContentResolver;
|
|
import android.content.ContentValues;
|
|
import android.content.Context;
|
|
import android.content.DialogInterface;
|
|
import android.content.Intent;
|
|
import android.content.pm.PackageManager;
|
|
import android.content.res.Configuration;
|
|
import android.graphics.Bitmap;
|
|
import android.graphics.BitmapFactory;
|
|
import android.net.Uri;
|
|
import android.os.Build;
|
|
import android.os.Bundle;
|
|
import android.os.Environment;
|
|
import android.os.ParcelFileDescriptor;
|
|
import android.provider.MediaStore;
|
|
import androidx.core.app.ActivityCompat;
|
|
import androidx.core.app.NotificationCompat;
|
|
import androidx.core.content.ContextCompat;
|
|
import androidx.core.view.MenuItemCompat;
|
|
import androidx.appcompat.app.AppCompatActivity;
|
|
import androidx.appcompat.widget.ShareActionProvider;
|
|
import android.util.Log;
|
|
import android.view.Gravity;
|
|
import android.view.Menu;
|
|
import android.view.MenuItem;
|
|
import android.view.View;
|
|
import android.widget.LinearLayout;
|
|
import android.widget.Toast;
|
|
|
|
import java.io.File;
|
|
import java.io.FileOutputStream;
|
|
import java.io.IOException;
|
|
import java.text.SimpleDateFormat;
|
|
import java.util.ArrayList;
|
|
import java.util.Date;
|
|
import java.util.List;
|
|
|
|
public class MainActivity extends AppCompatActivity {
|
|
private Decoder decoder;
|
|
private ImageView image;
|
|
private Bitmap bitmap;
|
|
private NotificationManager manager;
|
|
private ShareActionProvider share;
|
|
private int notifyID = 1;
|
|
private int permissionsID = 2;
|
|
private static final String channelID = "Robot36";
|
|
private boolean enableAnalyzer = true;
|
|
private Menu menu;
|
|
|
|
private void showNotification() {
|
|
Intent intent = new Intent(this, MainActivity.class);
|
|
int flags = 0;
|
|
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S)
|
|
flags = PendingIntent.FLAG_IMMUTABLE;
|
|
PendingIntent pending = PendingIntent.getActivity(this, 0, intent, flags);
|
|
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
|
|
NotificationChannel channel = manager.getNotificationChannel(channelID);
|
|
if (channel == null) {
|
|
channel = new NotificationChannel(channelID, getString(R.string.app_name), NotificationManager.IMPORTANCE_LOW);
|
|
channel.setDescription(getString(R.string.decoder_running));
|
|
manager.createNotificationChannel(channel);
|
|
}
|
|
}
|
|
NotificationCompat.Builder builder = new NotificationCompat.Builder(this, channelID)
|
|
.setSmallIcon(R.drawable.ic_notification)
|
|
.setLargeIcon(BitmapFactory.decodeResource(getResources(), R.drawable.ic_launcher))
|
|
.setContentTitle(getString(R.string.app_name))
|
|
.setContentText(getString(R.string.decoder_running))
|
|
.setContentIntent(pending)
|
|
.setOngoing(true);
|
|
manager.notify(notifyID, builder.build());
|
|
}
|
|
|
|
void updateTitle(final String newTitle)
|
|
{
|
|
if (getTitle() != newTitle) {
|
|
runOnUiThread(new Runnable() {
|
|
@Override
|
|
public void run() {
|
|
setTitle(newTitle);
|
|
}
|
|
});
|
|
}
|
|
}
|
|
|
|
void storeBitmap(Bitmap image) {
|
|
bitmap = image;
|
|
runOnUiThread(new Runnable() {
|
|
@Override
|
|
public void run() {
|
|
Date date = new Date();
|
|
String name = new SimpleDateFormat("yyyyMMdd_HHmmss").format(date);
|
|
String title = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(date);
|
|
ContentValues values = new ContentValues();
|
|
File dir;
|
|
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.Q) {
|
|
dir = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_PICTURES);
|
|
if (!dir.exists())
|
|
dir.mkdirs();
|
|
File file;
|
|
try {
|
|
file = File.createTempFile(name + "_", ".png", dir);
|
|
name = file.getName();
|
|
} catch (IOException ignore) {
|
|
return;
|
|
}
|
|
FileOutputStream stream;
|
|
try {
|
|
stream = new FileOutputStream(file);
|
|
} catch (IOException ignore) {
|
|
return;
|
|
}
|
|
bitmap.compress(Bitmap.CompressFormat.PNG, 100, stream);
|
|
try {
|
|
stream.close();
|
|
} catch (IOException ignore) {
|
|
return;
|
|
}
|
|
values.put(MediaStore.Images.ImageColumns.DATA, file.toString());
|
|
} else {
|
|
name += ".png";
|
|
values.put(MediaStore.Images.Media.DISPLAY_NAME, name);
|
|
values.put(MediaStore.Images.Media.RELATIVE_PATH, "Pictures/");
|
|
values.put(MediaStore.Images.Media.IS_PENDING, 1);
|
|
}
|
|
values.put(MediaStore.Images.ImageColumns.TITLE, title);
|
|
values.put(MediaStore.Images.ImageColumns.MIME_TYPE, "image/png");
|
|
ContentResolver resolver = getContentResolver();
|
|
Uri uri = resolver.insert(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, values);
|
|
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
|
|
FileOutputStream stream;
|
|
try {
|
|
ParcelFileDescriptor descriptor = getContentResolver().openFileDescriptor(uri,"w");
|
|
stream = new FileOutputStream(descriptor.getFileDescriptor());
|
|
} catch (IOException ignore) {
|
|
return;
|
|
}
|
|
bitmap.compress(Bitmap.CompressFormat.PNG, 100, stream);
|
|
try {
|
|
stream.close();
|
|
} catch (IOException ignore) {
|
|
return;
|
|
}
|
|
values.clear();
|
|
values.put(MediaStore.Images.Media.IS_PENDING, 0);
|
|
resolver.update(uri, values, null, null);
|
|
}
|
|
Intent intent = new Intent(Intent.ACTION_SEND);
|
|
intent.putExtra(Intent.EXTRA_STREAM, uri);
|
|
intent.setType("image/png");
|
|
share.setShareIntent(intent);
|
|
Toast toast = Toast.makeText(getApplicationContext(), name, Toast.LENGTH_SHORT);
|
|
toast.setGravity(Gravity.CENTER_HORIZONTAL | Gravity.CENTER_VERTICAL, 0, 0);
|
|
toast.show();
|
|
}
|
|
});
|
|
}
|
|
|
|
@Override
|
|
protected void onCreate(Bundle savedInstanceState) {
|
|
super.onCreate(savedInstanceState);
|
|
setContentView(R.layout.activity_main);
|
|
changeLayoutOrientation(getResources().getConfiguration());
|
|
image = (ImageView)findViewById(R.id.image);
|
|
manager = (NotificationManager)getSystemService(Context.NOTIFICATION_SERVICE);
|
|
startDecoder();
|
|
}
|
|
|
|
private void updateMenuButtons() {
|
|
if (menu != null) {
|
|
if (decoder != null) {
|
|
menu.findItem(R.id.action_toggle_decoder).setIcon(ContextCompat.getDrawable(this, android.R.drawable.ic_media_pause));
|
|
menu.setGroupEnabled(R.id.group_decoder, true);
|
|
} else {
|
|
menu.findItem(R.id.action_toggle_decoder).setIcon(ContextCompat.getDrawable(this, android.R.drawable.ic_media_play));
|
|
menu.setGroupEnabled(R.id.group_decoder, false);
|
|
}
|
|
}
|
|
}
|
|
|
|
protected void stopDecoder() {
|
|
if (decoder == null)
|
|
return;
|
|
decoder.destroy();
|
|
decoder = null;
|
|
manager.cancel(notifyID);
|
|
updateMenuButtons();
|
|
}
|
|
|
|
private Intent createEmailIntent(final String subject, final String text) {
|
|
Intent intent = new Intent(Intent.ACTION_SEND);
|
|
intent.setType("text/email");
|
|
intent.putExtra(Intent.EXTRA_EMAIL, new String[]{ getString(R.string.email_address) });
|
|
intent.putExtra(Intent.EXTRA_SUBJECT, subject);
|
|
intent.putExtra(Intent.EXTRA_TEXT, text);
|
|
return intent;
|
|
}
|
|
|
|
private void showErrorMessage(final String title, final String shortText, final String longText) {
|
|
AlertDialog.Builder builder = new AlertDialog.Builder(this);
|
|
builder.setTitle(title);
|
|
builder.setMessage(shortText);
|
|
builder.setNeutralButton(getString(R.string.btn_ok), null);
|
|
builder.setPositiveButton(getString(R.string.btn_send_email), new DialogInterface.OnClickListener() {
|
|
@Override
|
|
public void onClick(DialogInterface dialog, int which) {
|
|
String version = " " + BuildConfig.VERSION_NAME;
|
|
String device = " (" + Build.MANUFACTURER + " " + Build.BRAND + " " + Build.MODEL + " " + Build.VERSION.RELEASE + ")";
|
|
Intent intent = createEmailIntent(getString(R.string.email_subject) + version + device, longText);
|
|
startActivity(Intent.createChooser(intent, getString(R.string.chooser_title)));
|
|
}
|
|
});
|
|
builder.show();
|
|
}
|
|
|
|
private void showPrivacyPolicy() {
|
|
AlertDialog.Builder builder = new AlertDialog.Builder(this);
|
|
builder.setTitle(getString(R.string.privacy_policy));
|
|
builder.setMessage(getString(R.string.privacy_policy_text));
|
|
builder.setNeutralButton(getString(R.string.btn_ok), null);
|
|
builder.show();
|
|
}
|
|
|
|
@Override
|
|
public void onRequestPermissionsResult(int requestCode, String permissions[], int[] grantResults) {
|
|
if (requestCode != permissionsID)
|
|
return;
|
|
for (int result : grantResults)
|
|
if (result != PackageManager.PERMISSION_GRANTED)
|
|
return;
|
|
startDecoder();
|
|
}
|
|
|
|
private boolean permissionsGranted() {
|
|
List<String> permissions = new ArrayList<>();
|
|
if (ContextCompat.checkSelfPermission(this, Manifest.permission.RECORD_AUDIO) != PackageManager.PERMISSION_GRANTED)
|
|
permissions.add(Manifest.permission.RECORD_AUDIO);
|
|
if (ContextCompat.checkSelfPermission(this, Manifest.permission.WRITE_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED)
|
|
permissions.add(Manifest.permission.WRITE_EXTERNAL_STORAGE);
|
|
if (permissions.isEmpty())
|
|
return true;
|
|
ActivityCompat.requestPermissions(this, permissions.toArray(new String[permissions.size()]), permissionsID);
|
|
return false;
|
|
}
|
|
|
|
protected void startDecoder() {
|
|
if (decoder != null)
|
|
return;
|
|
if (!permissionsGranted())
|
|
return;
|
|
try {
|
|
decoder = new Decoder(this,
|
|
(SpectrumView) findViewById(R.id.spectrum),
|
|
(SpectrumView) findViewById(R.id.spectrogram),
|
|
(ImageView) findViewById(R.id.image),
|
|
(VUMeterView) findViewById(R.id.meter)
|
|
);
|
|
decoder.enable_analyzer(enableAnalyzer);
|
|
showNotification();
|
|
updateMenuButtons();
|
|
} catch (Exception e) {
|
|
showErrorMessage(getString(R.string.decoder_error), e.getMessage(), Log.getStackTraceString(e));
|
|
}
|
|
}
|
|
|
|
protected void toggleDecoder() {
|
|
if (decoder == null)
|
|
startDecoder();
|
|
else
|
|
stopDecoder();
|
|
}
|
|
|
|
@Override
|
|
protected void onDestroy () {
|
|
stopDecoder();
|
|
super.onDestroy();
|
|
}
|
|
|
|
@Override
|
|
protected void onPause() {
|
|
if (decoder != null)
|
|
decoder.pause();
|
|
super.onPause();
|
|
}
|
|
|
|
@Override
|
|
protected void onResume() {
|
|
if (decoder != null)
|
|
decoder.resume();
|
|
super.onResume();
|
|
}
|
|
|
|
@Override
|
|
public boolean onCreateOptionsMenu(Menu menu) {
|
|
getMenuInflater().inflate(R.menu.menu_main, menu);
|
|
this.menu = menu;
|
|
updateMenuButtons();
|
|
MenuItem item = menu.findItem(R.id.menu_item_share);
|
|
share = (ShareActionProvider)MenuItemCompat.getActionProvider(item);
|
|
return true;
|
|
}
|
|
|
|
@Override
|
|
public void onConfigurationChanged(Configuration config) {
|
|
super.onConfigurationChanged(config);
|
|
changeLayoutOrientation(config);
|
|
}
|
|
|
|
private void changeLayoutOrientation(Configuration config) {
|
|
boolean horizontal = config.orientation == Configuration.ORIENTATION_LANDSCAPE;
|
|
View analysis = findViewById(R.id.analysis);
|
|
analysis.setVisibility(enableAnalyzer ? View.VISIBLE : View.GONE);
|
|
analysis.setLayoutParams(
|
|
new LinearLayout.LayoutParams(
|
|
LinearLayout.LayoutParams.MATCH_PARENT,
|
|
LinearLayout.LayoutParams.MATCH_PARENT, horizontal ? 1.0f : 10.0f));
|
|
int content_orientation = horizontal ? LinearLayout.HORIZONTAL : LinearLayout.VERTICAL;
|
|
((LinearLayout)findViewById(R.id.content)).setOrientation(content_orientation);
|
|
int analysis_orientation = horizontal ? LinearLayout.VERTICAL : LinearLayout.HORIZONTAL;
|
|
((LinearLayout)findViewById(R.id.analysis)).setOrientation(analysis_orientation);
|
|
}
|
|
|
|
@Override
|
|
public boolean onOptionsItemSelected(MenuItem item) {
|
|
int id = item.getItemId();
|
|
if (id == R.id.action_toggle_decoder) {
|
|
toggleDecoder();
|
|
return true;
|
|
}
|
|
if (id == R.id.action_save_image) {
|
|
storeBitmap(image.bitmap);
|
|
return true;
|
|
}
|
|
if (id == R.id.action_clear_image) {
|
|
decoder.clear_image();
|
|
return true;
|
|
}
|
|
if (id == R.id.action_sharpest_image) {
|
|
decoder.adjust_blur(-3);
|
|
return true;
|
|
}
|
|
if (id == R.id.action_sharper_image) {
|
|
decoder.adjust_blur(-2);
|
|
return true;
|
|
}
|
|
if (id == R.id.action_sharp_image) {
|
|
decoder.adjust_blur(-1);
|
|
return true;
|
|
}
|
|
if (id == R.id.action_neutral_image) {
|
|
decoder.adjust_blur(0);
|
|
return true;
|
|
}
|
|
if (id == R.id.action_soft_image) {
|
|
decoder.adjust_blur(1);
|
|
return true;
|
|
}
|
|
if (id == R.id.action_softer_image) {
|
|
decoder.adjust_blur(2);
|
|
return true;
|
|
}
|
|
if (id == R.id.action_softest_image) {
|
|
decoder.adjust_blur(3);
|
|
return true;
|
|
}
|
|
if (id == R.id.action_toggle_scaling) {
|
|
decoder.toggle_scaling();
|
|
return true;
|
|
}
|
|
if (id == R.id.action_toggle_debug) {
|
|
decoder.toggle_debug();
|
|
return true;
|
|
}
|
|
if (id == R.id.action_auto_mode) {
|
|
decoder.auto_mode();
|
|
return true;
|
|
}
|
|
if (id == R.id.action_toggle_analyzer) {
|
|
decoder.enable_analyzer(enableAnalyzer ^= true);
|
|
changeLayoutOrientation(getResources().getConfiguration());
|
|
return true;
|
|
}
|
|
if (id == R.id.action_slow_update_rate) {
|
|
decoder.setUpdateRate(0);
|
|
return true;
|
|
}
|
|
if (id == R.id.action_normal_update_rate) {
|
|
decoder.setUpdateRate(1);
|
|
return true;
|
|
}
|
|
if (id == R.id.action_fast_update_rate) {
|
|
decoder.setUpdateRate(2);
|
|
return true;
|
|
}
|
|
if (id == R.id.action_faster_update_rate) {
|
|
decoder.setUpdateRate(3);
|
|
return true;
|
|
}
|
|
if (id == R.id.action_fastest_update_rate) {
|
|
decoder.setUpdateRate(4);
|
|
return true;
|
|
}
|
|
if (id == R.id.action_raw_mode) {
|
|
decoder.raw_mode();
|
|
return true;
|
|
}
|
|
if (id == R.id.action_robot36_mode) {
|
|
decoder.robot36_mode();
|
|
return true;
|
|
}
|
|
if (id == R.id.action_robot72_mode) {
|
|
decoder.robot72_mode();
|
|
return true;
|
|
}
|
|
if (id == R.id.action_martin1_mode) {
|
|
decoder.martin1_mode();
|
|
return true;
|
|
}
|
|
if (id == R.id.action_martin2_mode) {
|
|
decoder.martin2_mode();
|
|
return true;
|
|
}
|
|
if (id == R.id.action_scottie1_mode) {
|
|
decoder.scottie1_mode();
|
|
return true;
|
|
}
|
|
if (id == R.id.action_scottie2_mode) {
|
|
decoder.scottie2_mode();
|
|
return true;
|
|
}
|
|
if (id == R.id.action_scottieDX_mode) {
|
|
decoder.scottieDX_mode();
|
|
return true;
|
|
}
|
|
if (id == R.id.action_wraaseSC2_180_mode) {
|
|
decoder.wraaseSC2_180_mode();
|
|
return true;
|
|
}
|
|
if (id == R.id.action_pd50_mode) {
|
|
decoder.pd50_mode();
|
|
return true;
|
|
}
|
|
if (id == R.id.action_pd90_mode) {
|
|
decoder.pd90_mode();
|
|
return true;
|
|
}
|
|
if (id == R.id.action_pd120_mode) {
|
|
decoder.pd120_mode();
|
|
return true;
|
|
}
|
|
if (id == R.id.action_pd160_mode) {
|
|
decoder.pd160_mode();
|
|
return true;
|
|
}
|
|
if (id == R.id.action_pd180_mode) {
|
|
decoder.pd180_mode();
|
|
return true;
|
|
}
|
|
if (id == R.id.action_pd240_mode) {
|
|
decoder.pd240_mode();
|
|
return true;
|
|
}
|
|
if (id == R.id.action_pd290_mode) {
|
|
decoder.pd290_mode();
|
|
return true;
|
|
}
|
|
if (id == R.id.action_privacy_policy) {
|
|
showPrivacyPolicy();
|
|
return true;
|
|
}
|
|
return super.onOptionsItemSelected(item);
|
|
}
|
|
}
|