0

Android アプリを作成しました。デバイスにインストールされたメール経由で送信された署名付き APK としてエクスポートします。マーケットではありません。

実行時に、同様のコードでデータを内部ストレージに保存します。

FileOutputStream fos = openFileOutput(FILENAME, Context.MODE_PRIVATE);
fos.write(string.getBytes());
fos.close();

私が知っているように-間違っている場合は修正してください-/data/data/com.mycompany.myapp/FILENAMEに保存されます

で保存されているためMODE_PRIVATE、マーケットや私の他のアプリがそれを保存できるかどうかはわかりません. たぶん、同じ署名でアプリを作成したら?

電話はルート化されていません。アプリとADBシェルで多くのバックアップ、コピーを試しました。アプリでファイルが保存されませんでした。adb shell でアクセス許可が拒否されました。

プログラミングによる解決策はありますか、それともそのファイルを取得できませんか?

4

1 に答える 1

0

私はそれをテストするために小さなコード部分を書きました:

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 = falseboolean btLoadVisible = trueます。
  • 同じキーストアを使用して apk をエクスポートします。ただし、InternalMemoryReader_load.apk などの diff 名 - ただし、_datasaver _factoryservice を指定できます。これは通常、ユーザーには提供されません。

ここに画像の説明を入力

最初の apk をインストールして保存します。

  • apk をアンインストールしないでください

  • あなたがデータ損失のせいだと提案させてください。それを開くことができません...そして、メールで一度、サポートサービスから_load.apkを受け取ります。古いapkを削除せずにインストールします。パッケージ名も署名も同じで、差分ファイル名だけです。

    データを読み込むことができました。メールで送信することも、そこで処理することもできます。最も難しい部分は完了です。

結論:

あなたがアプリ開発者であり、キーストアがあり、変更された apk に署名できる場合は、その内部のプライベート ファイルにアクセスできます。

他の誰かがアプリのデータを回復するのを手伝って、あまり時間を無駄にしないことを願っています.

より良い解決策を知っている場合は、お知らせください。

于 2013-11-07T00:47:53.233 に答える