我目前正在寻找一个解决方案,通过http请求访问一个在线ics文件,并在我的应用程序中使用它。我有一个想法,但我不知道如何做到这一点。我想我必须做一个get请求(也许用httpURLconnection......)来下载ics文件并保存它,然后在我的活动中使用它。我已经在我的按钮监听器的onClick方法中尝试过这种方式。
try {
//this is the file you want to download from the remote server
String path = "http://.../file.ics";
//this is the name of the local file you will create
boolean eof = false;
URL u = new URL(path);
HttpURLConnection c = (HttpURLConnection) u.openConnection();
c.setRequestMethod("GET");
c.setDoOutput(true);
c.connect();
FileOutputStream f = new FileOutputStream(new File("data/edt.ics"));
InputStream in = c.getInputStream();
byte[] buffer = new byte[1024];
int len1 = 0;
while ((len1 = in.read(buffer)) > 0) {
f.write(buffer, 0, len1);
}
f.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
但它在logcat中产生了这个错误。
06-02 15:29:05.260 6685-6685/com.enib.enibapp E/AndroidRuntime: FATAL EXCEPTION: main
Process: com.enib.enibapp, PID: 6685
android.os.NetworkOnMainThreadException
at android.os.StrictMode$AndroidBlockGuardPolicy.onNetwork(StrictMode.java:1273)
at java.net.InetAddress.lookupHostByName(InetAddress.java:431)
at java.net.InetAddress.getAllByNameImpl(InetAddress.java:252)
at java.net.InetAddress.getAllByName(InetAddress.java:215)
at com.android.okhttp.internal.Network$1.resolveInetAddresses(Network.java:29)
at com.android.okhttp.internal.http.RouteSelector.resetNextInetSocketAddress(RouteSelector.java:188)
at com.android.okhttp.internal.http.RouteSelector.nextProxy(RouteSelector.java:157)
at com.android.okhttp.internal.http.RouteSelector.next(RouteSelector.java:100)
at com.android.okhttp.internal.http.HttpEngine.createNextConnection(HttpEngine.java:357)
at com.android.okhttp.internal.http.HttpEngine.nextConnection(HttpEngine.java:340)
at com.android.okhttp.internal.http.HttpEngine.connect(HttpEngine.java:330)
at com.android.okhttp.internal.http.HttpEngine.sendRequest(HttpEngine.java:248)
at com.android.okhttp.internal.huc.HttpURLConnectionImpl.execute(HttpURLConnectionImpl.java:433)
at com.android.okhttp.internal.huc.HttpURLConnectionImpl.connect(HttpURLConnectionImpl.java:114)
at com.enib.enibapp.ui.home.HomeFragment$1.onClick(HomeFragment.java:74)
at android.view.View.performClick(View.java:5198)
at android.view.View$PerformClick.run(View.java:21147)
at android.os.Handler.handleCallback(Handler.java:739)
at android.os.Handler.dispatchMessage(Handler.java:95)
at android.os.Looper.loop(Looper.java:148)
at android.app.ActivityThread.main(ActivityThread.java:5417)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:726)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:616)
而且我不明白这个堆栈跟踪...
目的是为了从ics文件中检索事件,以显示你在旅途中的事件。我已经找了一个解决方案来处理ics文件,我找到了iCal4j库。但是检索部分是我的一个问题。谁能帮我一下,或者给我一些线索?
PS:如果我的问题有什么问题,不要犹豫,可以向我报告问题,我是新来的,另外开始安卓开发。
谢谢你的建议@anmari。经过一些深入的研究,我找到了问题的解释:连接请求必须放在AsyncTask的子程序的doInBackground方法中。所以我把我使用的代码放在下面,如果有人和我有同样的情况需要解决的话。
AccesHTTP类。
public class AccesHTTP extends AsyncTask<String, String, String> {
private Controle controle;
private String urlServ = null;
public AsyncResponse delegate = null;
public AccesHTTP(String servaddr) {
controle = Controle.getInstance(null);
urlServ = servaddr;
}
@Override
protected String doInBackground(String... strings) {
// Create a TimeZone
System.setProperty("net.fortuna.ical4j.timezone.cache.impl", MapTimeZoneCache.class.getName());
URL url = null;
try {
url = new URL(urlServ);
Reader r = null;
r = new InputStreamReader(url.openStream(), "ISO-8859-15");
CalendarBuilder builder = new CalendarBuilder();
Calendar thisCalendar = builder.build(r);
controle.refreshEdt(thisCalendar);
} catch (IOException | ParserException e) {
e.printStackTrace();
}
return "Completed";
}
@Override
protected void onPostExecute(String s){
Log.d("Return","************ " + s + " ************");
if(s!=null){
delegate.processFinish(s);
};
}
}
AccesDistant类:
public class AccesDistant implements AsyncResponse {
//constant
private static final String SERVERADDR = "https://.../calendar.ics";
public AccesDistant() {
controle = Controle.getInstance(null);
}
@Override
public void processFinish(String output) {
if(output.equals("Completed")){
Log.d("Completed", "*******************");
} else {
Log.d("Erreur null return", "*******************");
}
}
public void envoi() {
AccesHTTP dataAccess = new AccesHTTP(SERVERADDR);
//delegate link
dataAccess.delegate = this;
//server call
try {
dataAccess.execute();
} catch (Exception e) {
Log.d("Erreur send request","******************" + e.toString());
e.printStackTrace();
}
}
}