在Android中显示MS Word文件(比如TextView)的方法

28

我想在Android中的View中显示一个包含数学符号和图片的.docx文件,并能够通过swipe手势翻页查看多个这样的文件。我已经成功地对.txt文件进行了相同操作,可以轻松地在翻页时进入下一页。以下是.txt文件的代码:

public String readTxt(String fileName)
    {


        try {
            InputStream is;
            is = context.getAssets().open(fileName + ".txt");
            ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();

            int i;
            i = is.read();
            while (i != -1)
            {
                byteArrayOutputStream.write(i);
                i = is.read();
            }

            is.close();

            return byteArrayOutputStream.toString();

        } 

        catch (IOException e) 
        {
            e.printStackTrace();
        }

        return fileName;
    }

这段代码返回文本,我随后在我的TextView中显示它。这样,我只需要动态更改文件名,然后在滑动时文本就会改变。

现在我想修改这个代码,以便我可以显示包含文本、图像和数学符号的MS Word文件(.docx)。

我已经在stackoverflow和其他论坛上检查了许多类似主题的帖子: 这些是许多人建议作为类似问题答案的链接,我已经尝试过:Link1link2

此外,在许多其他主题上,人们推荐使用Jopendocument。我也了解了那个并学习到Android不支持开放文档格式。所以那个选项看起来不太可能。但如果你有任何解决方案或关于将JOpenDocument库添加到项目并显示富文本的详细说明,请分享该解决方案,因为我已经搜索了很多,但找不到任何解决方法。

还有另一个库叫做OliveDocLibrary,用于在Android上显示富Word文件。这是我从中下载lib的链接。其中包含在下载包中的演示效果良好。但该库是试用版。所以我目前正在尝试使用此库并查看其效果。但仍在寻找更好的选择。

任何有关此的帮助都将不胜感激。除上面提到的指针外,欢迎任何其他建议。

更新:

我在这个问题上启动的第一个赏金中得到了一个建议,它告诉我在Apache POI(HWPF更具体地说)中使用。经过一些探索Apache POI后,我得到了一些代码,可以写入文档文件、读取文档文件、更新Excel表等。

我在互联网上找到的样本代码(针对Java)大致如下:

import java.io.*;
import org.apache.poi.hwpf.HWPFDocument;
import org.apache.poi.hwpf.extractor.WordExtractor;

public class ReadDocFile {
public static void main(String[] args) {
File file = null;
WordExtractor extractor = null ;
try {

file = new File("c:\\New.doc");
FileInputStream fis=new FileInputStream(file.getAbsolutePath());
HWPFDocument document=new HWPFDocument(fis);
extractor = new WordExtractor(document);
String [] fileData = extractor.getParagraphText();
for(int i=0;i<fileData.length;i++){
if(fileData[i] != null)
System.out.println(fileData[i]);
}
}
catch(Exception exep){}
}
}

所以我在Eclipse中将这个库(Apache POI)添加到我的Android项目中,并尝试了一些更改后的示例代码。然后尝试在TextView上显示它。然而问题在于它不像OliveDocLibrary那样显示图像。因此,如果有人要建议Apache POI,则请求提供一个能够读取docx文件及其所有内容(包括图像)并在自定义视图中显示它们的实用指针或代码。

Apache POI非常好,但遗憾的是我没有找到任何实现这些库的好示例/样本。如果您知道一个好的示例源(仅限于MS Word),请在评论中分享。

更新2

OliveDocLibrary中的包中,提供的代码可以正常工作。虽然视图上有Olive的水印。目前我正在执行对该代码的Swipe操作。但问题在于它是试用版。

更新3:

我认为OliveDocLibrary是最有效的方法。虽然它的缺点是试用版,但我认为没有其他库比这个库更好地满足我的特定要求。详细答案已发布在这里。由于赏金时间即将结束,我请求那些可能有其他替代方案和更好解决方法的人尽快发表意见。目前我使用OliveDocLibrary并接受自己的答案。


从这个帖子中:http://forum.openoffice.org/en/forum/viewtopic.php?f=12&t=38718 我认为将Word文档转换为PDF并在Android上显示会更容易。 - Morrison Chang
请点击这个链接,我认为这是你需要的:如何在Android中呈现PDF,此链接适用于PDF文件。对于Office文档,您可以通过已安装的应用程序发送意图或者使用Google Docs链接在Webview上显示。 - Ashish Mishra
2个回答

7
大家好,经过深思熟虑和大量的选择和解决方案,我认为OliveDocLibrary是最好的方式。这里是一个链接,它将直接引导您到三个Android库的下载页面,分别用于DOC、XLS和PPT。所有这些都运行得非常好。您将下载的包文件夹内有三个文件夹,分别是:
  1. API
  2. lib_trial
  3. Demo
demo文件夹中,您将找到一个Word的示例项目。您可以直接将此项目导入Eclipse工作区并测试代码。为了方便大家,我在此发布了该代码。我删除了一些我认为不必要的代码(关于我的问题的答案),所以代码有两个文件,主要活动是FileChooser,如下所示:
public class FileChooser extends Activity {

    private String filePath = Environment.getExternalStorageDirectory()
            .getPath() + "/simple.docx";
    MyBaseAdapter adapter;
    private static String parentPath;

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        requestWindowFeature(2);
        copyFileToSdcard();
        Intent intent = new Intent(FileChooser.this,
                OliveWordTrailDemoAcitivy.class);
        intent.setAction(Intent.ACTION_VIEW);
        intent.setData(Uri.fromFile(new File(filePath)));
        startActivity(intent);
    }

    class MyBaseAdapter extends BaseAdapter {
        private String[] list;

        public MyBaseAdapter(String[] list) {
            this.list = list;
        }

        @Override
        public View getView(int position, View convertView, ViewGroup parent) {
            if (convertView == null) {
                convertView = new TextView(FileChooser.this);
                ((TextView) convertView).setTextSize(35);
            }
            ((TextView) convertView).setText(list[position]);
            return convertView;
        }

        @Override
        public long getItemId(int position) {
            return position;
        }

        @Override
        public Object getItem(int position) {
            return null;
        }

        @Override
        public int getCount() {
            return list.length;
        }

        public void setList(String[] list) {
            this.list = list;
        }
    };

    class MyItemClickListener implements OnItemClickListener {
        String[] list;
        InputStream is;

        public MyItemClickListener(String[] list) {
            this.list = list;
        }

        @Override
        public void onItemClick(AdapterView<?> parent, View view, int position,
                long id) {

            File file = new File(parentPath + list[position]);
            if (file.isFile()) {
                Intent intent = new Intent(FileChooser.this,
                        OliveWordTrailDemoAcitivy.class);
                intent.setAction(Intent.ACTION_VIEW);
                intent.setData(Uri.fromFile(file));
                startActivity(intent);
            } else {
                list = file.list();
                adapter.setList(list);
                adapter.notifyDataSetChanged();
                parentPath = file.getAbsolutePath() + "/";
            }
        }

    }
    private void copyFileToSdcard() {
        InputStream inputstream     = getResources().openRawResource(
                R.raw.simple);
        byte[] buffer = new byte[1024];
        int count = 0;
        FileOutputStream fos = null;
        try {
            fos = new FileOutputStream(new File(filePath));
            while ((count = inputstream.read(buffer)) > 0) {
                fos.write(buffer, 0, count);
            }
            fos.close();
        } catch (FileNotFoundException e1) {
            e1.printStackTrace();
            Toast.makeText(FileChooser.this, "Check your sdcard", Toast.LENGTH_LONG).show();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

}

这里我放置了一个名为simple.docx的文档文件,其中包含图像和数学符号,这些符号可以被正确地呈现和显示。此活动与OliveWordTrialDemoActivity交互,如下所示:

public class OliveWordTrailDemoAcitivy extends Activity implements
OnClickListener, CommentListener, NoteListener, HyperlinkListener, ProgressListener {

    OliveWordOperator viu;

    EditText searchEditText;
    ArrayList<String> bookmarks;
    Handler handler;

    protected void onCreate(Bundle savedInstanceState) {
        viu = new OliveWordOperator(this, this);
        super.onCreate(savedInstanceState);
        requestWindowFeature(Window.FEATURE_PROGRESS);
        setProgressBarVisibility(true);
        getWindow().setFeatureInt(Window.FEATURE_PROGRESS, Window.PROGRESS_VISIBILITY_ON);
        setContentView(R.layout.demo_view);
        OliveWordView view = (OliveWordView) findViewById(R.id.test_view);

        try {
            viu.init(view, getIntent().getData());
            viu.start(viu.isEncrypted(), "111");
        } catch (Exception e) {
            e.printStackTrace();
        }
        handler = new Handler(){

            @Override
            public void handleMessage(Message msg) {
                setProgress(msg.what * 10);
                super.handleMessage(msg);
            }

        };

    }

    @Override
    protected void onDestroy() {
        viu.release();
        super.onDestroy();
    }

    @Override
    public void getComment(ArrayList<String[]> comments) {
        for (int i = 0; i < comments.size(); i++) {
            AlertDialog.Builder builder = new Builder(this);
            builder.setTitle(comments.get(i)[0]).setMessage(comments.get(i)[1])
            .show();
        }
    }

    @Override
    public void getHyperlink(String hyperlink) {
        if (Uri.parse(hyperlink).getScheme().contains("mailto")) {
            try {
                startActivity(new Intent(Intent.ACTION_SENDTO,
                        Uri.parse(hyperlink)));
            } catch (ActivityNotFoundException anfe) {
                Toast.makeText(this, "can't found email application",
                        Toast.LENGTH_SHORT).show();
            }
        } else {
            startActivity(new Intent(Intent.ACTION_VIEW, Uri.parse(hyperlink)));
        }
    }

    @Override
    public void getNote(SparseArray<String> notes) {
        for (int i = 0; i < notes.size(); i++) {
            AlertDialog.Builder builder = new Builder(this);
            if (notes.keyAt(i) == NoteListener.FOOTNOTE) {
                builder.setTitle("footnote").setMessage(notes.valueAt(i))
                .show();
            } else if (notes.keyAt(i) == NoteListener.ENDNOTE) {
                builder.setTitle("endnote").setMessage(notes.valueAt(i)).show();
            }
        }

    }

    public void goToBookmarks(String name) {
        viu.goToBookmark(name);
    }

    public void listBookmarks() {
        this.bookmarks = viu.listBookmarks();
    }

    @Override
    public void notifyProgress(int progress) {
        handler.sendEmptyMessage(progress);
    }

    @Override
    public void onClick(View v) {

    }

}

lib_trial 文件夹中,您可以找到这个库。如果您想单独使用它,可以将其添加到您的 libs 文件夹中。
而在 API 文件夹中,您会发现一个详细描述该库及其方法的 pdf 文件,非常易于理解。因此,人们可以直接使用此库并使用提供的方法来满足其特定需求。
所以,这是我现在要采取的解决方案。欢迎任何更好的解决方案。赏金时间即将结束,请尽快提供您可能拥有的任何其他解决方案。谢谢。

我也可以成功地使用上述库显示Word文档。唯一的问题是文档中显示的“水印”。您是否找到了其他更好的显示MS-Word文档的方法或者有任何去除此水印的想法? - YuDroid
@YuDroid:没有比OliveDocLibrary解决方案更好的了。而且,水印确实是一个问题。我已经不再在这个项目上工作了,但如果你找到了更好的方法,请在这个帖子上分享你的答案,因为我已经尝试过所有可能的方法并在这里提到了它们。 - D'yer Mak'er
我正在尝试从SD卡打开另一个doc文件,但是它会出现ActivityNotFoundError错误(android.content.ActivityNotFoundException: Unable to find explicit activity class {com.olivephone.sdk.view.word.trial/com.olivephone.sdk.word.demo.office.a};)。在viu.start(viu.isEncrypted(), "111");处。 - AkashG
你有关于这个问题的解决方案吗,@D'yer Mak'er? - AkashG
我使用IDocument创建了文档,并成功地创建了它,但是当尝试使用上述代码打开它时,它失败了。但是我要说,当尝试打开另一个不是从IDocument创建的doc文件时,上述代码是有效的。所以@D'yer能否帮助我编写程序创建doc/docx文件? - AkashG
显示剩余2条评论

2

根据你的问题,你已经尝试了一些库,如JopendocumentOliveDocLibraryApache POI,但都没有成功。

现在我想修改这段代码,以便我可以显示包含文本、图像和数学符号的MS Word文件(.docx)。

在研究过程中,我发现了另一个名为Tika的库,它也用于提取数据和其支持列出的文档,甚至还有Libra Office,您可以在其中读取、写入和管理文档。

最后一个建议:

您可以通过将doc转换为html,然后将html转换为pdf来实现,如此处所述

要将doc转换为html,请参考stack-overflow答案


嗨@RobinHood。感谢您的回复。如果您能发布一个使用tika在android中显示Word文件的示例代码,那将非常有帮助。我搜索了示例代码,但找不到任何内容。 在您提供的链接中,他们说它使用Apache POI进行此操作。关于MS文件,链接上写着: “OfficeParser和OOXMLParser类使用Apache POI库来支持从OLE2和OOXML文档中提取文本和元数据。” - D'yer Mak'er
1
这些链接都与编程有关,包括以下内容: http://www.hascode.com/2012/12/content-detection-metadata-and-content-extraction-with-apache-tika/ https://dev59.com/FGfWa4cB1Zd3GeqPezYO http://www.jworks.nl/2011/09/02/friday-repost-indexing-documents-with-tika-and-grails/虽然这些链接没有你想要的确切示例,但你可以从中获得参考。 - RobinHood

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接