安卓应用安全指南 4.6.1 处理文件 示例代码

简介: 安卓应用安全指南 4.6.1 处理文件 示例代码 原书:Android Application Secure Design/Secure Coding Guidebook 译者:飞龙 协议:CC BY-NC-SA 4.0如上所述,文件原则上应该是私有的。

安卓应用安全指南 4.6.1 处理文件 示例代码

原书:Android Application Secure Design/Secure Coding Guidebook

译者:飞龙

协议:CC BY-NC-SA 4.0

如上所述,文件原则上应该是私有的。 但是,由于某些原因,有时文件应该由其他应用直接读写。 按照安全角度分类和比较中文件类型如表 4.6-1 所示。 它们根据文件存储位置或其他应用的访问权限分为四类。 下面展示了每个文件类别的示例代码,并在其中添加了每个的解释。

表 4.6-1 按照安全角度的文件类别和比较

文件类别 其它应用的访问权限 储存位置 概述
私有文件 NA 应用目录中 (1)只能在应用中读写,(2)可以处理敏感数据,(3)文件原则上应该是这个类型
只读公共文件 读 应用目录中 (1)其它应用和用户可读,(2)可以处理公开给应用外部的信息
读写公共文件 读写 应用目录中 (1)其它应用和用户可以读写,(2)从安全和应用设计角度来看,不应该使用
外部存储设备(读写文件) 读写 外部存储设备,例如 SD 卡 (1)没有访问控制,(2)其它应用和用户总是可以读写或删除文件,(3)应该以最小需求使用,(4)可以处理很大的文件

4.6.1.1 使用私有文件

这种情况下使用的文件,只能在同一个应用中读取/写入,并且这是使用文件的一种非常安全的方式。 原则上,无论存储在文件中的信息是否是公开的,尽可能使用私有文件,当与其他应用交换必要的信息时,应该使用另一个 Android 系统(内容供应器,服务)来完成。

要点:

1) 文件必须在应用目录中创建。

2) 文件的访问权限必须设置为私有模式,以免其他应用使用。

3) 可以存储敏感信息。

4) 对于存储在文件中的信息,请仔细和安全地处理文件数据。

PrivateFileActivity.java

package org.jssec.android.file.privatefile;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import android.app.Activity;
import android.os.Bundle;
import android.view.View;
import android.widget.TextView;
public class PrivateFileActivity extends Activity {
    private TextView mFileView;
    private static final String FILE_NAME = "private_file.dat";

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.file);
        mFileView = (TextView) findViewById(R.id.file_view);
    }

    /**
    * Create file process
    *
    * @param view
    */
    public void onCreateFileClick(View view) {
        FileOutputStream fos = null;
        try {
            // *** POINT 1 *** Files must be created in application directory.
            // *** POINT 2 *** The access privilege of file must be set private mode in order not to be used by other applications.
            fos = openFileOutput(FILE_NAME, MODE_PRIVATE);
            // *** POINT 3 *** Sensitive information can be stored.
            // *** POINT 4 *** Regarding the information to be stored in files, handle file data carefully and securely.
            // Omitted, since this is a sample. Please refer to "3.2 Handling Input Data Carefully and Securely."
            fos.write(new String("Not sensotive information (File Activity)¥n").getBytes());
        } catch (FileNotFoundException e) {
            mFileView.setText(R.string.file_view);
        } catch (IOException e) {
            android.util.Log.e("PrivateFileActivity", "failed to read file");
        } finally {
            if (fos != null) {
                try {
                    fos.close();
                } catch (IOException e) {
                    android.util.Log.e("PrivateFileActivity", "failed to close file");
                }
            }
        }
        finish();
    }

    /**
    * Read file process
    *
    * @param view
    */
    public void onReadFileClick(View view) {
        FileInputStream fis = null;
        try {
            fis = openFileInput(FILE_NAME);
            byte[] data = new byte[(int) fis.getChannel().size()];
            fis.read(data);
            String str = new String(data);
            mFileView.setText(str);
        } catch (FileNotFoundException e) {
            mFileView.setText(R.string.file_view);
        } catch (IOException e) {
            android.util.Log.e("PrivateFileActivity", "failed to read file");
        } finally {
            if (fis != null) {
                try {
                    fis.close();
                } catch (IOException e) {
                    android.util.Log.e("PrivateFileActivity", "failed to close file");
                }
            }
        }
    }

    /**
    * Delete file process
    *
    * @param view
    */
    public void onDeleteFileClick(View view) {
        File file = new File(this.getFilesDir() + "/" + FILE_NAME);
        file.delete();
        mFileView.setText(R.string.file_view);
    }
}

PrivateUserActivity.java

package org.jssec.android.file.privatefile;

import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import android.app.Activity;
import android.content.Intent;
import android.os.Bundle;
import android.view.View;
import android.widget.TextView;

public class PrivateUserActivity extends Activity {

    private TextView mFileView;
    private static final String FILE_NAME = "private_file.dat";

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.user);
        mFileView = (TextView) findViewById(R.id.file_view);
    }

    private void callFileActivity() {
        Intent intent = new Intent();
        intent.setClass(this, PrivateFileActivity.class);
        startActivity(intent);
    }

    /**
    * Call file Activity process
    *
    * @param view
    */
    public void onCallFileActivityClick(View view) {
        callFileActivity();
    }

    /**
    * Read file process
    *
    * @param view
    */
    public void onReadFileClick(View view) {
        FileInputStream fis = null;
        try {
            fis = openFileInput(FILE_NAME);
            byte[] data = new byte[(int) fis.getChannel().size()];
            fis.read(data);
            // *** POINT 4 *** Regarding the information to be stored in files, handle file data carefully and securely.
            // Omitted, since this is a sample. Please refer to "3.2 Handling Input Data Carefully and Securely."
            String str = new String(data);
            mFileView.setText(str);
        } catch (FileNotFoundException e) {
            mFileView.setText(R.string.file_view);
        } catch (IOException e) {
            android.util.Log.e("PrivateUserActivity", "failed to read file");
        } finally {
            if (fis != null) {
                try {
                    fis.close();
                } catch (IOException e) {
                    android.util.Log.e("PrivateUserActivity", "failed to close file");
                }
            }
        }
    }

    /**
    * Rewrite file process
    *
    * @param view
    */
    public void onWriteFileClick(View view) {
        FileOutputStream fos = null;
        try {
            // *** POINT 1 *** Files must be created in application directory.
            // *** POINT 2 *** The access privilege of file must be set private mode in order not to be used by other applications.
            fos = openFileOutput(FILE_NAME, MODE_APPEND);
            // *** POINT 3 *** Sensitive information can be stored.
            // *** POINT 4 *** Regarding the information to be stored in files, handle file data carefully and securely.
            // Omitted, since this is a sample. Please refer to "3.2 Handling Input Data Carefully and Securely."
            fos.write(new String("Sensitive information (User Activity)¥n").getBytes());
        } catch (FileNotFoundException e) {
            mFileView.setText(R.string.file_view);
        } catch (IOException e) {
            android.util.Log.e("PrivateUserActivity", "failed to read file");
        } finally {
            if (fos != null) {
                try {
                    fos.close();
                } catch (IOException e) {
                    android.util.Log.e("PrivateUserActivity", "failed to close file");
                }
            }
        }
        callFileActivity();
    }
}

4.6.1.2 使用公共只读文件

这是使用文件向未指定的大量应用公开内容的情况。 如果通过遵循以下几点来实现,那么它也是比较安全的文件使用方法。 请注意,在 API 级别 1 7及更高版本中,不推荐使用MODE_WORLD_READABLE变量来创建公共文件,并且在 API 级别 24 及更高版本中,会触发安全异常; 因此使用内容供应器的文件共享方法更可取。

要点:

1) 文件必须在应用目录中创建。

2) 文件的访问权限必须设置为其他应用只读。

3) 敏感信息不得存储。

4) 对于要存储在文件中的信息,请仔细和安全地处理文件数据。

PublicFileActivity.java

package org.jssec.android.file.publicfile.readonly;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import android.app.Activity;
import android.os.Bundle;
import android.view.View;
import android.widget.TextView;

public class PublicFileActivity extends Activity {

    private TextView mFileView;
    private static final String FILE_NAME = "public_file.dat";

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.file);
        mFileView = (TextView) findViewById(R.id.file_view);
    }

    /**
    * Create file process
    *
    * @param view
    */
    public void onCreateFileClick(View view) {
        FileOutputStream fos = null;
        try {
            // *** POINT 1 *** Files must be created in application directory.
            // *** POINT 2 *** The access privilege of file must be set to read only to other applications.
            // (MODE_WORLD_READABLE is deprecated API Level 17,
            // don't use this mode as much as possible and exchange data by using ContentProvider().)
            fos = openFileOutput(FILE_NAME, MODE_WORLD_READABLE);
            // *** POINT 3 *** Sensitive information must not be stored.
            // *** POINT 4 *** Regarding the information to be stored in files, handle file data carefully and securely.
            // Omitted, since this is a sample. Please refer to "3.2 Handling Input Data Carefully and Securely."
            fos.write(new String("Not sensitive information (Public File Activity)¥n").getBytes());
        } catch (FileNotFoundException e) {
            mFileView.setText(R.string.file_view);
        } catch (IOException e) {
            android.util.Log.e("PublicFileActivity", "failed to read file");
        } finally {
            if (fos != null) {
                try {
                    fos.close();
                } catch (IOException e) {
                    android.util.Log.e("PublicFileActivity", "failed to close file");
                }
            }
        }
        finish();
    }

    /**
    * Read file process
    *
    * @param view
    */
    public void onReadFileClick(View view) {
        FileInputStream fis = null;
        try {
            fis = openFileInput(FILE_NAME);
            byte[] data = new byte[(int) fis.getChannel().size()];
            fis.read(data);
            String str = new String(data);
            mFileView.setText(str);
        } catch (FileNotFoundException e) {
            mFileView.setText(R.string.file_view);
        } catch (IOException e) {
            android.util.Log.e("PublicFileActivity", "failed to read file");
        } finally {
            if (fis != null) {
                try {
                    fis.close();
                } catch (IOException e) {
                    android.util.Log.e("PublicFileActivity", "failed to close file");
                }
            }
        }
    }

    /**
    * Delete file process
    *
    * @param view
    */
    public void onDeleteFileClick(View view) {
        File file = new File(this.getFilesDir() + "/" + FILE_NAME);
        file.delete();
        mFileView.setText(R.string.file_view);
    }
}

PublicUserActivity.java

package org.jssec.android.file.publicuser.readonly;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import android.app.Activity;
import android.content.ActivityNotFoundException;
import android.content.Context;
import android.content.Intent;
import android.content.pm.PackageManager.NameNotFoundException;
import android.os.Bundle;
import android.view.View;
import android.widget.TextView;

public class PublicUserActivity extends Activity {

    private TextView mFileView;
    private static final String TARGET_PACKAGE = "org.jssec.android.file.publicfile.readonly";
    private static final String TARGET_CLASS = "org.jssec.android.file.publicfile.readonly.PublicFileActivity";
    private static final String FILE_NAME = "public_file.dat";

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.user);
        mFileView = (TextView) findViewById(R.id.file_view);
    }

    private void callFileActivity() {
        Intent intent = new Intent();
        intent.setClassName(TARGET_PACKAGE, TARGET_CLASS);
        try {
            startActivity(intent);
        } catch (ActivityNotFoundException e) {
            mFileView.setText("(File Activity does not exist)");
        }
    }

    /**
    * Call file Activity process
    *
    * @param view
    */
    public void onCallFileActivityClick(View view) {
        callFileActivity();
    }

    /**
    * Read file process
    *
    * @param view
    */
    public void onReadFileClick(View view) {
        FileInputStream fis = null;
        try {
            File file = new File(getFilesPath(FILE_NAME));
            fis = new FileInputStream(file);
            byte[] data = new byte[(int) fis.getChannel().size()];
            fis.read(data);
            // *** POINT 4 *** Regarding the information to be stored in files, handle file data carefully and securely.
            // Omitted, since this is a sample. Please refer to "3.2 Handling Input Data Carefully and Securely."
            String str = new String(data);
            mFileView.setText(str);
        } catch (FileNotFoundException e) {
            android.util.Log.e("PublicUserActivity", "no file");
        } catch (IOException e) {
            android.util.Log.e("PublicUserActivity", "failed to read file");
        } finally {
            if (fis != null) {
                try {
                    fis.close();
                } catch (IOException e) {
                    android.util.Log.e("PublicUserActivity", "failed to close file");
                }
            }
        }
    }

    /**
    * Rewrite file process
    *
    * @param view
    */
    public void onWriteFileClick(View view) {
        FileOutputStream fos = null;
        boolean exception = false;
        try {
            File file = new File(getFilesPath(FILE_NAME));
            // Fail to write in. FileNotFoundException occurs.
            fos = new FileOutputStream(file, true);
            fos.write(new String("Not sensitive information (Public User Activity)¥n").getBytes());
        } catch (IOException e) {
            mFileView.setText(e.getMessage());
            exception = true;
        } finally {
            if (fos != null) {
                try {
                    fos.close();
                } catch (IOException e) {
                    exception = true;
                }
            }
        }
        if (!exception)
            callFileActivity();
    }

    private String getFilesPath(String filename) {
        String path = "";
        try {
            Context ctx = createPackageContext(TARGET_PACKAGE,
            Context.CONTEXT_RESTRICTED);
            File file = new File(ctx.getFilesDir(), filename);
            path = file.getPath();
        } catch (NameNotFoundException e) {
            android.util.Log.e("PublicUserActivity", "no file");
        }
        return path;
    }
}

4.6.1.3 创建公共读写文件

这是一种文件用法,它允许未指定的大量应用的读写访问。

未指定的大量应用可以读写,意思不用多说了。 恶意软件也可以读取和写入,因此数据的可信度和安全性将永远不会得到保证。 另外,即使在没有恶意的情况下,也不能控制文件中的数据格式或写入的时间。 所以这种类型的文件在功能方面几乎不实用。

如上所述,从安全性和应用设计的角度来看,不可能安全地使用读写文件,因此应该避免使用读写文件。

要点:

不要创建允许来自其他应用的读写操作的文件。

4.6.1.4 使用外部存储器(公共读写)文件

将文件存储在 SD 卡等外部存储器中时,就是这种情况。当存储比较庞大的信息(放置从 Web 下载的文件)或者将信息带出到外部时(备份等)时,应该使用它。

对于未指定的大量应用,“外部存储器文件(公共读写)”与“公共读写文件“有相同特性。另外,对于声明使用android.permission.WRITE_EXTERNAL_STORAGE权限的应用,它和“公共读写文件”具有相同的特性。因此,应尽可能减少“外部存储器(公共读写)文件”的使用。

按照 Android 应用的惯例,备份文件很可能是在外部存储器中创建的。但是,如上所述,外部存储器中的文件存在被其他应用(包括恶意软件)篡改/删除的风险。因此,在输出备份的应用中,为了最小化应用规范或设计方面的风险,一些设计是必要的,例如显示“尽快将备份文件复制到 PC 等安全位置”。

要点:

1) 不得存储敏感信息。

2) 文件必须存储在每个应用的唯一目录中。

3) 对于要存储在文件中的信息,请仔细和安全地处理文件数据。

4) 请求应用的文件写入应该按照规范禁止。

AndroidManifest.xml

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="org.jssec.android.file.externalfile" >
    <!-- declare android.permission.WRITE_EXTERNAL_STORAGE permission to write to the external strage --
    >
    <!-- In Android 4.4 (API Level 19) and later, the application, which read/write only files in its sp
    ecific
    directories on external storage media, need not to require the permission and it should declare
    the maxSdkVersion -->
    <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"
    android:maxSdkVersion="18"/>
    <application
        android:icon="@drawable/ic_launcher"
        android:label="@string/app_name"
        android:allowBackup="false" >
        <activity
            android:name=".ExternalFileActivity"
            android:label="@string/app_name"
            android:exported="true" >
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />
                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
    </application>
</manifest>

ExternalFileActivity.java

package org.jssec.android.file.externalfile;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import android.app.Activity;
import android.os.Bundle;
import android.view.View;
import android.widget.TextView;

public class ExternalFileActivity extends Activity {

    private TextView mFileView;
    private static final String TARGET_TYPE = "external";
    private static final String FILE_NAME = "external_file.dat";

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.file);
        mFileView = (TextView) findViewById(R.id.file_view);

    }
    /**
    * Create file process
    *
    * @param view
    */
    public void onCreateFileClick(View view) {
        FileOutputStream fos = null;
        try {
            // *** POINT 1 *** Sensitive information must not be stored.
            // *** POINT 2 *** Files must be stored in the unique directory per application.
            File file = new File(getExternalFilesDir(TARGET_TYPE), FILE_NAME);
            fos = new FileOutputStream(file, false);
            // *** POINT 3 *** Regarding the information to be stored in files, handle file data carefully and securely.
            // Omitted, since this is a sample. Please refer to "3.2 Handling Input Data Carefully and Securely."
            fos.write(new String("Non-Sensitive Information(ExternalFileActivity)¥n")
            .getBytes());
        } catch (FileNotFoundException e) {
            mFileView.setText(R.string.file_view);
        } catch (IOException e) {
            android.util.Log.e("ExternalFileActivity", "failed to read file");
        } finally {
            if (fos != null) {
                try {
                    fos.close();
                } catch (IOException e) {
                    android.util.Log.e("ExternalFileActivity", "failed to close file");
                }
            }
        }
        finish();
    }

    /**
    * Read file process
    *
    * @param view
    */
    public void onReadFileClick(View view) {
        FileInputStream fis = null;
        try {
            File file = new File(getExternalFilesDir(TARGET_TYPE), FILE_NAME);
            fis = new FileInputStream(file);
            byte[] data = new byte[(int) fis.getChannel().size()];
            fis.read(data);
            // *** POINT 3 *** Regarding the information to be stored in files, handle file data carefully and securely.
            // Omitted, since this is a sample. Please refer to "3.2 Handling Input Data Carefully and Securely."
            String str = new String(data);
            mFileView.setText(str);
        } catch (FileNotFoundException e) {
            mFileView.setText(R.string.file_view);
        } catch (IOException e) {
            android.util.Log.e("ExternalFileActivity", "failed to read file");
        } finally {
            if (fis != null) {
                try {
                    fis.close();
                } catch (IOException e) {
                    android.util.Log.e("ExternalFileActivity", "failed to close file");
                }
            }
        }
    }

    /**
    * Delete file process
    *
    * @param view
    */
    public void onDeleteFileClick(View view) {
        File file = new File(getExternalFilesDir(TARGET_TYPE), FILE_NAME);
        file.delete();
        mFileView.setText(R.string.file_view);
    }
}

使用的示例代码:

ExternalFileUser.java

package org.jssec.android.file.externaluser;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import android.app.Activity;
import android.app.AlertDialog;
import android.content.ActivityNotFoundException;
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import android.content.pm.PackageManager.NameNotFoundException;
import android.os.Bundle;
import android.view.View;
import android.widget.TextView;

public class ExternalUserActivity extends Activity {

    private TextView mFileView;
    private static final String TARGET_PACKAGE = "org.jssec.android.file.externalfile";
    private static final String TARGET_CLASS = "org.jssec.android.file.externalfile.ExternalFileActivity";
    private static final String TARGET_TYPE = "external";
    private static final String FILE_NAME = "external_file.dat";

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.user);
        mFileView = (TextView) findViewById(R.id.file_view);
    }
    private void callFileActivity() {
        Intent intent = new Intent();
        intent.setClassName(TARGET_PACKAGE, TARGET_CLASS);
        try {
            startActivity(intent);
        } catch (ActivityNotFoundException e) {
            mFileView.setText("(File Activity does not exist)");
        }
    }

    /**
    * Call file Activity process
    *
    * @param view
    */
    public void onCallFileActivityClick(View view) {
        callFileActivity();
    }

    /**
    * Read file process
    *
    * @param view
    */
    public void onReadFileClick(View view) {
        FileInputStream fis = null;
        try {
            File file = new File(getFilesPath(FILE_NAME));
            fis = new FileInputStream(file);
            byte[] data = new byte[(int) fis.getChannel().size()];
            fis.read(data);
            // *** POINT 3 *** Regarding the information to be stored in files, handle file data carefully and securely.
            // Omitted, since this is a sample. Please refer to "3.2 Handling Input Data Carefully and Securely."
            String str = new String(data);
            mFileView.setText(str);
        } catch (FileNotFoundException e) {
            mFileView.setText(R.string.file_view);
        } catch (IOException e) {
            android.util.Log.e("ExternalUserActivity", "failed to read file");
        } finally {
            if (fis != null) {
                try {
                    fis.close();
                } catch (IOException e) {
                    android.util.Log.e("ExternalUserActivity", "failed to close file");
                }
            }
        }
    }

    /**
    * Rewrite file process
    *
    * @param view
    */
    public void onWriteFileClick(View view) {
        // *** POINT 4 *** Writing file by the requesting application should be prohibited as the specification.
        // Application should be designed supposing malicious application may overwrite or delete file.
        final AlertDialog.Builder alertDialogBuilder = new AlertDialog.Builder(this);
        alertDialogBuilder.setTitle("POINT 4");
        alertDialogBuilder.setMessage("Do not write in calling appllication.");
        alertDialogBuilder.setPositiveButton("OK",
        new DialogInterface.OnClickListener() {
            @Override
            public void onClick(DialogInterface dialog, int which) {
                callFileActivity();
            }
        });
        alertDialogBuilder.create().show();
    }

    private String getFilesPath(String filename) {
        String path = "";
        try {
            Context ctx = createPackageContext(TARGET_PACKAGE,
            Context.CONTEXT_IGNORE_SECURITY);
            File file = new File(ctx.getExternalFilesDir(TARGET_TYPE), filename);
            path = file.getPath();
        } catch (NameNotFoundException e) {
            android.util.Log.e("ExternalUserActivity", "no file");
        }
        return path;
    }
}

AndroidManifest.xml

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="org.jssec.android.file.externaluser" >
    <!-- In Android 4.0.3 (API Level 14) and later, the permission for reading external storages
    has been defined and the application should decalre that it requires the permission.
    In fact in Android 4.4 (API Level 19) and later, that must be declared to read other directories
    than the package specific directories. -->
    <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />

    <application
        android:icon="@drawable/ic_launcher"
        android:label="@string/app_name"
        android:allowBackup="false" >
        <activity
            android:name=".ExternalUserActivity"
            android:label="@string/app_name"
            android:exported="true" >
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />
                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
    </application>
</manifest>
相关文章
|
Java Android开发 C++
Android Studio JNI 使用模板:c/cpp源文件的集成编译,快速上手
本文提供了一个Android Studio中JNI使用的模板,包括创建C/C++源文件、编辑CMakeLists.txt、编写JNI接口代码、配置build.gradle以及编译生成.so库的详细步骤,以帮助开发者快速上手Android平台的JNI开发和编译过程。
1642 1
|
移动开发 安全 Java
Android历史版本与APK文件结构
通过以上内容,您可以全面了解Android的历史版本及其主要特性,同时掌握APK文件的结构和各部分的作用。这些知识对于理解Android应用的开发和发布过程非常重要,也有助于在实际开发中进行高效的应用管理和优化。希望这些内容对您的学习和工作有所帮助。
1981 83
|
ARouter Android开发
Android不同module布局文件重名被覆盖
Android不同module布局文件重名被覆盖
|
Android开发 开发者
Android自定义View之不得不知道的文件attrs.xml(自定义属性)
本文详细介绍了如何通过自定义 `attrs.xml` 文件实现 Android 自定义 View 的属性配置。以一个包含 TextView 和 ImageView 的 DemoView 为例,讲解了如何使用自定义属性动态改变文字内容和控制图片显示隐藏。同时,通过设置布尔值和点击事件,实现了图片状态的切换功能。代码中展示了如何在构造函数中解析自定义属性,并通过方法 `setSetting0n` 和 `setbackeguang` 实现功能逻辑的优化与封装。此示例帮助开发者更好地理解自定义 View 的开发流程与 attrs.xml 的实际应用。
564 2
Android自定义View之不得不知道的文件attrs.xml(自定义属性)
|
Java Android开发
Android studio中build.gradle文件简单介绍
本文解析了Android项目中build.gradle文件的作用,包括jcenter仓库配置、模块类型定义、包名设置及依赖管理,涵盖本地、库和远程依赖的区别。
1283 19
|
存储 XML Java
Android 文件数据储存之内部储存 + 外部储存
简介:本文详细介绍了Android内部存储与外部存储的使用方法及核心原理。内部存储位于手机内存中,默认私有,适合存储SharedPreferences、SQLite数据库等重要数据,应用卸载后数据会被清除。外部存储包括公共文件和私有文件,支持SD卡或内部不可移除存储,需申请权限访问。文章通过代码示例展示了如何保存、读取、追加、删除文件以及将图片保存到系统相册的操作,帮助开发者理解存储机制并实现相关功能。
3300 2
|
存储 安全 Android开发
探索Android系统的最新安全特性
在数字时代,智能手机已成为我们生活中不可或缺的一部分。随着技术的不断进步,手机操作系统的安全性也越来越受到重视。本文将深入探讨Android系统最新的安全特性,包括其设计理念、实施方式以及对用户的影响。通过分析这些安全措施如何保护用户免受恶意软件和网络攻击的威胁,我们希望为读者提供对Android安全性的全面了解。
|
算法 安全 Java
即时通讯安全篇(一):正确地理解和使用Android端加密算法
本文主要讨论针对Android这样的移动端应用开发时,如何正确的理解目前常用的加密算法,为诸如即时通讯应用的实战开发,如何在合适的场景下选择适合的算法,提供一些参考。
649 0
|
存储 监控 数据库
Android经典实战之OkDownload的文件分段下载及合成原理
本文介绍了 OkDownload,一个高效的 Android 下载引擎,支持多线程下载、断点续传等功能。文章详细描述了文件分段下载及合成原理,包括任务创建、断点续传、并行下载等步骤,并展示了如何通过多种机制保证下载的稳定性和完整性。
1015 1
|
开发工具 git 索引
repo sync 更新源码 android-12.0.0_r34, fatal: 不能重置索引文件至版本 ‘v2.27^0‘。
本文描述了在更新AOSP 12源码时遇到的repo同步错误,并提供了通过手动git pull更新repo工具来解决这一问题的方法。
1056 1

热门文章

最新文章