Add permission check

pull/123/head
FongMi 3 years ago
parent 9109e262da
commit ca5b00964b
  1. 1
      app/build.gradle
  2. 12
      app/src/leanback/java/com/fongmi/android/tv/ui/activity/SearchActivity.java
  3. 21
      app/src/leanback/java/com/fongmi/android/tv/ui/activity/SettingActivity.java
  4. 24
      app/src/leanback/java/com/fongmi/android/tv/ui/custom/CustomMic.java
  5. 2
      app/src/leanback/java/com/fongmi/android/tv/ui/custom/dialog/ConfigDialog.java
  6. 12
      app/src/main/java/com/fongmi/android/tv/event/ServerEvent.java
  7. 5
      app/src/main/java/com/fongmi/android/tv/server/Nano.java
  8. 28
      app/src/main/java/com/fongmi/android/tv/utils/Utils.java
  9. 6
      app/src/main/res/raw/script.js

@ -76,6 +76,7 @@ dependencies {
implementation 'com.google.android.material:material:1.7.0'
implementation 'com.google.code.gson:gson:2.10'
implementation 'com.google.zxing:core:3.5.1'
implementation 'com.guolindev.permissionx:permissionx:1.7.1'
implementation 'com.squareup.okhttp3:okhttp:5.0.0-alpha.10'
implementation 'me.jessyan:autosize:1.2.1'
implementation 'org.greenrobot:eventbus:3.3.1'

@ -8,9 +8,6 @@ import android.view.KeyEvent;
import android.view.View;
import android.view.inputmethod.EditorInfo;
import androidx.activity.result.ActivityResultCallback;
import androidx.activity.result.ActivityResultLauncher;
import androidx.activity.result.contract.ActivityResultContracts;
import androidx.annotation.NonNull;
import androidx.viewbinding.ViewBinding;
@ -45,13 +42,6 @@ public class SearchActivity extends BaseActivity implements WordAdapter.OnClickL
activity.startActivity(new Intent(activity, SearchActivity.class));
}
private final ActivityResultLauncher<String> launcher = registerForActivityResult(new ActivityResultContracts.RequestPermission(), new ActivityResultCallback<>() {
@Override
public void onActivityResult(Boolean isGranted) {
if (isGranted) mBinding.mic.start();
}
});
@Override
protected ViewBinding getBinding() {
return mBinding = ActivitySearchBinding.inflate(getLayoutInflater());
@ -77,7 +67,7 @@ public class SearchActivity extends BaseActivity implements WordAdapter.OnClickL
else getSuggest(s.toString());
}
});
mBinding.mic.setListener(launcher, new CustomListener() {
mBinding.mic.setListener(this, new CustomListener() {
@Override
public void onEndOfSpeech() {
mBinding.mic.stop();

@ -19,12 +19,14 @@ import com.fongmi.android.tv.BuildConfig;
import com.fongmi.android.tv.R;
import com.fongmi.android.tv.api.ApiConfig;
import com.fongmi.android.tv.api.LiveConfig;
import com.fongmi.android.tv.api.Updater;
import com.fongmi.android.tv.api.WallConfig;
import com.fongmi.android.tv.bean.Config;
import com.fongmi.android.tv.bean.Live;
import com.fongmi.android.tv.bean.Site;
import com.fongmi.android.tv.databinding.ActivitySettingBinding;
import com.fongmi.android.tv.event.RefreshEvent;
import com.fongmi.android.tv.event.ServerEvent;
import com.fongmi.android.tv.impl.ConfigCallback;
import com.fongmi.android.tv.impl.LiveCallback;
import com.fongmi.android.tv.impl.SiteCallback;
@ -36,13 +38,15 @@ import com.fongmi.android.tv.ui.custom.dialog.SiteDialog;
import com.fongmi.android.tv.utils.Notify;
import com.fongmi.android.tv.utils.Prefers;
import com.fongmi.android.tv.utils.ResUtil;
import com.fongmi.android.tv.api.Updater;
import com.fongmi.android.tv.utils.Utils;
import com.permissionx.guolindev.PermissionX;
import org.greenrobot.eventbus.Subscribe;
import org.greenrobot.eventbus.ThreadMode;
public class SettingActivity extends BaseActivity implements ConfigCallback, SiteCallback, LiveCallback {
private final ActivityResultLauncher<String> launcherString = registerForActivityResult(new ActivityResultContracts.RequestPermission(), isGranted -> loadConfig());
private final ActivityResultLauncher<Intent> launcherIntent = registerForActivityResult(new ActivityResultContracts.StartActivityForResult(), result -> loadConfig());
private ActivitySettingBinding mBinding;
private Config config;
@ -96,10 +100,10 @@ public class SettingActivity extends BaseActivity implements ConfigCallback, Sit
}
private void checkPermission() {
if (config.getUrl().startsWith("file") && Build.VERSION.SDK_INT >= Build.VERSION_CODES.R && !Environment.isExternalStorageManager()) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R && !Environment.isExternalStorageManager()) {
openSetting();
} else if (config.getUrl().startsWith("file") && Build.VERSION.SDK_INT < Build.VERSION_CODES.R && ContextCompat.checkSelfPermission(this, Manifest.permission.READ_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED) {
launcherString.launch(Manifest.permission.READ_EXTERNAL_STORAGE);
} else if (Build.VERSION.SDK_INT < Build.VERSION_CODES.R && ContextCompat.checkSelfPermission(this, Manifest.permission.READ_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED) {
PermissionX.init(this).permissions(Manifest.permission.READ_EXTERNAL_STORAGE, Manifest.permission.WRITE_EXTERNAL_STORAGE).request((allGranted, grantedList, deniedList) -> loadConfig());
} else {
loadConfig();
}
@ -167,6 +171,11 @@ public class SettingActivity extends BaseActivity implements ConfigCallback, Sit
}
}
@Subscribe(threadMode = ThreadMode.MAIN)
public void onServerEvent(ServerEvent event) {
if (event.getType() == ServerEvent.Type.FILE) Utils.checkStoragePermission(this);
}
@Override
public void setSite(Site item) {
ApiConfig.get().setHome(item);

@ -3,7 +3,6 @@ package com.fongmi.android.tv.ui.custom;
import android.Manifest;
import android.content.Context;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.graphics.PorterDuff;
import android.graphics.Rect;
import android.speech.RecognizerIntent;
@ -12,21 +11,21 @@ import android.util.AttributeSet;
import android.view.KeyEvent;
import android.view.animation.Animation;
import androidx.activity.result.ActivityResultLauncher;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.appcompat.widget.AppCompatImageView;
import androidx.core.content.ContextCompat;
import androidx.fragment.app.FragmentActivity;
import com.fongmi.android.tv.R;
import com.fongmi.android.tv.utils.ResUtil;
import com.fongmi.android.tv.utils.Utils;
import com.github.bassaer.library.MDColor;
import com.permissionx.guolindev.PermissionX;
public class CustomMic extends AppCompatImageView {
private ActivityResultLauncher<String> launcher;
private SpeechRecognizer recognizer;
private FragmentActivity activity;
private Animation flicker;
private boolean listen;
@ -44,10 +43,6 @@ public class CustomMic extends AppCompatImageView {
recognizer = SpeechRecognizer.createSpeechRecognizer(context);
}
private boolean hasPermission() {
return ContextCompat.checkSelfPermission(getContext(), Manifest.permission.RECORD_AUDIO) == PackageManager.PERMISSION_GRANTED;
}
private boolean isListen() {
return listen;
}
@ -56,14 +51,15 @@ public class CustomMic extends AppCompatImageView {
this.listen = listen;
}
public void setListener(ActivityResultLauncher<String> launcher, CustomListener listener) {
public void setListener(FragmentActivity activity, CustomListener listener) {
this.recognizer.setRecognitionListener(listener);
this.launcher = launcher;
this.activity = activity;
}
private void check() {
if (hasPermission()) start();
else launcher.launch(Manifest.permission.RECORD_AUDIO);
private void checkPermission() {
PermissionX.init(activity).permissions(Manifest.permission.RECORD_AUDIO).request((allGranted, grantedList, deniedList) -> {
if (allGranted) start();
});
}
private void startListening() {
@ -93,7 +89,7 @@ public class CustomMic extends AppCompatImageView {
@Override
protected void onFocusChanged(boolean gainFocus, int direction, @Nullable Rect previouslyFocusedRect) {
super.onFocusChanged(gainFocus, direction, previouslyFocusedRect);
if (gainFocus) check();
if (gainFocus) checkPermission();
else stop();
}

@ -98,8 +98,8 @@ public class ConfigDialog implements DialogInterface.OnDismissListener {
private void onPositive(View view) {
String text = Utils.checkClan(binding.text.getText().toString().trim());
if (!url.equals(text)) callback.setConfig(Config.find(text, type));
if (text.isEmpty()) Config.delete(url, type);
callback.setConfig(Config.find(text, type));
dialog.dismiss();
}

@ -4,8 +4,8 @@ import org.greenrobot.eventbus.EventBus;
public class ServerEvent {
private final String text;
private final Type type;
private String text;
public static void search(String text) {
EventBus.getDefault().post(new ServerEvent(Type.SEARCH, text));
@ -23,6 +23,14 @@ public class ServerEvent {
EventBus.getDefault().post(new ServerEvent(Type.API, text));
}
public static void file() {
EventBus.getDefault().post(new ServerEvent(Type.FILE));
}
public ServerEvent(Type type) {
this.type = type;
}
private ServerEvent(Type type, String text) {
this.type = type;
this.text = text;
@ -37,6 +45,6 @@ public class ServerEvent {
}
public enum Type {
SEARCH, UPDATE, PUSH, API
SEARCH, UPDATE, PUSH, API, FILE
}
}

@ -2,6 +2,7 @@ package com.fongmi.android.tv.server;
import com.fongmi.android.tv.R;
import com.fongmi.android.tv.api.ApiConfig;
import com.fongmi.android.tv.event.ServerEvent;
import com.fongmi.android.tv.server.process.InputRequestProcess;
import com.fongmi.android.tv.server.process.RawRequestProcess;
import com.fongmi.android.tv.server.process.RequestProcess;
@ -11,7 +12,6 @@ import com.google.gson.JsonObject;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.InputStream;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
@ -101,7 +101,7 @@ public class Nano extends NanoHTTPD {
File file = FileUtil.getRootFile(path);
if (file.isFile()) return newChunkedResponse(Response.Status.OK, "application/octet-stream", new FileInputStream(file));
else return newFixedLengthResponse(Response.Status.OK, MIME_PLAINTEXT, listFiles(file));
} catch (FileNotFoundException e) {
} catch (Exception e) {
return newFixedLengthResponse(Response.Status.INTERNAL_ERROR, MIME_PLAINTEXT, e.getMessage());
}
}
@ -150,6 +150,7 @@ public class Nano extends NanoHTTPD {
JsonObject info = new JsonObject();
info.addProperty("parent", parent);
if (list == null || list.length == 0) {
if (parent.equals(".")) ServerEvent.file();
info.add("files", new JsonArray());
return info.toString();
}

@ -1,8 +1,13 @@
package com.fongmi.android.tv.utils;
import android.Manifest;
import android.app.Activity;
import android.content.Context;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.net.Uri;
import android.os.Build;
import android.os.Environment;
import android.os.IBinder;
import android.provider.Settings;
import android.text.TextUtils;
@ -11,9 +16,15 @@ import android.view.KeyEvent;
import android.view.View;
import android.view.inputmethod.InputMethodManager;
import androidx.annotation.RequiresApi;
import androidx.core.content.ContextCompat;
import androidx.fragment.app.FragmentActivity;
import com.fongmi.android.tv.App;
import com.fongmi.android.tv.BuildConfig;
import com.fongmi.android.tv.server.Server;
import com.google.android.exoplayer2.util.Util;
import com.permissionx.guolindev.PermissionX;
import java.math.BigInteger;
import java.security.MessageDigest;
@ -166,4 +177,21 @@ public class Utils {
imm.hideSoftInputFromWindow(windowToken, 0);
}
}
public static void checkStoragePermission(FragmentActivity activity) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R && !Environment.isExternalStorageManager()) {
Utils.openManageFileAccess();
} else if (Build.VERSION.SDK_INT < Build.VERSION_CODES.R && ContextCompat.checkSelfPermission(activity, Manifest.permission.READ_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED) {
PermissionX.init(activity).permissions(Manifest.permission.READ_EXTERNAL_STORAGE, Manifest.permission.WRITE_EXTERNAL_STORAGE).request(null);
}
}
@RequiresApi(api = Build.VERSION_CODES.R)
public static void openManageFileAccess() {
try {
App.get().startActivity(new Intent(Settings.ACTION_MANAGE_APP_ALL_FILES_ACCESS_PERMISSION, Uri.parse("package:" + BuildConfig.APPLICATION_ID)));
} catch (Exception e) {
App.get().startActivity(new Intent(Settings.ACTION_MANAGE_ALL_FILES_ACCESS_PERMISSION));
}
}
}

@ -21,6 +21,10 @@ function api() {
doAction('api', { text: $('#api_url').val() });
}
function api(text) {
doAction('api', { text: text });
}
function doAction(action, kv) {
kv['do'] = action;
$.post('/action', kv, function (data) {
@ -79,7 +83,7 @@ function selectFile(path, canDel) {
}
function fileToApi() {
doAction('api', { text: "file://" + current_file });
api("file://" + current_file);
hideFileInfo();
}

Loading…
Cancel
Save