【问题标题】:Unable to install .apk from app无法从应用安装 .apk
【发布时间】:2011-05-30 19:38:01
【问题描述】:

我有一个托管在 SourceForge (https://sourceforge.net/projects/pokedroid/) 上的应用程序。我决定添加一个按钮来直接从 CVS 服务器下载最新版本的应用程序。 .apk 下载正常,但是当我尝试安装它时,包安装程序会出现“无法解析包”错误。我正在使用的代码:

    private class DownloadAndInstall extends AsyncTask<String, Integer, Boolean>
{
    protected Boolean doInBackground(String... derp)
    {
        String ur=derp[0];
        String fileName=derp[1];
        ByteArrayBuffer baf = new ByteArrayBuffer(50);

        try
        {
            URL url = new URL(ur);
            URLConnection ucon = null;
            ucon = url.openConnection();

            InputStream is = ucon.getInputStream();
            BufferedInputStream bis = new BufferedInputStream(is);

            int current = 0;
            int updateCount=0;
            while ((current = bis.read()) != -1)
            {
                if(updateCount==256)
                {
                    publishProgress(baf.length());
                    updateCount=0;
                }
                baf.append((byte) current);
                updateCount++;
            }

            FileOutputStream fos = PokeDroid.openFileOutput(fileName, Context.MODE_WORLD_READABLE);
            fos.write(baf.toByteArray());
            fos.close();

        } catch (Exception e) {
            Log.e("pokedroid", e.toString());
        }

        MessageDigest digest = null;
        try {
            digest = java.security.MessageDigest.getInstance("MD5");
        } catch (NoSuchAlgorithmException e) {
            Log.e("pokedroid", e.toString());
        }
        digest.update(baf.toByteArray());
        byte[] h = digest.digest();

        if(baf.length()==0)
            return null;
        String[] fileList=fileList();
        boolean exists=false;
        for(String i:fileList)
            if(i.equals("updatehash.md5"))
                exists=true;

        String newHash=new String(h);
        Log.e("pokedroid", "new="+newHash);

        if(exists)
        {
            try
            {
                String oldHash=loadObject("updatehash.md5");
                Log.e("pokedroid", "old="+oldHash);
                if(oldHash.equals(newHash))
                    return false;
                else
                    saveObject(newHash, "updatehash.md5");
            }
            catch (Exception e)
            {
                Log.e("pokedroid",e.toString());
            }
        }
        else
        {
            try {
                saveObject(newHash, "updatehash.md5");
            } catch (IOException e) {
                Log.e("pokedroid",e.toString());
            }
        }
        return true;
    }

    protected void onProgressUpdate(Integer...integers)
    {
        p.setMessage("Downloading update...\n"+integers[0]/1000+"kb downloaded so far.");
    }

    protected void onPostExecute(Boolean b)
    {
        if(b==null)
        {
            noConnection.show();
            deleteFile("PokeDroid.apk");
            p.dismiss();
            return;
        }
        if(!b)
            noNewUpdate.show();
        else
        {
            Intent intent=new Intent();
            intent.setAction(android.content.Intent.ACTION_VIEW);
            intent.setDataAndType(Uri.parse("file:///data/data/com.games.pokedroid/files/PokeDroid.apk"), "application/vnd.android.package-archive");
            startActivity(intent);
            deleteFile("PokeDroid.apk");
        }
        p.dismiss();
    }

    public void saveObject(String obj, String filename) throws IOException
    {
        FileOutputStream fos = openFileOutput(filename,Context.MODE_PRIVATE);
        ObjectOutputStream out = new ObjectOutputStream(fos);
        out.writeObject(obj);
        out.close();
        fos.close();
    }

    public String loadObject(String filename) throws StreamCorruptedException, IOException, ClassNotFoundException
    {
        FileInputStream fis=openFileInput(filename);
        ObjectInputStream in=new ObjectInputStream(fis);
        String out=(String) in.readObject();
        in.close();
        fis.close();
        return out;
    }
}

当然,这是我的 Activity 中的一个子类。我做错了什么?

【问题讨论】:

  • 您应该确保您正在创建并尝试 ACTION_VIEW 同一个文件。硬编码到应用程序私有存储的绝对路径让我觉得是在做出毫无根据的假设。如果你想让它在世界上可读,为什么不把它放在 sdcard 上呢? (嗯,好吧,是的,它不仅可读而且更容易找到——但这可能会帮助你解决问题)
  • 嗨 notverycreative,我想做和你一样的事情,但是在 startActivityForResult(intent);它给了我“解析包时出现问题”的错误。你能帮帮我吗?
  • 包可能存在问题(例如,签名错误、传输时损坏等)。如果不是这样,我真的不知道;自从我大约一年前发布这个问题以来,我还没有对 Android 做任何事情。您可能想问一个新问题。对不起,如果我不是很有帮助:/

标签: android download installation apk


【解决方案1】:

我可以在您的代码中看到一个问题:

 startActivity(intent);
 deleteFile("PokeDroid.apk");

此代码发送意图,然后删除文件。注意startActivity 是异步函数。 IE。它发送请求,但不等待该请求完成。因此,当 Application Installer Activity 实际接收到意图时(让我们这样称呼它),您的 .apk 文件已被您删除。

如何解决

您需要将这两行代码替换为:

startActivityForResult(intent);

然后在onActivityResult函数中:

deleteFile("PokeDroid.apk");

【讨论】:

  • 哦,哇,我不敢相信我错过了。我会试一试。
【解决方案2】:

您是否检查过您的手机已配置为接受第 3 方应用程序?

apk 签名了吗?

【讨论】:

  • 这可能是问题所在。未签名的版本永远不会覆盖已签名的版本。然后当然还有第 3 方的事情。 ;)
猜你喜欢
  • 2018-07-30
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-04-14
  • 2017-08-10
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多