Android says, that listOfFiles if null, so what have i done wrong?
I've tried to change getPath to getAboletePath, but it is just the same.
And, i've tried to access /storage/ (whereas SD_PATH is /storage/emulated/0) and i've got a list of 2 folders: emulated and self, both of wich are unaccessible.
public class MainActivity extends AppCompatActivity {
private static final String SD_PATH = Environment.getExternalStorageDirectory().getPath();
...
File home = new File(SD_PATH);
File[] listOfFiles = home.listFiles();
if(listOfFiles != null && listOfFiles.length > 0){
for (File file : home.listFiles()){
songs.add(file.getName());
}
}
Here is my AndroidManifest.xml:
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.unimusic">
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>
<application
android:allowBackup="true"
android:icon="#mipmap/ic_launcher"
android:label="#string/app_name"
android:supportsRtl="true"
android:theme="#style/AppTheme">
<activity android:name=".MainActivity">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
</application>
</manifest>
This same thing has burned me in the past.
To quote the docs
Beginning in Android 6.0 (API level 23), users grant permissions to apps while the app is running, not when they install the app.
(see here)
Reading from the file system is one of the permissions that must now be requested at run time in order to use. This is only an issue if you target SDK 23 or later. So how to fix:
The docs show an example (see here for the original) that I have modified for your use case (I have not run this code, but it should be a good starting point). You probably want to request permissions in the onCreate() for the Activity that is going to need the permission (in your case the MainActivity).
// Ask for the read external storage permission
if (ContextCompat.checkSelfPermission(this, Manifest.permission.READ_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED)
{
// Should we show an explanation?
if (ActivityCompat.shouldShowRequestPermissionRationale(this,
Manifest.permission.READ_EXTERNAL_STORAGE))
{
// Provide an additional rationale to the user if the permission was not granted
// and the user would benefit from additional context for the use of the permission.
// Display a SnackBar with a button to request the missing permission.
Snackbar.make(layout,
"External storage is needed in order to {YOUR EXPLANATION HERE}",
Snackbar.LENGTH_INDEFINITE).setAction("OK", new View.OnClickListener()
{
#Override
public void onClick(View view)
{
// Request the permission
ActivityCompat.requestPermissions(MainActivity.this,
new String[]{Manifest.permission.READ_EXTERNAL_STORAGE}, 0);
}
}).show();
}
else
{
// No explanation needed, we can request the permission.
ActivityCompat.requestPermissions(this,
new String[]{Manifest.permission.READ_EXTERNAL_STORAGE}, 0);
}
}
Related
I'm having some trouble with Intent Action_Call. I put the permission in Manifest, but it doesn't work. I press the button to Call and nothing happens. The app that I'm making is an app that does multiple Intents so the code isn't in MainActivity. I don't know if it helps, but I'm using API 28.
Thanks for reading.
MANIFEST:
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.intentsimplicitas">
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.CALL_PHONE"/>
<uses-permission android:name="android.permission.READ_SMS" />
<uses-permission android:name="android.permission.WRITE_SMS" />
<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=".SmsActivity"></activity>
<activity android:name=".DialActivity" />
<activity android:name=".WaysActivity" />
<activity android:name=".MapActivity" />
<activity android:name=".PageActivity" />
<activity android:name=".MainActivity">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
</application>
JAVA (DialActivity.java)
public class DialActivity extends Activity {
Button btnDial;
EditText edtPhone;
String phone;
Intent it;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_dial);
btnDial = (Button)findViewById(R.id.btnDial);
edtPhone = (EditText)findViewById(R.id.edtPhone);
}
public void dialClick (View v) {
phone = edtPhone.getText().toString();
Uri uri = Uri.parse("tel: " + phone);
it = new Intent(Intent.ACTION_CALL);
it.setData(uri);
startActivity(it);
}
}
From https://developer.android.com/training/permissions/requesting:
Requesting permission:
// Here, thisActivity is the current activity
if (ContextCompat.checkSelfPermission(thisActivity,
Manifest.permission.CALL_PHONE)
!= PackageManager.PERMISSION_GRANTED) {
// Permission is not granted
// Should we show an explanation?
if (ActivityCompat.shouldShowRequestPermissionRationale(thisActivity,
Manifest.permission.CALL_PHONE)) {
// Show an explanation to the user *asynchronously* -- don't block
// this thread waiting for the user's response! After the user
// sees the explanation, try again to request the permission.
} else {
// No explanation needed; request the permission
ActivityCompat.requestPermissions(thisActivity,
new String[]{Manifest.permission.CALL_PHONE},
MY_PERMISSIONS_REQUEST_CALL_PHONE);
// MY_PERMISSIONS_REQUEST_CALL_PHONE is an
// app-defined int constant. The callback method gets the
// result of the request.
}
} else {
// Permission has already been granted
}
Verifying:
#Override
public void onRequestPermissionsResult(int requestCode,
String[] permissions, int[] grantResults) {
switch (requestCode) {
case MY_PERMISSIONS_REQUEST_CALL_PHONE: {
// If request is cancelled, the result arrays are empty.
if (grantResults.length > 0
&& grantResults[0] == PackageManager.PERMISSION_GRANTED) {
// permission was granted, yay! Do the
// contacts-related task you need to do.
} else {
// permission denied, boo! Disable the
// functionality that depends on this permission.
}
return;
}
// other 'case' lines to check for other
// permissions this app might request.
}
}
You can do via Intent
public void dialClick (View v) {
phone = edtPhone.getText().toString();
Uri uri = Uri.parse("tel: " + phone);
it = new Intent(Intent.ACTION_DIAL);
it.setData(uri);
startActivity(it);
}
You need to add the permissions at run time to be able to make the call, I recommend the following library, since it is much easier to implement the permissions in time of execution.
https://github.com/Karumi/Dexter
The main reason I'm posting here is that I'm currently stuck without a computer that can run an emulator, I've been having to send the APK to my phone to test it. Even if my phone's connected to my computer, or I have a third party emulator running, it wont work. Due to this...I have no error logs.
The app is a simple password manager, and all the other functions thus far work. I was trying to add an export function, I can't get either to actually write anything. I've checked other questions and various sources online, but I cannot seem to figure out what could be causing it. When the method is called, it simply doesn't do anything as far as I can tell. I apologize if I'm missing something, or if there was indeed another question with the same issue. I couldn't find anything missing.
Here is the method I'm using;
EDIT: The code has been updated to reflect a better method of requesting runtime permissions, which was suggested here. This ultimately is what fixed the application.
//Method017: Exports the account info to a .txt file.
public void exportData() throws IOException {
//Opens dialog to request permission.
ActivityCompat.requestPermissions(Main.this, new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE}, 1);
}
//Method to handle result of permission request.
#Override
public void onRequestPermissionsResult(int requestCode, String permissions[], int[] grantResults) {
switch (requestCode) {
case 1: {
// If request is cancelled, the result arrays are empty.
if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
//Attempt to write a file to the Download folder.
String content = "hello world";
File file;
FileOutputStream outputStream;
try {
file = new File(Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS), "MyCache");
outputStream = new FileOutputStream(file);
outputStream.write(content.getBytes());
outputStream.close();
//According to an online source, this is necessary to make the file viewable on the device.
Intent intent = new Intent(Intent.ACTION_MEDIA_SCANNER_SCAN_FILE);
intent.setData(Uri.fromFile(file));
sendBroadcast(intent);
} catch (IOException e) {
e.printStackTrace();
}
} else {
// permission denied, boo! Disable the
// functionality that depends on this permission.
Toast.makeText(Main.this, "Permission denied to read your External storage", Toast.LENGTH_SHORT).show();
}
return;
}
// other 'case' lines to check for other
// permissions this app might request
}
}
And my manifest:
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.brand.psync">
<application
android:allowBackup="true"
android:icon="#drawable/psynclogo"
android:label="#string/app_name"
android:supportsRtl="true"
android:theme="#style/AppTheme"
android:screenOrientation="portrait">
<activity android:name=".Main">
<intent-filter>
<action
android:name="android.intent.action.MAIN"
android:screenOrientation="portrait" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<category
android:name="android.intent.category.LAUNCHER"
android:screenOrientation="portrait" />
</intent-filter>
</activity>
</application>
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
</manifest>
Sorry about the lack of error log...but if I had that, I likely wouldn't need to post here.
I have try your code and it working.
public class SaveFileSampleActivity extends Activity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
TextView lblBackground = new TextView(this);
lblBackground.setBackgroundColor(Color.WHITE);
setContentView(lblBackground);
ActivityCompat.requestPermissions(SaveFileSampleActivity.this, new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE}, 1);
}
#Override
public void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults) {
switch (requestCode) {
case 1: {
// If request is cancelled, the result arrays are empty.
if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
//Attempt to write a file to the Download folder.
String content = "hello world";
File file;
FileOutputStream outputStream;
try {
file = new File(Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS), "MyCache");
outputStream = new FileOutputStream(file);
outputStream.write(content.getBytes());
outputStream.close();
//According to an online source, this is necessary to make the file viewable on the device.
Intent intent = new Intent(Intent.ACTION_MEDIA_SCANNER_SCAN_FILE);
intent.setData(Uri.fromFile(file));
sendBroadcast(intent);
} catch (IOException e) {
e.printStackTrace();
}
} else {
// permission denied, boo! Disable the
// functionality that depends on this permission.
Toast.makeText(SaveFileSampleActivity.this, "Permission denied to read your External storage", Toast.LENGTH_SHORT).show();
}
return;
}
// other 'case' lines to check for other
// permissions this app might request
}
}
}
And mainifest
<application
android:allowBackup="true"
android:icon="#mipmap/ic_launcher"
android:label="#string/app_name"
android:roundIcon="#mipmap/ic_launcher"
android:supportsRtl="true"
android:theme="#style/AppTheme">
<activity
android:name=".SaveFileSampleActivity"
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>
</application>
It's work and result:
You can review your code. I hope it can help you!
I am trying to get permissions (from users running versions of Android higher than 6.0) for ACCESS_FINE_LOCATION at runtime. This was unsuccessful in my main app so I tried making a test app with a sole purpose of requesting location permissions from the user.
The problem I am having is that no permissions dialog box is being shown to the user - from the logcat I can see that the 'onRequestPermissionsResult' method is being run straight away (without asking the user to accept permissions), and it is showing that permissions were not granted.
After looking through other questions around this topic, I have double checked that the 'uses-permission' line is in my Android Manifest XML file, but couldn't find any other solution.
Here is my code:
package com.user.testapplication;
import android.Manifest;
import android.content.pm.PackageManager;
import android.os.Build;
import android.support.v4.content.ContextCompat;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.util.Log;
public class MainActivity extends AppCompatActivity {
private static final int REQUEST_LOCATION_ID = 1;
private static final String TAG = MainActivity.class.getSimpleName();
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
checkLocationPermissions();
}
private void checkLocationPermissions(){
if (ContextCompat.checkSelfPermission(MainActivity.this,
Manifest.permission.ACCESS_FINE_LOCATION)
!= PackageManager.PERMISSION_GRANTED) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
Log.i(TAG, "Device version above 6.0 - Requesting location permissions.");
requestPermissions(new String[]{Manifest.permission.ACCESS_FINE_LOCATION},
REQUEST_LOCATION_ID);
}
}
}
#Override
public void onRequestPermissionsResult(int requestCode,
String permissions[], int[] grantResults) {
switch (requestCode) {
case REQUEST_LOCATION_ID: {
// If request is cancelled, the result arrays are empty.
if (grantResults.length > 0
&& grantResults[0] == PackageManager.PERMISSION_GRANTED) {
Log.i(TAG, "Permissions granted successfully!");
} else {
Log.i(TAG, "Permissions were not granted.");
}
return;
}
}//end switch
}
}//end class
My Manifest:
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.user.testapplication">
<uses-permission android:name="android.permisssion.ACCESS_FINE_LOCATION"/>
<application
android:allowBackup="true"
android:icon="#mipmap/ic_launcher"
android:label="#string/app_name"
android:supportsRtl="true"
android:theme="#style/AppTheme">
<activity android:name=".MainActivity">
<intent-filter>
<action android:name="android.intent.action.MAIN"/>
<category android:name="android.intent.category.LAUNCHER"/>
</intent-filter>
</activity>
</application>
And the relevant lines from the logcat:
11-27 13:27:47.752 31839-31839/com.user.testapplication I/MainActivity: Device version above 6.0 - Requesting location permissions.
11-27 13:27:47.881 31839-31839/com.user.testapplication I/MainActivity: Permissions were not granted.
Any help is much appreciated - I think I may just be missing something.
Use this in onStart() method, it will solve your issue.
//This checks for the permission
if (ContextCompat.checkSelfPermission(this, android.Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED)
{
// Should we show an explanation?
if (ActivityCompat.shouldShowRequestPermissionRationale(this, android.Manifest.permission.ACCESS_FINE_LOCATION)){
// You can show your dialog message here but instead I am
// showing the grant permission dialog box
ActivityCompat.requestPermissions(this, new String[] {
Manifest.permission.ACCESS_FINE_LOCATION,
Manifest.permission.ACCESS_COARSE_LOCATION },
10);
}
else{
//Requesting permission
ActivityCompat.requestPermissions(this, new String[] {
Manifest.permission.ACCESS_FINE_LOCATION,
Manifest.permission.ACCESS_COARSE_LOCATION },
10);
}
}
The reason for no Dialog box being shown was a typo in the AndroidManifest, you can see that the permission was spelt android-permisssion rather than android-permission.
I also had the same problem my issue was i had written following line in manifest
<permission android:name="android.permission.ACCESS_FINE_LOCATION" />
instead of
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
I'm trying to create a system overlay. But I keep getting "permission denied". I'm using SDK version 23.
My manifest file:
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.test" >
<uses-permission android:name="android.permission.SYSTEM_OVERLAY_WINDOW" />
<application
android:allowBackup="true"
android:icon="#mipmap/ic_launcher"
android:label="#string/app_name"
android:theme="#style/AppTheme" >
<activity
android:name=".activity.MainActivity"
android:label="#string/app_name" >
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
</application>
</manifest>
The code I use to create the overlay:
//mView = new HUDView(this);
mButton = new Button(this);
mButton.setText("Overlay button");
mButton.setOnTouchListener(this);
WindowManager.LayoutParams params = new WindowManager.LayoutParams(
WindowManager.LayoutParams.WRAP_CONTENT,
WindowManager.LayoutParams.WRAP_CONTENT,
WindowManager.LayoutParams.TYPE_SYSTEM_ALERT,
WindowManager.LayoutParams.FLAG_WATCH_OUTSIDE_TOUCH,
PixelFormat.TRANSLUCENT);
params.gravity = Gravity.RIGHT | Gravity.TOP;
params.setTitle("Load Average");
WindowManager wm = (WindowManager) getSystemService(WINDOW_SERVICE);
wm.addView(mButton, params);
First, there is no permission named SYSTEM_OVERLAY_WINDOW. It is SYSTEM_ALERT_WINDOW.
Second, if your targetSdkVersion is 23 or higher, and you are running on Android 6.0+ devices, your app will not get this permission at the outset. Call Settings.canDrawOverlays() to see if you have the permission, and use ACTION_MANAGE_OVERLAY_PERMISSION to lead the user over to Settings if you do not.
In AndroidManifest (for version < 23)
<uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW"/>
public static int ACTION_MANAGE_OVERLAY_PERMISSION_REQUEST_CODE= 5469;
//Random value
public void testPermission() {
if (!Settings.canDrawOverlays(this)) {
Intent intent = new Intent(Settings.ACTION_MANAGE_OVERLAY_PERMISSION,
Uri.parse("package:" + getPackageName()));
startActivityForResult(intent, ACTION_MANAGE_OVERLAY_PERMISSION_REQUEST_CODE);
}
}
Result :
#Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
if (requestCode == ACTION_MANAGE_OVERLAY_PERMISSION_REQUEST_CODE) {
if (Settings.canDrawOverlays(this)) {
// You have permission
}
}
}
You can also lead the user over to the specific app's overlaying page. The documentation states:
Input: Optionally, the Intent's data URI can specify the application package name to directly invoke the management GUI specific to the package name. For example "package:com.my.app".
So something like:
intent.setData(Uri.fromParts("package", getPackageName(), null));
As an alternative solution, you can try WindowManager.LayoutParams.TYPE_TOAST instead of WindowManager.LayoutParams.TYPE_SYSTEM_ALERT.
This not requires any permission.
I'm using it to show image, maybe button will work to
for users below and above android 8 use
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
LAYOUT_FLAG = WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY;
} else {
LAYOUT_FLAG = WindowManager.LayoutParams.TYPE_PHONE;
}
I handled all of the overlay permissions for every android version in my library. Please see the gist here.
For Display over the other apps permissions is required to add in the manifest is
<uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW" />
To check your app has permission
Settings.canDrawOverlays(context)
To check permission checkOverlayPermission
private const val CODE_DRAW_OVER_OTHER_APP_PERMISSION = 2084
private fun checkOverlayPermission(){
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M && !Settings.canDrawOverlays(this)) {
//If the draw over permission is not available open the settings screen
//to grant the permission.
val intent = Intent(
Settings.ACTION_MANAGE_OVERLAY_PERMISSION,
Uri.parse("package:$packageName")
)
startActivityForResult(
intent,
CODE_DRAW_OVER_OTHER_APP_PERMISSION
)
}
}
And in onActivityResult you can check permission is granted or not
override fun onActivityResult(
requestCode: Int,
resultCode: Int,
data: Intent?
) {
if (requestCode == CODE_DRAW_OVER_OTHER_APP_PERMISSION) {
if (Settings.canDrawOverlays(this)) {
// Permission Granted
} else {
// Permission not Granted
// If you want then call again checkOverlayPermission until permission granted
}
}
}
I'm trying to check if a file exists on my sdcard with this code but I have some problems. The API version on my Android phone is 19 and the API version of the application is 19 but there are a lot of exceptions from other application which I do not want to work with like zedge for example. Please give me some hints on how to check if that file exists.
public class MainActivity extends Activity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
File extStore = Environment.getExternalStorageDirectory();
File myFile = new File(extStore.getAbsolutePath() + "/test.txt");
if(myFile.exists()){
Log.d("File", "exists");
}
}
public boolean isExternalStorage() {
String state = Environment.getExternalStorageState();
if (Environment.MEDIA_MOUNTED.equals(state)) {
return true;
}
return false;
}
}
My Manifest file is like this:
<?xml version="1.0" encoding="utf-8"?>
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
<application
android:allowBackup="true"
android:icon="#mipmap/ic_launcher"
android:label="#string/app_name"
android:theme="#style/AppTheme" >
<activity
android:name=".MainActivity"
android:label="#string/app_name" >
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
</application>
your code just checks if file exists at sdcard/fileName.ext :
File extStore = Environment.getExternalStorageDirectory();
File myFile = new File(extStore.getAbsolutePath() + "/test.txt");
if(myFile.exists()){
Log.d("File", "exists");
}
To search entire file system (dir tree), we need a recursive function which enters a directory or compares a file with search file name:
public static boolean searchForFile(File root, File mySearchFile)
{
if(root == null || mySearchFile == null) return; //just for safety
if(root.isDirectory())
{
Boolean flag = false;
for(File file : root.listFiles()){
flag = searchForDatFiles(file, mySearchFile);
if(flag) return true;
}
}
else if(root.isFile() && root.getName().equals(mySearchFile.getName())
{
return true;
}
return false;
}
UPDATE
Just saw that you are looking for the file in root folder only. Check this link for four ways to check if file exists. Also, above code will work for sdcard only too, but not recommended because it will parse any folders it first encounter. Good for whole directory tree search.