mirror of
https://github.com/xdsopl/robot36.git
synced 2026-01-08 01:00:00 +01:00
added storing of scope and sharing
This commit is contained in:
parent
d6ee2a3a43
commit
fff69bd4fe
|
|
@ -2,7 +2,18 @@
|
|||
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:tools="http://schemas.android.com/tools">
|
||||
|
||||
<queries>
|
||||
<intent>
|
||||
<action android:name="android.intent.action.SEND" />
|
||||
<data android:mimeType="image/png" />
|
||||
</intent>
|
||||
</queries>
|
||||
|
||||
<uses-permission android:name="android.permission.RECORD_AUDIO" />
|
||||
<uses-permission
|
||||
android:name="android.permission.WRITE_EXTERNAL_STORAGE"
|
||||
android:maxSdkVersion="28" />
|
||||
|
||||
<application
|
||||
android:allowBackup="true"
|
||||
android:dataExtractionRules="@xml/data_extraction_rules"
|
||||
|
|
|
|||
|
|
@ -7,7 +7,10 @@ Copyright 2024 Ahmet Inan <xdsopl@gmail.com>
|
|||
package xdsopl.robot36;
|
||||
|
||||
import android.Manifest;
|
||||
import android.content.ContentResolver;
|
||||
import android.content.ContentValues;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.content.SharedPreferences;
|
||||
import android.content.pm.PackageManager;
|
||||
import android.content.res.Configuration;
|
||||
|
|
@ -15,25 +18,40 @@ import android.graphics.Bitmap;
|
|||
import android.media.AudioFormat;
|
||||
import android.media.AudioRecord;
|
||||
import android.media.MediaRecorder;
|
||||
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 android.view.Gravity;
|
||||
import android.view.Menu;
|
||||
import android.view.MenuItem;
|
||||
import android.widget.ImageView;
|
||||
import android.widget.Toast;
|
||||
|
||||
import androidx.activity.EdgeToEdge;
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.appcompat.app.AlertDialog;
|
||||
import androidx.appcompat.app.AppCompatActivity;
|
||||
import androidx.appcompat.app.AppCompatDelegate;
|
||||
import androidx.appcompat.widget.ShareActionProvider;
|
||||
import androidx.core.app.ActivityCompat;
|
||||
import androidx.core.content.ContextCompat;
|
||||
import androidx.core.graphics.Insets;
|
||||
import androidx.core.view.MenuItemCompat;
|
||||
import androidx.core.view.ViewCompat;
|
||||
import androidx.core.view.WindowInsetsCompat;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.text.SimpleDateFormat;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
|
||||
public class MainActivity extends AppCompatActivity {
|
||||
|
||||
|
|
@ -336,6 +354,8 @@ public class MainActivity extends AppCompatActivity {
|
|||
} else {
|
||||
initAudioRecord();
|
||||
}
|
||||
if (Build.VERSION.SDK_INT <= Build.VERSION_CODES.P && ContextCompat.checkSelfPermission(this, Manifest.permission.WRITE_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED)
|
||||
permissions.add(Manifest.permission.WRITE_EXTERNAL_STORAGE);
|
||||
if (!permissions.isEmpty())
|
||||
ActivityCompat.requestPermissions(this, permissions.toArray(new String[0]), permissionID);
|
||||
}
|
||||
|
|
@ -361,6 +381,10 @@ public class MainActivity extends AppCompatActivity {
|
|||
@Override
|
||||
public boolean onOptionsItemSelected(MenuItem item) {
|
||||
int id = item.getItemId();
|
||||
if (id == R.id.action_store_scope) {
|
||||
storeBitmap(scopeBitmap);
|
||||
return true;
|
||||
}
|
||||
if (id == R.id.action_set_record_rate_8000) {
|
||||
setRecordRate(8000);
|
||||
return true;
|
||||
|
|
@ -494,6 +518,81 @@ public class MainActivity extends AppCompatActivity {
|
|||
builder.show();
|
||||
}
|
||||
|
||||
void storeBitmap(Bitmap bitmap) {
|
||||
Date date = new Date();
|
||||
String name = new SimpleDateFormat("yyyyMMdd_HHmmss", Locale.US).format(date);
|
||||
name += ".png";
|
||||
String title = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss", Locale.US).format(date);
|
||||
ContentValues values = new ContentValues();
|
||||
File dir;
|
||||
if (Build.VERSION.SDK_INT <= Build.VERSION_CODES.P) {
|
||||
dir = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_PICTURES);
|
||||
if (!dir.exists() && !dir.mkdirs()) {
|
||||
showToast(R.string.creating_picture_directory_failed);
|
||||
return;
|
||||
}
|
||||
File file;
|
||||
try {
|
||||
file = new File(dir, name);
|
||||
FileOutputStream stream = new FileOutputStream(file);
|
||||
bitmap.compress(Bitmap.CompressFormat.PNG, 100, stream);
|
||||
stream.close();
|
||||
} catch (IOException e) {
|
||||
showToast(R.string.creating_picture_file_failed);
|
||||
return;
|
||||
}
|
||||
values.put(MediaStore.Images.ImageColumns.DATA, file.toString());
|
||||
} else {
|
||||
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 (uri == null) {
|
||||
showToast(R.string.storing_picture_failed);
|
||||
return;
|
||||
}
|
||||
if (Build.VERSION.SDK_INT > Build.VERSION_CODES.P) {
|
||||
try {
|
||||
ParcelFileDescriptor descriptor = getContentResolver().openFileDescriptor(uri, "w");
|
||||
if (descriptor == null) {
|
||||
showToast(R.string.storing_picture_failed);
|
||||
return;
|
||||
}
|
||||
FileOutputStream stream = new FileOutputStream(descriptor.getFileDescriptor());
|
||||
bitmap.compress(Bitmap.CompressFormat.PNG, 100, stream);
|
||||
stream.close();
|
||||
descriptor.close();
|
||||
} catch (IOException e) {
|
||||
showToast(R.string.storing_picture_failed);
|
||||
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");
|
||||
ShareActionProvider share = (ShareActionProvider) MenuItemCompat.getActionProvider(menu.findItem(R.id.menu_item_share));
|
||||
if (share != null)
|
||||
share.setShareIntent(intent);
|
||||
showToast(name);
|
||||
}
|
||||
|
||||
private void showToast(String message) {
|
||||
Toast toast = Toast.makeText(getApplicationContext(), message, Toast.LENGTH_SHORT);
|
||||
toast.setGravity(Gravity.CENTER_HORIZONTAL | Gravity.CENTER_VERTICAL, 0, 0);
|
||||
toast.show();
|
||||
}
|
||||
|
||||
private void showToast(int id) {
|
||||
showToast(getString(id));
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onResume() {
|
||||
startListening();
|
||||
|
|
|
|||
5
app/src/main/res/drawable/baseline_save_alt_24.xml
Normal file
5
app/src/main/res/drawable/baseline_save_alt_24.xml
Normal file
|
|
@ -0,0 +1,5 @@
|
|||
<vector xmlns:android="http://schemas.android.com/apk/res/android" android:height="24dp" android:tint="#000000" android:viewportHeight="24" android:viewportWidth="24" android:width="24dp">
|
||||
|
||||
<path android:fillColor="@android:color/white" android:pathData="M19,12v7L5,19v-7L3,12v7c0,1.1 0.9,2 2,2h14c1.1,0 2,-0.9 2,-2v-7h-2zM13,12.67l2.59,-2.58L17,11.5l-5,5 -5,-5 1.41,-1.41L11,12.67L11,3h2z"/>
|
||||
|
||||
</vector>
|
||||
|
|
@ -1,7 +1,20 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<menu xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
tools:context="xdsopl.robot36.MainActivity">
|
||||
<item
|
||||
android:id="@+id/action_store_scope"
|
||||
android:title="@string/store_scope"
|
||||
android:icon="@drawable/baseline_save_alt_24"
|
||||
app:iconTint="@color/tint"
|
||||
app:showAsAction="always"
|
||||
tools:ignore="AlwaysShowAction" />
|
||||
<item
|
||||
android:id="@+id/menu_item_share"
|
||||
android:title="@string/action_share"
|
||||
app:actionProviderClass="androidx.appcompat.widget.ShareActionProvider"
|
||||
app:showAsAction="always" />
|
||||
<item android:title="@string/audio_settings">
|
||||
<menu>
|
||||
<item android:title="@string/sample_rate">
|
||||
|
|
|
|||
|
|
@ -1,5 +1,7 @@
|
|||
<resources>
|
||||
<string name="app_name">Robot36</string>
|
||||
<string name="action_share">Share</string>
|
||||
<string name="store_scope">Store Scope</string>
|
||||
<string name="listening">Listening</string>
|
||||
<string name="audio_settings">Audio Settings</string>
|
||||
<string name="sample_rate">Sample Rate</string>
|
||||
|
|
@ -24,6 +26,9 @@
|
|||
<string name="audio_setup_failed">Audio setup failed</string>
|
||||
<string name="audio_permission_denied">Audio permission denied</string>
|
||||
<string name="audio_recording_error">Audio recording error</string>
|
||||
<string name="creating_picture_directory_failed">Creating picture directory failed</string>
|
||||
<string name="creating_picture_file_failed">Creating picture file failed</string>
|
||||
<string name="storing_picture_failed">Storing picture failed</string>
|
||||
<string name="scope_description">Decoded SSTV picture</string>
|
||||
<string name="freq_plot_description">Frequency plot</string>
|
||||
<string name="peak_meter_description">Peak audio signal level</string>
|
||||
|
|
|
|||
Loading…
Reference in a new issue