私はそれをテストするために小さなコード部分を書きました:
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import android.app.Activity;
import android.app.AlertDialog;
import android.content.Context;
import android.content.DialogInterface;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.EditText;
import android.widget.Toast;
public class MainActivity extends Activity {
private EditText tfData;
private Button btSave, btLoad;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
tfData = (EditText) findViewById(R.id.tfData);
btSave = (Button) findViewById(R.id.btSave);
btLoad = (Button) findViewById(R.id.btLoad);
btSave.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
doSave();
}
});
btLoad.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
doLoad();
}
});
tfData.setText("Some secret data");
boolean btLoadVisible = false; // TODO change this value for the second build!
if (!btLoadVisible) {
btLoad.setVisibility(View.GONE);
}
else{
btSave.setVisibility(View.INVISIBLE);
}
}
private static final String FILENAME = "private.dat";
private void doSave() {
String text = null;
if (tfData.getText() == null) {
Toast.makeText(this, "Please enter a string!", Toast.LENGTH_SHORT).show();
return;
}
text = tfData.getText().toString();
if (text == null || text.length() == 0) {
Toast.makeText(this, "Please enter a string!!!", Toast.LENGTH_SHORT).show();
}
FileOutputStream fos = null;
try {
fos = openFileOutput(FILENAME, Context.MODE_PRIVATE);
fos.write(text.getBytes("UTF-8"));
fos.close();
fos = null;
new AlertDialog.Builder(this).setTitle("Saved").setMessage("Your data is saved:\n" + text+"\nChange the build to recover it!")
.setPositiveButton("Ok", new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int which) {
dialog.dismiss();
}
}).show();
} catch (Exception e) {
Log.e("doSave", "Can't save ...", e);
} finally {
if (fos != null) {
try {
fos.close();
} catch (IOException e) {
// I don't care:
e.printStackTrace();
}
}
}
}
private void doLoad() {
FileInputStream fis = null;
try {
fis = openFileInput(FILENAME);
} catch (FileNotFoundException e) {
e.printStackTrace();
new AlertDialog.Builder(this)
.setTitle("FileNotFoundException")
.setMessage(
"The file with data can't be found. Or it wasn't saved at all or you have uninstalled the old app or... who knows.\nI can't recover the data, it is lost permanenty!!!")
.setPositiveButton("I am sad", new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int which) {
dialog.dismiss();
}
}).show();
return; // I don't like return from catch...
}
if (fis != null) {
try {
int size = fis.available();// not the best, but now I hope is possible to read 10-30 bytes without blocking
byte[] buff = new byte[size];
int readCount = fis.read(buff);
if (readCount != size) {
Toast.makeText(this, "Dammit can't read : " + size + " bytes, only " + readCount + ". Restart app, than phone? ", Toast.LENGTH_SHORT)
.show();
}
String text = new String(buff, "UTF-8");
tfData.setText(text);
new AlertDialog.Builder(this).setTitle("Loaded").setMessage("Your data is recovered:\n" + text)
.setPositiveButton("I am happy", new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int which) {
dialog.dismiss();
}
}).show();
} catch (IOException e) {
Log.e("doLoad", "Can't load ...", e);
new AlertDialog.Builder(this).setTitle("IOException").setMessage("There is some error while reading the data:\n" + e.getMessage())
.setPositiveButton("I am sad", new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int which) {
dialog.dismiss();
}
}).show();
}
}
}
}
署名済み apk としてクリーン、ビルド、エクスポート: 例: InternalMemoryReader_save.apk
キーストアを保存してください!!!
- を に変更
boolean btLoadVisible = false
しboolean btLoadVisible = true
ます。
- 同じキーストアを使用して apk をエクスポートします。ただし、InternalMemoryReader_load.apk などの diff 名 - ただし、_datasaver _factoryservice を指定できます。これは通常、ユーザーには提供されません。
最初の apk をインストールして保存します。
結論:
あなたがアプリ開発者であり、キーストアがあり、変更された apk に署名できる場合は、その内部のプライベート ファイルにアクセスできます。
他の誰かがアプリのデータを回復するのを手伝って、あまり時間を無駄にしないことを願っています.
より良い解決策を知っている場合は、お知らせください。