Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
21 changes: 15 additions & 6 deletions android/app/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -147,17 +147,26 @@ android {
}
}
}
packagingOptions {
//当项目中出现多个同名的so文件会编译异常,过滤多余的so文件
pickFirst '**/libfbjni.so'
pickFirst '**/libc++_shared.so'
pickFirst '**/libjsc.so'
}
}

dependencies {
implementation project(':@react-native-community_async-storage')
implementation project(':react-native-music-control')
implementation project(':react-native-vector-icons')
implementation project(':react-native-gesture-handler')
implementation project(':react-native-video')
implementation project(path: ':@react-native-community_toolbar-android')
implementation project(path: ':@react-native-community_async-storage')
implementation project(path: ':react-native-music-control')
implementation project(path: ':react-native-vector-icons')
implementation project(path: ':react-native-gesture-handler')
implementation project(path: ':react-native-screens')
implementation project(path: ':react-native-video')
implementation fileTree(dir: "libs", include: ["*.jar"])
implementation "com.android.support:appcompat-v7:${rootProject.ext.supportLibVersion}"
implementation "androidx.activity:activity:1.3.0"
implementation "com.facebook.react:react-native:+" // From node_modules
implementation "org.webkit:android-jsc:+"
}

// Run this once to be able to run the application with BUCK
Expand Down
44 changes: 24 additions & 20 deletions android/app/src/main/AndroidManifest.xml
Original file line number Diff line number Diff line change
@@ -1,31 +1,35 @@
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.listen1.app">
package="com.listen1.app">

<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.FOREGROUND_SERVICE" />

<!-- usesCleartextTraffic: fix bug: http request not sent when install by released apk -->
<application
android:name=".MainApplication"
android:label="@string/app_name"
android:icon="@mipmap/ic_launcher"
android:roundIcon="@mipmap/ic_launcher_round"
android:allowBackup="false"
android:usesCleartextTraffic="true"
android:theme="@style/AppTheme">
<!-- https://stackoverflow.com/questions/39657029/react-native-android-several-apps-instances-running-at-the-same-time-as-result -->
<activity
android:name=".MainActivity"
android:name=".MainApplication"
android:allowBackup="false"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:launchMode="singleInstance"
android:configChanges="keyboard|keyboardHidden|orientation|screenSize"
android:windowSoftInputMode="adjustResize">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<activity android:name="com.facebook.react.devsupport.DevSettingsActivity" />
android:requestLegacyExternalStorage="true"
android:roundIcon="@mipmap/ic_launcher_round"
android:theme="@style/AppTheme"
android:usesCleartextTraffic="true">
<!-- https://stackoverflow.com/questions/39657029/react-native-android-several-apps-instances-running-at-the-same-time-as-result -->
<activity
android:name=".MainActivity"
android:configChanges="keyboard|keyboardHidden|orientation|screenSize"
android:exported="true"
android:label="@string/app_name"
android:launchMode="singleInstance"
android:windowSoftInputMode="adjustResize">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<activity android:name="com.facebook.react.devsupport.DevSettingsActivity" />
<activity android:name=".OpenFileActivity"
android:theme="@style/translucentStyle"/>
</application>

</manifest>
13 changes: 7 additions & 6 deletions android/app/src/main/java/com/listen1/app/MainApplication.java
Original file line number Diff line number Diff line change
Expand Up @@ -29,12 +29,13 @@ public boolean getUseDeveloperSupport() {
@Override
protected List<ReactPackage> getPackages() {
return Arrays.<ReactPackage>asList(
new MainReactPackage(),
new AsyncStoragePackage(),
new MusicControl(),
new VectorIconsPackage(),
new RNGestureHandlerPackage(),
new ReactVideoPackage()
new MainReactPackage(),
new MainPackage(),
new AsyncStoragePackage(),
new MusicControl(),
new VectorIconsPackage(),
new RNGestureHandlerPackage(),
new ReactVideoPackage()
);
}

Expand Down
35 changes: 35 additions & 0 deletions android/app/src/main/java/com/listen1/app/MainPackage.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
package com.listen1.app;

import com.facebook.react.ReactPackage;
import com.facebook.react.bridge.NativeModule;
import com.facebook.react.bridge.ReactApplicationContext;
import com.facebook.react.uimanager.ViewManager;
import com.listen1.app.utils.FileConfig;

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

import javax.annotation.Nonnull;

/**
* @Description: java类作用描述
* @Author: Void
* @CreateDate: 2023/1/11 15:31
* @UpdateDate: 2023/1/11 15:31
*/
public class MainPackage implements ReactPackage {
@Nonnull
@Override
public List<NativeModule> createNativeModules(@Nonnull ReactApplicationContext context) {
List<NativeModule> modules = new ArrayList<>();
modules.add(new FileConfig(context));
return modules;
}

@Nonnull
@Override
public List<ViewManager> createViewManagers(@Nonnull ReactApplicationContext reactApplicationContext) {
return Collections.emptyList();
}
}
148 changes: 148 additions & 0 deletions android/app/src/main/java/com/listen1/app/OpenFileActivity.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,148 @@
package com.listen1.app;

import android.Manifest;
import android.app.Activity;
import android.content.Intent;
import android.net.Uri;
import android.os.Bundle;
import android.os.Environment;
import android.os.ParcelFileDescriptor;
import android.util.Log;
import androidx.annotation.Nullable;
import com.listen1.app.utils.FileConfig;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.FileWriter;
import java.io.IOException;
import java.io.PrintWriter;

public class OpenFileActivity extends PermissionActivity {
private final String[] readStoragePermissions = new String[]{
Manifest.permission.READ_EXTERNAL_STORAGE
};
private int openFileRequestCode = -1;

@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
openFileRequestCode = getIntent().getIntExtra("OPEN_FILE_REQUEST_CODE", -1);
checkPermission();
}

@Override
protected void onActivityResult(int requestCode, int resultCode, @Nullable Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if (requestCode != 1001) return;
if (data == null) {
backResult("", false);
return;
}
byte[] bytes = new byte[50];
StringBuilder builder = new StringBuilder();
Uri uri = data.getData();
new Thread() {
@Override
public void run() {
super.run();
FileInputStream fileInputStream = null;
ParcelFileDescriptor descriptor = null;
int endLength;
try {
descriptor = getContentResolver().openFileDescriptor(uri, "r");
fileInputStream = new FileInputStream(descriptor.getFileDescriptor());
while ((endLength = fileInputStream.read(bytes)) > 0) {
builder.append(new String(bytes, 0, endLength));
}
} catch (IOException e) {
e.printStackTrace();
backResult("", false);
} finally {
try {
if (descriptor != null) descriptor.close();
if (fileInputStream != null) fileInputStream.close();
} catch (IOException e) {
e.printStackTrace();
}
backResult(builder.toString(), false);
}
}
}.start();
}

@Override
protected String[] getPermissionArray() {
return readStoragePermissions;
}

@Override
protected String getDialogHint() {
return "需要读写权限以继续流程";
}

/**
* 权限请求结果回调
*/
@Override
protected void permissionResult(boolean state, @Nullable String msg) {
Log.d("PermissionActivity", "state:" + state);
if (!state) return;
if (openFileRequestCode == FileConfig.readFileCode) {
//打开文件管理器
Intent mIntent = new Intent(Intent.ACTION_GET_CONTENT);
mIntent.addCategory(Intent.CATEGORY_OPENABLE);
mIntent.setType("application/json");
startActivityForResult(mIntent, 1001);
} else if (openFileRequestCode == FileConfig.writeFileCode) {
writeContentToFile();
}
}

private void backResult(String content, boolean writeState) {
if (callback == null) return;
Bundle mBundle = new Bundle();
if (openFileRequestCode == FileConfig.readFileCode) {
mBundle.putString("jsonContent", content);
} else if (openFileRequestCode == FileConfig.writeFileCode) {
mBundle.putBoolean("writeState", writeState);
}
callback.onResult(openFileRequestCode, mBundle);
callback = null;
finish();
}

private void writeContentToFile() {
File dir = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS);
boolean state;
if (!dir.exists()) dir.mkdirs();
File exportJson = new File(dir, "listen1_backup.json");
try {
if (exportJson.exists()) {
//如果文件存在,清空文件内容
FileWriter fileWrite = new FileWriter(exportJson);
fileWrite.write("");
fileWrite.flush();
fileWrite.close();
} else {
exportJson.createNewFile();
}
PrintWriter writer = new PrintWriter(new FileOutputStream(exportJson));
writer.print(FileConfig.content);
writer.close();
state = true;
} catch (IOException e) {
e.printStackTrace();
state = false;
}
backResult("", state);
}

private static ResultCallback callback = null;

public static void newInstance(Activity activity, int openFileRequestCode, @Nullable ResultCallback callback) {
OpenFileActivity.callback = callback;
Intent mIntent = new Intent(activity, OpenFileActivity.class);
mIntent.putExtra("OPEN_FILE_REQUEST_CODE", openFileRequestCode);
activity.startActivity(mIntent);
}
}
95 changes: 95 additions & 0 deletions android/app/src/main/java/com/listen1/app/PermissionActivity.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,95 @@
package com.listen1.app;

import android.app.AlertDialog;
import android.content.DialogInterface;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.net.Uri;
import android.os.Bundle;
import android.provider.Settings;

import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.appcompat.app.AppCompatActivity;
import androidx.core.app.ActivityCompat;
import androidx.core.content.ContextCompat;

public abstract class PermissionActivity extends AppCompatActivity {
private String requestHint = "该操作需要权限才能继续";

@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
String hint = getDialogHint();
if (hint != null && !hint.isEmpty()) {
requestHint = hint;
}
}

@Override
public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
super.onRequestPermissionsResult(requestCode, permissions, grantResults);
if (requestCode != 1001) return;
if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
permissionResult(true, null);
}
}

protected abstract String[] getPermissionArray();

protected abstract String getDialogHint();

/**
* 返回权限处理结果
*
* @param state true:权限获取成功
* @param msg 额外的消息字符串
*/
protected abstract void permissionResult(boolean state, @Nullable String msg);

protected void checkPermission() {
if (getPermissionArray() == null || getPermissionArray().length == 0) {
throw new RuntimeException("权限不能为空!");
}
for (String permission : getPermissionArray()) {
if (ContextCompat.checkSelfPermission(getApplicationContext(), permission) != PackageManager.PERMISSION_DENIED)
continue;
if (ActivityCompat.shouldShowRequestPermissionRationale(this, permission)) {
//用户之前拒绝了权限,且设置了不再提示
createDialog("已设置拒绝授予权限且不在显示,请前往设置手动设置权限", "确定", (dialog, which) -> {
//当用户还是想用APP,跳转到APP设置界面,由用户手动授予权限
Intent mIntent = new Intent(
Settings.ACTION_APPLICATION_DETAILS_SETTINGS,
Uri.fromParts("package", getPackageName(), null)
);
startActivity(mIntent);
});
permissionResult(false, null);
} else {
createDialog(requestHint, "设置权限", (dialog, which) -> ActivityCompat.requestPermissions(this, getPermissionArray(), 1001));
}
return;
}
permissionResult(true, null);
}

/**
* 创建请求权限弹窗,当用户允许时触发权限请求流程
*
* @param msg 弹窗内容
* @param positiveBtn acceptBtn
*/
private void createDialog(String msg, String positiveBtn, DialogInterface.OnClickListener listener) {
AlertDialog permissionDialog = new AlertDialog.Builder(this)
.setTitle("请求权限")
.setMessage(msg)
.setCancelable(false)
.setPositiveButton(positiveBtn, listener)
.setNegativeButton("取消", (dialog, which) -> finish())
.create();
if (permissionDialog.isShowing()) {
permissionDialog.dismiss();
}
permissionDialog.show();
}
}
7 changes: 7 additions & 0 deletions android/app/src/main/java/com/listen1/app/ResultCallback.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
package com.listen1.app;

import android.os.Bundle;

public interface ResultCallback {
void onResult(int requestCode, Bundle bundle);
}
Loading