Permisssion denied while attaching apk file with GMail app android
Asked Answered
G

1

0

I have a requirement to send a apk file through share Intent and I have also implemented without any hassle. But the problem arises only while sending apk via GMail, I am getting permission denied while i try to attach. I really dont know what is happening with GMail. Kindly help me through your answers and solutions. Any Small hint and tips would also be useful for me. Thanks in advance

I am using following code to send APK using shared intents:

 public static void appSend(ArrayList<File> files,Context context){
        Intent shareIntent = new Intent(Intent.ACTION_SEND_MULTIPLE);
        shareIntent.setType("application/vnd.android.package-archive");
        shareIntent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_WHEN_TASK_RESET);
        ArrayList<Uri> uriFiles = new ArrayList<Uri> ();
        for(File file: files) {
            uriFiles.add (Uri.fromFile (file));
        }
        shareIntent.putParcelableArrayListExtra (Intent.EXTRA_STREAM, uriFiles);

        try {
            context.startActivity (Intent.createChooser (shareIntent, "Share via"));
        } catch (android.content.ActivityNotFoundException ex) {
            Toast.makeText (context, "There are no share applications installed.", Toast.LENGTH_SHORT).show();
        }
    }

Androidmanifest.xml:

    <?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.sample.share"
    android:versionCode="2"
    android:versionName="1.1">

    <uses-permission android:name="android.permission.WRITE_INTERNAL_STORAGE" />
    <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />

    <uses-permission android:name="ANDROID.PERMISSION.READ_EXTERNAL_STORAGE"/>

    <uses-feature
        android:glEsVersion="0x00020000"
        android:required="true" />

    <application
        android:allowBackup="true"
        android:icon="@mipmap/ic_launcher"
        android:label="@string/app_name">
        <activity
            android:name="com.sample.share.SplashActivity"
            android:label="@string/app_name"
            android:theme="@style/Theme.AppCompat.Light.NoActionBar.FullScreen">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />

                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>

        <activity
            android:name="com.sample.share.LandingScreenActivity"
            android:label="@string/app_name"
            android:theme="@style/Theme.AppCompat.Light.NoActionBar.FullScreen"/>

        <activity
            android:name="com.sample.share.MainActivity"
            android:label="@string/app_name"
            android:theme="@style/ShareToolbar"/>
    </application>

</manifest>

Adapter class to fetch the list of apps present in the device
ShowAppsAdapter.java

public class ShowAppsAdapter extends RecyclerView.Adapter<ShowAppsAdapter.ViewHolder> implements Filterable{
    private Context context;
    private static List pkgAppsList;
    private List pkgAppsListOriginal;
    private int mLayout;
    private ArrayList<File> mFileList;
    static OnItemClickListener mItemClickListener;

    private ItemFilter filter = new ItemFilter();
    private HashMap<String,Boolean> itemChecked = new HashMap<String,Boolean>();
    private Typeface tf;

    public ShowAppsAdapter(Context context, List pkgAppsList, int layout, Typeface tf) {
        this.context = context;
        this.pkgAppsList = pkgAppsList;
        this.pkgAppsListOriginal = pkgAppsList;
        this.mLayout = layout;
        this.mFileList = new ArrayList<File> ();
        this.tf = tf;

        for (int i = 0; i < this.getItemCount (); i++) {
            itemChecked.put ((String) ((ResolveInfo) pkgAppsList.get (i)).loadLabel (context.getPackageManager ()), false); // initializes all items value with false
        }
    }

    @Override
    public ViewHolder onCreateViewHolder(ViewGroup viewGroup, int i) {

        View v = LayoutInflater.from(viewGroup.getContext()).inflate(mLayout, viewGroup, false);


        return new ViewHolder(v);
    }




    @Override
    public void onBindViewHolder(final ViewHolder holder, final int position) {

        final ResolveInfo info = (ResolveInfo) pkgAppsList.get(position);
        final File file = new File(info.activityInfo.applicationInfo.publicSourceDir);
        String appSize= (Utils.getFileSize(context, info.activityInfo.applicationInfo.sourceDir));

        holder.txtAppName.setText(info.loadLabel(context.getPackageManager()));


        holder.txtAppSize.setText(/*info.activityInfo.packageName*/""+appSize);

        holder.txtAppName.setTypeface(tf);
        holder.txtAppSize.setTypeface(tf);

        holder.txtAppIcon.setImageDrawable(info.loadIcon(context.getPackageManager()));

        holder.chkTick.setChecked(itemChecked.get(info.loadLabel (context.getPackageManager ())));
        holder.chkTick.setOnClickListener (new View.OnClickListener () {
            @Override
            public void onClick (View view) {

                toggleSelected((String) info.loadLabel (context.getPackageManager ()), holder.chkTick.isChecked(),  file);

            }
        });
    }


    private void toggleSelected (String name, boolean b, File file) {
        itemChecked.put (name,b);
        if(b){
            addAppList(file);
        }else{
            removeAppList(file);
        }
    }


    private void addAppList (File file) {

        mFileList.add (file);
    }

    private void removeAppList (File file) {

        mFileList.remove (file);
    }

    public ArrayList<File> getAppList(){


        return mFileList;
    }

    @Override
    public int getItemCount() {
        return pkgAppsList == null ? 0 : pkgAppsList.size();
    }

    @Override
    public Filter getFilter () {
        return filter;
    }




    public static class ViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener {
        TextView txtAppName;
        TextView txtAppSize;
        ImageView txtAppIcon;
        CheckBox chkTick;

        public ViewHolder(View itemView) {
            super(itemView);
            txtAppName = (TextView)itemView.findViewById(R.id.text_app_name);
            txtAppSize = (TextView)itemView.findViewById(R.id.txt_app_size);
            txtAppIcon = (ImageView)itemView.findViewById(R.id.img_app_icon);
            chkTick = (CheckBox)itemView.findViewById (R.id.chk_tick);
            itemView.setOnClickListener(this);

        }



        @Override
        public void onClick(View v) {
            mItemClickListener.onItemClick(v, getAdapterPosition (),((ResolveInfo)pkgAppsList.get (getAdapterPosition ()))); //OnItemClickListener mItemClickListener;
        }

    }


    public interface OnItemClickListener {
        public void onItemClick (View view, int position, ResolveInfo o);
    }

    public void SetOnItemClickListener(final OnItemClickListener mItemClickListener) {
        this.mItemClickListener = mItemClickListener;
    }
    @Override
    public long getItemId(int i) {
        return i;
    }


    private class ItemFilter extends Filter{
        @Override
        protected FilterResults performFiltering (CharSequence charSequence) {
            String searchString = charSequence.toString ().toLowerCase ();
            FilterResults results = new FilterResults();
            final List list = pkgAppsListOriginal;

            int count = list.size();
            final List nlist = new ArrayList<ResolveInfo>(count);

            String filterableString ;

            for (int i = 0; i < count; i++) {
                final ResolveInfo info = (ResolveInfo) pkgAppsListOriginal.get(i);
                filterableString = (String) info.loadLabel (context.getPackageManager ());
                if (filterableString.toLowerCase().contains(searchString)) {
                    nlist.add(pkgAppsListOriginal.get (i));
                }
            }

            results.values = nlist;
            results.count = nlist.size();

            return results;
        }

        @Override
        protected void publishResults (CharSequence charSequence, FilterResults filterResults) {
            pkgAppsList = (List) filterResults.values;
            notifyDataSetChanged ();
        }
    }
}
Gerald answered 14/5, 2015 at 20:35 Comment(0)
S
1

When sharing files between applications, you should use a FileProvider as per the setting up file sharing training as this ensures that the receiving app can read the file without requiring any permissions. As of Android 6.0, Gmail does not request the storage permission, meaning it is unable to read any files you provide with Uri.fromFile().

You'd declare a FileProvider in your manifest:

<provider
        android:name="android.support.v4.content.FileProvider"
        android:authorities="com.example.myapp.fileprovider"
        android:grantUriPermissions="true"
        android:exported="false">
        <meta-data
            android:name="android.support.FILE_PROVIDER_PATHS"
            android:resource="@xml/filepaths" />
</provider>

An XML file (in this case called filepaths.xml to match the above manifest declaration) which determines which directories are available via the FileProvider:

<paths>
    <files-path path="images/" name="myimages" />
</paths>

Then, in place of using Uri.fromFile(file), you use FileProvider.getUriForFile(), passing in the same authority as in your manifest.

Steelwork answered 14/5, 2015 at 20:46 Comment(7)
thanks for your answer. But what would be my <file-path> to sharing apk's instead of <files-path path="images/" name="myimages" />Gerald
Also what should be given in getUriForFile 2nd paramete. I am completely struct with it. I gave "images" as second parameter but app got crashedGerald
1) you give it the path where your files are 2) the same string as the android:authorities in the manifest entrySteelwork
I am competely stuck with itGerald
I My app getting force stop once if i do like thatGerald
@Gerald - if you'd like to edit your question, adding what code you've tried, what directory you've saved the files you wish to share (the line on where you create the file, etc is fine), and of course the logcat of your error messages all would be very helpful in debugging your issues.Steelwork
@ianhanniballake- I have edited and added full source code of my project. I am completely helpless. You are my only hope. I cannot see any solutions in google. Apk attachments are working with all other third party app except GMail (Non rooted devices).Gerald

© 2022 - 2024 — McMap. All rights reserved.