无法访问“下载”文件夹
Fails to access the `Downloads` folder
我正在尝试将一个 txt 文件保存到我的第一个 abndroid 应用程序的下载文件夹中。
public class DisplaySettingsActivity extends AppCompatActivity implements View.OnClickListener {
private H300sVoipSettings settings;
Button saveIntoFile;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_display_settings);
this.settings = (H300sVoipSettings) getIntent().getSerializableExtra("H300sVoipSettings");
this.saveIntoFile = (Button)findViewById(R.id.save);
this.saveIntoFile.setOnClickListener(this);
}
private String saveFile(){
Log.d("Η300s","Saving");
String state = Environment.getExternalStorageState();
if (!Environment.MEDIA_MOUNTED.equals(state)) {
Log.e("H300s","Unable to detect external storage");
return null;
}
DateTimeFormatter pattern = DateTimeFormatter.ofPattern("yyyMMdd");
File file = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS);
file = new File( file.getAbsolutePath(),"voip_h300s_"+pattern.format(LocalDate.now())+".txt");
Log.d("H300s",file.toString());
try {
Log.d("H300s","Saving");
this.settings.save(file);
Log.d("H300s","Saved");
Log.d("H300s",file.getAbsolutePath());
return file.getAbsolutePath();
} catch (Exception e) {
Log.e("H300s",e.toString());
Log.e("H300s",Log.getStackTraceString(e));
return null;
}
}
}
但是我函数中的这段代码:
this.settings.save(file);
由于权限不足,保存失败。如下日志所示:
2021-04-24 14:48:18.498 8208-8208/com.example.vodafone_fu_h300s E/H300s: java.io.IOException: Permission denied
2021-04-24 14:48:18.499 8208-8208/com.example.vodafone_fu_h300s E/H300s: java.io.IOException: Permission denied
at java.io.UnixFileSystem.createFileExclusively0(Native Method)
at java.io.UnixFileSystem.createFileExclusively(UnixFileSystem.java:281)
at java.io.File.createNewFile(File.java:1008)
at pc_magas.vodafone_fu_h300s.screens.DisplaySettingsActivity.saveFile(DisplaySettingsActivity.java:97)
at pc_magas.vodafone_fu_h300s.screens.DisplaySettingsActivity.onClick(DisplaySettingsActivity.java:120)
at android.view.View.performClick(View.java:6597)
at com.google.android.material.button.MaterialButton.performClick(MaterialButton.java:967)
at android.view.View.performClickInternal(View.java:6574)
at android.view.View.access00(View.java:778)
at android.view.View$PerformClick.run(View.java:25906)
at android.os.Handler.handleCallback(Handler.java:873)
at android.os.Handler.dispatchMessage(Handler.java:99)
at android.os.Looper.loop(Looper.java:193)
at android.app.ActivityThread.main(ActivityThread.java:6718)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:491)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:858)
我想要做的是将一个 txt 文件保存到下载文件夹中,并让用户可以通过文件管理器访问它。 class H300sVoipSettings
有以下内容:
public class H300sVoipSettings implements Serializable
{
private String username = null;
private String password = null;
private String primary_registar = null;
private String primary_registar_port = null;
private String secondary_registar = null;
private String secondary_registar_port = null;
private String primary_proxy = null;
private String primary_proxy_port = null;
private String secondary_proxy = null;
private String secondary_proxy_port = null;
private String sip_domain = null;
private String sip_number = null;
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
public String getPrimary_registar() {
return primary_registar;
}
public void setPrimary_registar(String primary_registar) {
this.primary_registar = primary_registar;
}
public String getPrimary_registar_port() {
return primary_registar_port;
}
public void setPrimary_registar_port(String primary_registar_port) {
this.primary_registar_port = primary_registar_port;
}
public String getSecondary_registar() {
if(secondary_registar == null || secondary_registar.trim().equals("")){
return null;
}
return secondary_registar;
}
public void setSecondary_registar(String secondary_registar) {
this.secondary_registar = secondary_registar;
}
public String getSecondary_registar_port() {
return secondary_registar_port;
}
public void setSecondary_registar_port(String secondary_registar_port) {
this.secondary_registar_port = secondary_registar_port;
}
public String getPrimary_proxy() {
return primary_proxy;
}
public void setPrimary_proxy(String primary_proxy) {
this.primary_proxy = primary_proxy;
}
public String getPrimary_proxy_port() {
return primary_proxy_port;
}
public void setPrimary_proxy_port(String primary_proxy_port) {
this.primary_proxy_port = primary_proxy_port;
}
public String getSecondary_proxy() {
return secondary_proxy;
}
public void setSecondary_proxy(String secondary_proxy) {
this.secondary_proxy = secondary_proxy;
}
public String getSecondary_proxy_port() {
return secondary_proxy_port;
}
public void setSecondary_proxy_port(String secondary_proxy_port) {
this.secondary_proxy_port = secondary_proxy_port;
}
public String getSip_domain() {
return sip_domain;
}
public void setSip_domain(String sip_domain) {
this.sip_domain = sip_domain;
}
public String getSip_number() {
return sip_number;
}
public void setSip_number(String sip_number) {
this.sip_number = sip_number;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
public static H300sVoipSettings createFromJson(String jsonString) throws IllegalArgumentException, JSONException {
if(jsonString == null || jsonString.trim().equals("")){
throw new IllegalArgumentException("JsonString Should not be empty");
}
JSONArray settingsJson = new JSONArray(jsonString);
H300sVoipSettings settings = new H300sVoipSettings();
for (int i = 0; i < settingsJson.length(); i++) {
JSONObject item = settingsJson.getJSONObject(i);
if(item.getString("type").equals("provider")){
settings.setPrimary_registar(item.getString("primary_registrar"));
settings.setPrimary_registar_port(item.getString("primary_registrar_port"));
settings.setPrimary_proxy(item.getString("primary_proxy"));
settings.setPrimary_proxy_port(item.getString("primary_proxy_port"));
settings.setSip_domain(item.getString("sip_domain"));
String secondary_proxy = item.getString("secondary_proxy");
if(secondary_proxy != null && !secondary_proxy.trim().equals("")){
settings.setSecondary_proxy(secondary_proxy.trim());
}
settings.setSecondary_proxy_port(item.getString("secondary_proxy_port"));
settings.setSecondary_registar(item.getString("secondary_registrar"));
settings.setSecondary_registar_port(item.getString("secondary_registrar_port"));
} else if(item.getString("type").equals("number")){
settings.setSip_number(item.getString("sip_number"));
settings.setUsername(item.getString("username"));
settings.setPassword(item.getString("password"));
}
}
return settings;
}
public boolean equals(H300sVoipSettings other){
boolean truth = other.getPassword().equals(this.getPassword()) &&
other.getUsername().equals(this.getUsername()) &&
other.getSip_number().equals(this.getSip_number()) &&
other.getSip_domain().equals(this.getSip_domain()) &&
other.getPrimary_proxy().equals(this.getPrimary_proxy()) &&
other.getPrimary_proxy_port().equals(this.getPrimary_proxy_port()) &&
other.getPrimary_registar().equals(this.getPrimary_registar()) &&
other.getPrimary_registar_port().equals(this.getPrimary_registar_port()) &&
other.getSecondary_proxy_port().equals(this.getSecondary_proxy_port()) &&
other.getSecondary_registar_port().equals(this.getSecondary_registar_port());
truth = truth && ((other.getSecondary_proxy() == null && this.getSecondary_proxy() == null) || (other.getSecondary_proxy().equals(this.getSecondary_proxy())));
truth = truth &&
(
(other.getSecondary_registar() == null && this.getSecondary_registar() == null) ||
(
other.getSecondary_registar().equals(this.getSecondary_registar())
)
);
return truth;
}
public String toString()
{
StringBuilder txt = new StringBuilder();
txt.append("Phone Number: ");
txt.append(this.getSip_number());
txt.append("\n");
txt.append("Username: ");
txt.append(this.getUsername());
txt.append("\n");
txt.append("Password: ");
txt.append(this.getPassword());
txt.append("\n");
txt.append("Sip Domain: ");
txt.append(this.getSip_domain());
txt.append("\n");
txt.append("Primary proxy: ");
txt.append(this.getPrimary_proxy());
txt.append(" Port: ");
txt.append(this.getPrimary_proxy_port());
txt.append("\n");
txt.append("Secondary proxy: ");
String secondary_proxy = this.getSecondary_proxy();
secondary_proxy = (secondary_proxy == null || !secondary_proxy.trim().equals(""))?"N/A":secondary_proxy;
txt.append(secondary_proxy);
txt.append(" Port: ");
String secondaryProxyPort = this.getSecondary_proxy_port();
secondaryProxyPort=(secondaryProxyPort == null || !secondaryProxyPort.trim().equals(""))?"N/A":secondaryProxyPort;
txt.append(secondaryProxyPort);
txt.append("\n");
txt.append("Primary Registar: ");
String primaryRegistar = this.getPrimary_registar();
txt.append(primaryRegistar);
txt.append(" Port: ");
String primaryRegistarPort = this.getPrimary_registar_port();
txt.append(primaryRegistarPort);
txt.append("\n");
txt.append("Secondary Registar: ");
String secondary_registar = this.getSecondary_registar();
secondary_registar = (secondary_registar == null || !secondary_registar.trim().equals(""))?"N/A":secondary_registar;
txt.append(secondary_registar);
txt.append(" Port: ");
String secondaryRegistarPort = this.getSecondary_registar();
secondaryRegistarPort=(secondaryRegistarPort == null || !secondaryRegistarPort.trim().equals(""))?"N/A":secondaryRegistarPort;
txt.append(secondaryRegistarPort);
txt.append("\n");
return txt.toString();
}
public void save(File file) throws IOException {
PrintWriter out = new PrintWriter(new FileWriter(file));
out.println("********");
out.print("Exported Date: ");
out.println(new Date().toString());
out.println("********");
out.print(this.toString());
out.close();
}
}
并用于数据序列化。该应用程序在 Android 清单中具有以下内容:
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
此外,我查看了这些答案,但没有任何结果:
那么你知道我如何访问 donwloads 文件夹吗?
尽管拥有权限:
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
您还应该提示用户也接受这些请求。为了实现这一点,onCLick
函数应该是:
public void onClick(View v) {
if (ContextCompat.checkSelfPermission(this, Manifest.permission.WRITE_EXTERNAL_STORAGE) == PackageManager.PERMISSION_GRANTED) {
Log.d("H300s","Permission Accepted");
saveFile();
} else {
requestPermissionLauncher.launch(Manifest.permission.WRITE_EXTERNAL_STORAGE );
}
}
其中 requestPermissionLauncher
被初始化为 onCreate
是这样的:
requestPermissionLauncher = registerForActivityResult(new ActivityResultContracts.RequestPermission(), isGranted -> {
Log.d("H300s","Permissions Callback");
if (isGranted) {
Log.d("H300s","Permission Accepted 2");
saveFile();
} else {
permissionSaveDenied();
}
});
此外,请确保在 build.gradle
处放置以下内容:
implementation 'androidx.activity:activity-ktx:1.2.0'
implementation 'androidx.fragment:fragment:1.3.0'
为了 ActivityResultContracts
正常工作。
奖金提示
您可以跳过声明需要此权限:
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
因为应用程序仍然会要求用户提供它。
我正在尝试将一个 txt 文件保存到我的第一个 abndroid 应用程序的下载文件夹中。
public class DisplaySettingsActivity extends AppCompatActivity implements View.OnClickListener {
private H300sVoipSettings settings;
Button saveIntoFile;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_display_settings);
this.settings = (H300sVoipSettings) getIntent().getSerializableExtra("H300sVoipSettings");
this.saveIntoFile = (Button)findViewById(R.id.save);
this.saveIntoFile.setOnClickListener(this);
}
private String saveFile(){
Log.d("Η300s","Saving");
String state = Environment.getExternalStorageState();
if (!Environment.MEDIA_MOUNTED.equals(state)) {
Log.e("H300s","Unable to detect external storage");
return null;
}
DateTimeFormatter pattern = DateTimeFormatter.ofPattern("yyyMMdd");
File file = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS);
file = new File( file.getAbsolutePath(),"voip_h300s_"+pattern.format(LocalDate.now())+".txt");
Log.d("H300s",file.toString());
try {
Log.d("H300s","Saving");
this.settings.save(file);
Log.d("H300s","Saved");
Log.d("H300s",file.getAbsolutePath());
return file.getAbsolutePath();
} catch (Exception e) {
Log.e("H300s",e.toString());
Log.e("H300s",Log.getStackTraceString(e));
return null;
}
}
}
但是我函数中的这段代码:
this.settings.save(file);
由于权限不足,保存失败。如下日志所示:
2021-04-24 14:48:18.498 8208-8208/com.example.vodafone_fu_h300s E/H300s: java.io.IOException: Permission denied
2021-04-24 14:48:18.499 8208-8208/com.example.vodafone_fu_h300s E/H300s: java.io.IOException: Permission denied
at java.io.UnixFileSystem.createFileExclusively0(Native Method)
at java.io.UnixFileSystem.createFileExclusively(UnixFileSystem.java:281)
at java.io.File.createNewFile(File.java:1008)
at pc_magas.vodafone_fu_h300s.screens.DisplaySettingsActivity.saveFile(DisplaySettingsActivity.java:97)
at pc_magas.vodafone_fu_h300s.screens.DisplaySettingsActivity.onClick(DisplaySettingsActivity.java:120)
at android.view.View.performClick(View.java:6597)
at com.google.android.material.button.MaterialButton.performClick(MaterialButton.java:967)
at android.view.View.performClickInternal(View.java:6574)
at android.view.View.access00(View.java:778)
at android.view.View$PerformClick.run(View.java:25906)
at android.os.Handler.handleCallback(Handler.java:873)
at android.os.Handler.dispatchMessage(Handler.java:99)
at android.os.Looper.loop(Looper.java:193)
at android.app.ActivityThread.main(ActivityThread.java:6718)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:491)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:858)
我想要做的是将一个 txt 文件保存到下载文件夹中,并让用户可以通过文件管理器访问它。 class H300sVoipSettings
有以下内容:
public class H300sVoipSettings implements Serializable
{
private String username = null;
private String password = null;
private String primary_registar = null;
private String primary_registar_port = null;
private String secondary_registar = null;
private String secondary_registar_port = null;
private String primary_proxy = null;
private String primary_proxy_port = null;
private String secondary_proxy = null;
private String secondary_proxy_port = null;
private String sip_domain = null;
private String sip_number = null;
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
public String getPrimary_registar() {
return primary_registar;
}
public void setPrimary_registar(String primary_registar) {
this.primary_registar = primary_registar;
}
public String getPrimary_registar_port() {
return primary_registar_port;
}
public void setPrimary_registar_port(String primary_registar_port) {
this.primary_registar_port = primary_registar_port;
}
public String getSecondary_registar() {
if(secondary_registar == null || secondary_registar.trim().equals("")){
return null;
}
return secondary_registar;
}
public void setSecondary_registar(String secondary_registar) {
this.secondary_registar = secondary_registar;
}
public String getSecondary_registar_port() {
return secondary_registar_port;
}
public void setSecondary_registar_port(String secondary_registar_port) {
this.secondary_registar_port = secondary_registar_port;
}
public String getPrimary_proxy() {
return primary_proxy;
}
public void setPrimary_proxy(String primary_proxy) {
this.primary_proxy = primary_proxy;
}
public String getPrimary_proxy_port() {
return primary_proxy_port;
}
public void setPrimary_proxy_port(String primary_proxy_port) {
this.primary_proxy_port = primary_proxy_port;
}
public String getSecondary_proxy() {
return secondary_proxy;
}
public void setSecondary_proxy(String secondary_proxy) {
this.secondary_proxy = secondary_proxy;
}
public String getSecondary_proxy_port() {
return secondary_proxy_port;
}
public void setSecondary_proxy_port(String secondary_proxy_port) {
this.secondary_proxy_port = secondary_proxy_port;
}
public String getSip_domain() {
return sip_domain;
}
public void setSip_domain(String sip_domain) {
this.sip_domain = sip_domain;
}
public String getSip_number() {
return sip_number;
}
public void setSip_number(String sip_number) {
this.sip_number = sip_number;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
public static H300sVoipSettings createFromJson(String jsonString) throws IllegalArgumentException, JSONException {
if(jsonString == null || jsonString.trim().equals("")){
throw new IllegalArgumentException("JsonString Should not be empty");
}
JSONArray settingsJson = new JSONArray(jsonString);
H300sVoipSettings settings = new H300sVoipSettings();
for (int i = 0; i < settingsJson.length(); i++) {
JSONObject item = settingsJson.getJSONObject(i);
if(item.getString("type").equals("provider")){
settings.setPrimary_registar(item.getString("primary_registrar"));
settings.setPrimary_registar_port(item.getString("primary_registrar_port"));
settings.setPrimary_proxy(item.getString("primary_proxy"));
settings.setPrimary_proxy_port(item.getString("primary_proxy_port"));
settings.setSip_domain(item.getString("sip_domain"));
String secondary_proxy = item.getString("secondary_proxy");
if(secondary_proxy != null && !secondary_proxy.trim().equals("")){
settings.setSecondary_proxy(secondary_proxy.trim());
}
settings.setSecondary_proxy_port(item.getString("secondary_proxy_port"));
settings.setSecondary_registar(item.getString("secondary_registrar"));
settings.setSecondary_registar_port(item.getString("secondary_registrar_port"));
} else if(item.getString("type").equals("number")){
settings.setSip_number(item.getString("sip_number"));
settings.setUsername(item.getString("username"));
settings.setPassword(item.getString("password"));
}
}
return settings;
}
public boolean equals(H300sVoipSettings other){
boolean truth = other.getPassword().equals(this.getPassword()) &&
other.getUsername().equals(this.getUsername()) &&
other.getSip_number().equals(this.getSip_number()) &&
other.getSip_domain().equals(this.getSip_domain()) &&
other.getPrimary_proxy().equals(this.getPrimary_proxy()) &&
other.getPrimary_proxy_port().equals(this.getPrimary_proxy_port()) &&
other.getPrimary_registar().equals(this.getPrimary_registar()) &&
other.getPrimary_registar_port().equals(this.getPrimary_registar_port()) &&
other.getSecondary_proxy_port().equals(this.getSecondary_proxy_port()) &&
other.getSecondary_registar_port().equals(this.getSecondary_registar_port());
truth = truth && ((other.getSecondary_proxy() == null && this.getSecondary_proxy() == null) || (other.getSecondary_proxy().equals(this.getSecondary_proxy())));
truth = truth &&
(
(other.getSecondary_registar() == null && this.getSecondary_registar() == null) ||
(
other.getSecondary_registar().equals(this.getSecondary_registar())
)
);
return truth;
}
public String toString()
{
StringBuilder txt = new StringBuilder();
txt.append("Phone Number: ");
txt.append(this.getSip_number());
txt.append("\n");
txt.append("Username: ");
txt.append(this.getUsername());
txt.append("\n");
txt.append("Password: ");
txt.append(this.getPassword());
txt.append("\n");
txt.append("Sip Domain: ");
txt.append(this.getSip_domain());
txt.append("\n");
txt.append("Primary proxy: ");
txt.append(this.getPrimary_proxy());
txt.append(" Port: ");
txt.append(this.getPrimary_proxy_port());
txt.append("\n");
txt.append("Secondary proxy: ");
String secondary_proxy = this.getSecondary_proxy();
secondary_proxy = (secondary_proxy == null || !secondary_proxy.trim().equals(""))?"N/A":secondary_proxy;
txt.append(secondary_proxy);
txt.append(" Port: ");
String secondaryProxyPort = this.getSecondary_proxy_port();
secondaryProxyPort=(secondaryProxyPort == null || !secondaryProxyPort.trim().equals(""))?"N/A":secondaryProxyPort;
txt.append(secondaryProxyPort);
txt.append("\n");
txt.append("Primary Registar: ");
String primaryRegistar = this.getPrimary_registar();
txt.append(primaryRegistar);
txt.append(" Port: ");
String primaryRegistarPort = this.getPrimary_registar_port();
txt.append(primaryRegistarPort);
txt.append("\n");
txt.append("Secondary Registar: ");
String secondary_registar = this.getSecondary_registar();
secondary_registar = (secondary_registar == null || !secondary_registar.trim().equals(""))?"N/A":secondary_registar;
txt.append(secondary_registar);
txt.append(" Port: ");
String secondaryRegistarPort = this.getSecondary_registar();
secondaryRegistarPort=(secondaryRegistarPort == null || !secondaryRegistarPort.trim().equals(""))?"N/A":secondaryRegistarPort;
txt.append(secondaryRegistarPort);
txt.append("\n");
return txt.toString();
}
public void save(File file) throws IOException {
PrintWriter out = new PrintWriter(new FileWriter(file));
out.println("********");
out.print("Exported Date: ");
out.println(new Date().toString());
out.println("********");
out.print(this.toString());
out.close();
}
}
并用于数据序列化。该应用程序在 Android 清单中具有以下内容:
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
此外,我查看了这些答案,但没有任何结果:
那么你知道我如何访问 donwloads 文件夹吗?
尽管拥有权限:
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
您还应该提示用户也接受这些请求。为了实现这一点,onCLick
函数应该是:
public void onClick(View v) {
if (ContextCompat.checkSelfPermission(this, Manifest.permission.WRITE_EXTERNAL_STORAGE) == PackageManager.PERMISSION_GRANTED) {
Log.d("H300s","Permission Accepted");
saveFile();
} else {
requestPermissionLauncher.launch(Manifest.permission.WRITE_EXTERNAL_STORAGE );
}
}
其中 requestPermissionLauncher
被初始化为 onCreate
是这样的:
requestPermissionLauncher = registerForActivityResult(new ActivityResultContracts.RequestPermission(), isGranted -> {
Log.d("H300s","Permissions Callback");
if (isGranted) {
Log.d("H300s","Permission Accepted 2");
saveFile();
} else {
permissionSaveDenied();
}
});
此外,请确保在 build.gradle
处放置以下内容:
implementation 'androidx.activity:activity-ktx:1.2.0'
implementation 'androidx.fragment:fragment:1.3.0'
为了 ActivityResultContracts
正常工作。
奖金提示
您可以跳过声明需要此权限:
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
因为应用程序仍然会要求用户提供它。