Я пытаюсь создать приложение, которое создает файл CSV, а затем экспортирует этот файл CSV, прикрепив его к электронному письму или загрузив на диск Google. Я смотрел это видео: https://www.youtube.com/watch?v=VDAwbgHoYEA, и код почти работает. Тем не менее, у меня возникает проблема с разрешением, когда я пытаюсь его экспортировать: java.lang.SecurityException: Permission Denial: reading androidx.core.content.FileProvider uri content://com.example.CalendarTracker.fileprovider/data/data.csv from pid=22257, uid=1000 requires the provider be exported, or grantUriPermission()
Я знаю, что это довольно часто задаваемый вопрос, но я не смог найти онлайн-решение, которое, кажется, работает с новейшая Android сборка. Мне было интересно, если кто-то может помочь мне понять, как решить проблему, которая у меня возникла? В функции экспорта я пытаюсь отправить текстовый файл.
Ниже приведены мои основные действия и android файл манифеста ниже. Заранее благодарим за любую помощь!
Основная деятельность
package com.example.calendartracker;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.pm.PackageManager;
import android.content.pm.ResolveInfo;
import android.graphics.Color;
import android.net.Uri;
import android.os.Bundle;
import androidx.appcompat.app.AppCompatActivity;
import androidx.core.content.FileProvider;
import android.os.CountDownTimer;
import android.view.View;
import android.widget.Button;
import android.widget.TextView;
import java.io.File;
import java.io.FileOutputStream;
import java.net.URI;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.List;
public class MainActivity extends AppCompatActivity {
private static final long START_TIME_IN_MILLIS = 900000000;
private TextView mResultsString;
private TextView mStatusString;
private Button mResetButton;
private Button mStopButton;
private CountDownTimer mCountdownTimer;
private boolean mTimerRunning;
private long mTimeLeftInMillis = START_TIME_IN_MILLIS;
private int count = 0;
StringBuilder calendarData = new StringBuilder();
Calendar calendar = Calendar.getInstance();
@Override
protected void onCreate(Bundle savedInstanceState){
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mResultsString = findViewById(R.id.resultsString);
mStatusString = findViewById(R.id.status_TextView);
mResetButton = findViewById(R.id.reset_button);
mStopButton = findViewById(R.id.stopButton);
mResetButton.setEnabled(false);
mStatusString.setText("Collection Running");
mStatusString.setTextColor(Color.rgb(0,255,0));
startTimer();
mResetButton.setOnClickListener(new View.OnClickListener(){
@Override
public void onClick(View v){
resetTimer();
}
});
mStopButton.setOnClickListener(new View.OnClickListener(){
@Override
public void onClick(View v){
stopTimer();
}
});
updateUI();
}
private void startTimer(){
mCountdownTimer = new CountDownTimer(mTimeLeftInMillis, 1000){
@Override
public void onTick(long millisUntilFinshed){
calendar = Calendar.getInstance();
updateUI();
}
@Override
public void onFinish(){
mTimerRunning = false;
}
}.start();
mTimerRunning = true;
}
private void resetTimer(){
mStatusString.setText("Collection Running");
mStatusString.setTextColor(Color.rgb(0,255,0));
mResetButton.setEnabled(false);
mStopButton.setEnabled(true);
mTimeLeftInMillis = START_TIME_IN_MILLIS;
startTimer();
updateUI();
}
private void stopTimer(){
mCountdownTimer.cancel();
mTimerRunning = false;
mResetButton.setEnabled(true);
mStopButton.setEnabled(false);
mStatusString.setText("Stopped");
mStatusString.setTextColor(Color.rgb(255,0,0));
export();
}
private void updateUI(){
SimpleDateFormat formatter = new SimpleDateFormat("MM/dd/yyyy hh:mm:ss");
String currentTime = formatter.format(calendar.getTime());
mResultsString.setText(currentTime);
calendarData.append(currentTime);
}
public void export() {
Context context = getApplicationContext();
File fileLocation = new File(getFilesDir(), "data.csv");
Uri path = FileProvider.getUriForFile(context, "com.example.CalendarTracker.fileprovider", fileLocation);
//writing the data to a CSV file
try {
FileOutputStream output = openFileOutput("data.csv", Context.MODE_PRIVATE);
output.write((calendarData.toString().getBytes()));
output.close();
//exporting
Intent fileIntent = new Intent(Intent.ACTION_SEND);
fileIntent.setType("*/*");
fileIntent.putExtra(Intent.EXTRA_SUBJECT, "Calendar Data");
fileIntent.putExtra(Intent.EXTRA_STREAM, path);
fileIntent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION |Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
startActivity(Intent.createChooser(fileIntent, "Send mail"));
} catch (Exception e) {
System.out.println(e);
}
}
}
Android Манифест
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.calendartracker">
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.READ_INTERNAL_STORAGE" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<application
android:allowBackup="true"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:roundIcon="@mipmap/ic_launcher_round"
android:supportsRtl="true"
android:theme="@style/AppTheme">
<activity
android:name=".MainActivity"
android:label="@string/app_name"
android:theme="@style/AppTheme.NoActionBar">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<provider
android:name="androidx.core.content.FileProvider"
android:authorities="com.example.CalendarTracker.fileprovider"
android:grantUriPermissions="true"
android:exported="false">
<meta-data
android:name="android.support.FILE_PROVIDER_PATHS"
android:resource="@xml/provider_paths"/>
</provider>
</application>
</manifest>