The following code inspired here should take a file in (.mht/.mhtml) format and convert it to html format.
The mht file is a file saved from chrome browser to the Download
directory.
The code failes when message.getContent()
is called.
How can I fix it?
// MainActivity.java
package org.xralf.safreading;
import androidx.activity.result.ActivityResult;
import androidx.activity.result.ActivityResultCallback;
import androidx.activity.result.ActivityResultLauncher;
import androidx.activity.result.contract.ActivityResultContracts;
import androidx.appcompat.app.AppCompatActivity;
import android.os.Bundle;
import android.app.Activity;
import android.content.Intent;
import android.net.Uri;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;
import android.widget.Toast;
import java.io.BufferedReader;
import java.io.ByteArrayInputStream;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.net.URL;
import java.nio.charset.StandardCharsets;
import java.util.Properties;
import javax.mail.BodyPart;
import javax.mail.Session;
import javax.mail.internet.MimeMessage;
import javax.mail.internet.MimeMultipart;
import org.apache.commons.io.IOUtils;
public class MainActivity extends AppCompatActivity {
public class MhtParser {
//private File mhtFile;
private String mhtFile;
private File outputFolder;
public MhtParser(String mhtFile, File outputFolder) {
this.mhtFile = mhtFile;
this.outputFolder = outputFolder;
}
public void decompress() throws Exception {
MimeMessage message =
new MimeMessage(
Session.getDefaultInstance(new Properties(), null),
//new FileInputStream(mhtFile));
//new ByteArrayInputStream(mhtFile.getBytes(StandardCharsets.UTF_8)));
IOUtils.toInputStream(mhtFile, StandardCharsets.UTF_8));
//mhtFile);
if (message.getContent() instanceof MimeMultipart) {
outputFolder.mkdir();
MimeMultipart mimeMultipart = (MimeMultipart) message.getContent();
for (int i = 0; i < mimeMultipart.getCount(); i++) {
BodyPart bodyPart = mimeMultipart.getBodyPart(i);
String fileName = bodyPart.getFileName();
if (fileName == null) {
String[] locationHeader = bodyPart.getHeader("Content-Location");
if (locationHeader != null && locationHeader.length > 0) {
fileName =
new File(new URL(locationHeader[0]).getFile()).getName();
}
}
if (fileName != null) {
FileOutputStream out =
new FileOutputStream(new File(outputFolder, fileName));
IOUtils.copy(bodyPart.getInputStream(), out);
out.flush();
out.close();
}
}
}
}
}
private EditText editText;
private Button button;
ActivityResultLauncher<Intent> startOpenForResult =
registerForActivityResult(
new ActivityResultContracts.StartActivityForResult(),
new ActivityResultCallback<ActivityResult>() {
@Override
public void onActivityResult(ActivityResult result) {
if (result.getResultCode() == Activity.RESULT_OK) {
Intent data = result.getData();
if (data != null) {
Uri currentUri = data.getData();
try {
String content = readFileContent(currentUri);
editText.setText(content);
File directory = new File(getExternalFilesDir(null), "dir");
MhtParser mhtParser = new MhtParser(content, directory);
try {
mhtParser.decompress();
} catch (Exception e) {
e.printStackTrace();
}
} catch (IOException e) {
Toast.makeText(getApplicationContext(), "Error reading file", Toast.LENGTH_SHORT).show();
}
}
}
}
}
);
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
editText = findViewById(R.id.edit_text);
button = findViewById(R.id.button);
button.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Intent intent = new Intent(Intent.ACTION_OPEN_DOCUMENT);
intent.setType("*/*");
intent.addCategory(Intent.CATEGORY_OPENABLE);
intent.setFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
startOpenForResult.launch(intent);
}
});
}
private String readFileContent(Uri uri) throws IOException {
InputStream inputStream = getContentResolver().openInputStream(uri);
BufferedReader reader = new BufferedReader(new InputStreamReader(inputStream));
StringBuilder stringBuilder = new StringBuilder();
String currentLine;
while ((currentLine = reader.readLine()) != null) {
//stringBuilder.append(currentLine).append("\n");
stringBuilder.append(currentLine);
}
inputStream.close();
return stringBuilder.toString();
}
}
// activity_main.xml
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity">
<EditText
android:id="@+id/edit_text"
android:layout_width="242dp"
android:layout_height="188dp"
android:ems="10"
android:inputType="text"
android:text="Name"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<Button
android:id="@+id/button"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="read"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/edit_text" />
</androidx.constraintlayout.widget.ConstraintLayout>
Here is the error from logcat
:
FATAL EXCEPTION: main
Process: org.xralf.safreading, PID: 7062
java.lang.NoClassDefFoundError: Failed resolution of: Ljava/awt/datatransfer/Transferable;
at org.xralf.safreading.MainActivity$MhtParser.decompress(MainActivity.java:54)
at org.xralf.safreading.MainActivity$1.onActivityResult(MainActivity.java:112)
at org.xralf.safreading.MainActivity$1.onActivityResult(MainActivity.java:98)
at androidx.activity.result.ActivityResultRegistry$1.onStateChanged(ActivityResultRegistry.java:149)
at androidx.lifecycle.LifecycleRegistry$ObserverWithState.dispatchEvent(LifecycleRegistry.java:360)
at androidx.lifecycle.LifecycleRegistry.forwardPass(LifecycleRegistry.java:271)
at androidx.lifecycle.LifecycleRegistry.sync(LifecycleRegistry.java:313)
at androidx.lifecycle.LifecycleRegistry.moveToState(LifecycleRegistry.java:151)
at androidx.lifecycle.LifecycleRegistry.handleLifecycleEvent(LifecycleRegistry.java:134)
at androidx.lifecycle.ReportFragment.dispatch(ReportFragment.java:68)
at androidx.lifecycle.ReportFragment$LifecycleCallbacks.onActivityPostStarted(ReportFragment.java:187)
at android.app.Activity.dispatchActivityPostStarted(Activity.java:1380)
at android.app.Activity.performStart(Activity.java:8113)
at android.app.ActivityThread.handleStartActivity(ActivityThread.java:3660)
at android.app.servertransaction.TransactionExecutor.performLifecycleSequence(TransactionExecutor.java:221)
at android.app.servertransaction.TransactionExecutor.cycleToPath(TransactionExecutor.java:201)
at android.app.servertransaction.TransactionExecutor.executeLifecycleState(TransactionExecutor.java:173)
at android.app.servertransaction.TransactionExecutor.execute(TransactionExecutor.java:97)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:2210)
at android.os.Handler.dispatchMessage(Handler.java:106)
at android.os.Looper.loopOnce(Looper.java:201)
at android.os.Looper.loop(Looper.java:288)
at android.app.ActivityThread.main(ActivityThread.java:7839)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:548)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1003)
Caused by: java.lang.ClassNotFoundException: Didn't find class "java.awt.datatransfer.Transferable" on path: DexPathList[[dex file "/data/data/org.xralf.safreading/code_cache/.overlay/base.apk/classes3.dex", zip file "/data/app/~~i4aHJ3VUmdawPwuyNI_dHg==/org.xralf.safreading-rH4ceYka7KTyjpEojS3MzQ==/base.apk"],nativeLibraryDirectories=[/data/app/~~i4aHJ3VUaddwPwuyNI_dHg==/org.xralf.safreading-rH4MeYkr7KTyjpEajS3MzQ==/lib/x86_64, /system/lib64, /system_ext/lib64]]
at dalvik.system.BaseDexClassLoader.findClass(BaseDexClassLoader.java:218)
at java.lang.ClassLoader.loadClass(ClassLoader.java:379)
at java.lang.ClassLoader.loadClass(ClassLoader.java:312)
at org.xralf.safreading.MainActivity$MhtParser.decompress(MainActivity.java:54)
at org.xralf.safreading.MainActivity$1.onActivityResult(MainActivity.java:112)
at org.xralf.safreading.MainActivity$1.onActivityResult(MainActivity.java:98)
at androidx.activity.result.ActivityResultRegistry$1.onStateChanged(ActivityResultRegistry.java:149)
at androidx.lifecycle.LifecycleRegistry$ObserverWithState.dispatchEvent(LifecycleRegistry.java:360)
at androidx.lifecycle.LifecycleRegistry.forwardPass(LifecycleRegistry.java:271)
at androidx.lifecycle.LifecycleRegistry.sync(LifecycleRegistry.java:313)
at androidx.lifecycle.LifecycleRegistry.moveToState(LifecycleRegistry.java:151)
at androidx.lifecycle.LifecycleRegistry.handleLifecycleEvent(LifecycleRegistry.java:134)
at androidx.lifecycle.ReportFragment.dispatch(ReportFragment.java:68)
at androidx.lifecycle.ReportFragment$LifecycleCallbacks.onActivityPostStarted(ReportFragment.java:187)
at android.app.Activity.dispatchActivityPostStarted(Activity.java:1380)
at android.app.Activity.performStart(Activity.java:8113)
at android.app.ActivityThread.handleStartActivity(ActivityThread.java:3660)
at android.app.servertransaction.TransactionExecutor.performLifecycleSequence(TransactionExecutor.java:221)
at android.app.servertransaction.TransactionExecutor.cycleToPath(TransactionExecutor.java:201)
at android.app.servertransaction.TransactionExecutor.executeLifecycleState(TransactionExecutor.java:173)
at android.app.servertransaction.TransactionExecutor.execute(TransactionExecutor.java:97)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:2210)
at android.os.Handler.dispatchMessage(Handler.java:106)
at android.os.Looper.loopOnce(Looper.java:201)
at android.os.Looper.loop(Looper.java:288)
at android.app.ActivityThread.main(ActivityThread.java:7839)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:548)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1003)