diff --git a/.gitignore b/.gitignore index 9c2c9cbc2..5a01e7d20 100644 --- a/.gitignore +++ b/.gitignore @@ -37,3 +37,8 @@ build/* *Karen_angelXwind* local.properties ant.properties + +# Linux stuff +shell/lin86/.map +shell/lin86/nosym-reicast.elf +shell/lin86/reicast.elf diff --git a/.travis.yml b/.travis.yml index a38e3eeb6..1b0b7028d 100644 --- a/.travis.yml +++ b/.travis.yml @@ -9,7 +9,7 @@ before_install: - sudo apt-get -qq update - sudo apt-get -qq -y install openjdk-7-jdk ant lib32z1-dev lib32stdc++6 - GIT_HASH=`git log --pretty=format:'%h' -n 1` -- GIT_BUILD=`git rev-parse --abbrev-ref HEAD`-$GIT_HASH +- GIT_BUILD=`git describe --all`-$GIT_HASH install: - download_extract http://dl.google.com/android/ndk/android-ndk-r9c-linux-x86_64.tar.bz2 android-ndk-r9c-linux-x86_64.tar.bz2 diff --git a/README.md b/README.md index d9862b508..7e663621b 100644 --- a/README.md +++ b/README.md @@ -59,6 +59,22 @@ cd shell/ios/ xcodebuild -configuration Release ``` +Building for Linux +------------------ + +The code is only currently compatible with 32bit architectures so you will need +to install 32bit libs to build reicast. + +Requirements: +* build-essential +* libasound +* libegl1-mesa-dev +* libgles2-mesa-dev +* libasound2-dev + +To build the project, go to shell/lin86 and run make + + Translations ------------ New and updated translations are always appreciated! @@ -82,7 +98,9 @@ Well, glad you liked the project so far! We're currently short on hardware. -If you would like to donate some devices, get in touch at team@reicast.com. GLES3 capable stuff, some mainstream hardware and rarities would be extremely appreciated. +If you would like to donate some devices, get in touch at team@reicast.com. +GLES3 capable stuff, some mainstream hardware and rarities would be extremely +appreciated. Keep in mind we're located in Greece for the most part This has been tested/developed on @@ -94,14 +112,17 @@ This has been tested/developed on * Various development boards * GCW Zero -We had to buy all of these, except the GCW Zero and a BeagleBone which were donated (Thanks! You rock!) +We had to buy all of these, except the GCW Zero and a BeagleBone which were +donated (Thanks! You rock!) Apart from that, we don't accept monetary donations right now. We also don't plan to be releasing a premium version at any store. -Most of the project has been developed by drk||Raziel (aka, skmp, drk, Raz, etc) but it has been based on the -works of multiple people. It would be extremely unfair to charge for it and get all the credit :) +Most of the project has been developed by drk||Raziel (aka, skmp, drk, Raz, +etc) but it has been based on the works of multiple people. It would be +extremely unfair to charge for it and get all the credit :) -We're planning for an indiegogo campaign later on to help with sustained development and running costs, so follow @reicastdc on twitter for updates +We're planning for an indiegogo campaign later on to help with sustained +development and running costs, so follow @reicastdc on twitter for updates Other Testing ------------- @@ -124,14 +145,16 @@ Team You can check the currently active committers on [the pretty graphs page](https://github.com/reicast/reicast-emulator/graphs/contributors) -Our IRC channel is [#reicast @ chat.freenode.net](irc://chat.freenode.net/reicast). +Our IRC channel is [#reicast @ chat.freenode.net](irc://chat.freenode.net/reicast). -The original reicast team consisted of drk||Raziel (mostly just writing code), PsyMan (debugging/testing and everything else) and a little bit of gb_away +The original reicast team consisted of drk||Raziel (mostly just writing code), +PsyMan (debugging/testing and everything else) and a little bit of gb_away Special thanks -------------- -In previous iterations a lot of people have worked on this, notably David Miller (aka, ZeZu), the nullDC team, friends from #pcsx2 and all over the world :) +In previous iterations a lot of people have worked on this, notably David +Miller (aka, ZeZu), the nullDC team, friends from #pcsx2 and all over the world :) [![Bitdeli Badge](https://d2weczhvl823v0.cloudfront.net/reicast/reicast-emulator/trend.png)](https://bitdeli.com/free "Bitdeli Badge") diff --git a/shell/android/res/values-ko/strings.xml b/shell/android/res/values-ko/strings.xml index 58f405ea1..b57e98f11 100644 --- a/shell/android/res/values-ko/strings.xml +++ b/shell/android/res/values-ko/strings.xml @@ -7,12 +7,12 @@ 기본 게임 저장 부팅 드림 캐스트 바이오스 - BIOS는 없음.드림 캐스트 BIOS가 작동하려면이 에뮬레이터가 필요합니다.BIOS 파일에 배치 %1$s/데이터/dc_boot.bin - 누락 플래시.드림 캐스트 플래시가 작동하려면이 에뮬레이터가 필요합니다.플래시 파일에 배치 %1$s/데이터/dc_flash.bin - 당신은 BIOS를 제공해야 + BIOS가 없음.드림캐스트가 작동하려면 BIOS가 필요합니다.BIOS 파일에 배치 %1$s/데이터/dc_boot.bin + 플래시파일 없음.드림 캐스트가 에뮬레이터가 작동하려면 플레시파일이필요합니다.%1$s/데이터/dc_flash.bin에 넣으십시오 + BIOS가 필요합니다 BOOT의 BIOS - 현재 폴더를 선택 + 이 폴더를 선택 실험 (광범위한 패닉이 발생할 수 있음) Dynarec 옵션 @@ -34,7 +34,7 @@ 제어 장치 B 제어 장치 C 제어 장치 D - 컨트롤러 연결되지 않음 + 컨트롤러가 연결되지 않음 선정 된 제어기가 없습니다 선택 제거 diff --git a/shell/android/res/values/strings.xml b/shell/android/res/values/strings.xml index d2d027818..9c0396c89 100644 --- a/shell/android/res/values/strings.xml +++ b/shell/android/res/values/strings.xml @@ -113,4 +113,7 @@ be created in VmuBackups folder! Upload VMU Download VMU + + Copying logcat content to clipboard\nPlease paste in the issue report + Log saved to \"Files Dir\" path \ No newline at end of file diff --git a/shell/android/src/com/reicast/emulator/FileBrowser.java b/shell/android/src/com/reicast/emulator/FileBrowser.java index 80347ba2f..cb5095ecb 100644 --- a/shell/android/src/com/reicast/emulator/FileBrowser.java +++ b/shell/android/src/com/reicast/emulator/FileBrowser.java @@ -66,11 +66,6 @@ public class FileBrowser extends Fragment { super.onCreate(savedInstanceState); mPrefs = PreferenceManager.getDefaultSharedPreferences(getActivity()); - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) { - sdcard = getActivity().getExternalFilesDir(null); - home_directory = sdcard + "/dc"; - game_directory = sdcard + "/dc"; - } home_directory = mPrefs.getString(Config.pref_home, home_directory); game_directory = mPrefs.getString(Config.pref_games, game_directory); diff --git a/shell/android/src/com/reicast/emulator/GL2JNIActivity.java b/shell/android/src/com/reicast/emulator/GL2JNIActivity.java index beef10062..b180bea4e 100644 --- a/shell/android/src/com/reicast/emulator/GL2JNIActivity.java +++ b/shell/android/src/com/reicast/emulator/GL2JNIActivity.java @@ -282,10 +282,10 @@ public class GL2JNIActivity extends Activity { GL2JNIView.rt[playerNum] = (int) (R2 * 255); if (prefs.getBoolean("right_buttons", true)) { - if (RS_Y > 0.5) { + if (RS_Y > 0.25) { handle_key(playerNum, pad.map[playerNum][0]/* A */, true); pad.wasKeyStick[playerNum] = true; - } else if (RS_Y < 0.5) { + } else if (RS_Y < 0.25) { handle_key(playerNum, pad.map[playerNum][1]/* B */, true); pad.wasKeyStick[playerNum] = true; } else if (pad.wasKeyStick[playerNum]){ @@ -294,10 +294,10 @@ public class GL2JNIActivity extends Activity { pad.wasKeyStick[playerNum] = false; } } else { - if (RS_Y > 0.5) { + if (RS_Y > 0.25) { GL2JNIView.rt[playerNum] = (int) (RS_Y * 255); GL2JNIView.lt[playerNum] = (int) (L2 * 255); - } else if (RS_Y < 0.5) { + } else if (RS_Y < 0.25) { GL2JNIView.rt[playerNum] = (int) (R2 * 255); GL2JNIView.lt[playerNum] = (int) (-(RS_Y) * 255); } diff --git a/shell/android/src/com/reicast/emulator/GL2JNINative.java b/shell/android/src/com/reicast/emulator/GL2JNINative.java index 7c8bcb6f7..8d69f40cc 100644 --- a/shell/android/src/com/reicast/emulator/GL2JNINative.java +++ b/shell/android/src/com/reicast/emulator/GL2JNINative.java @@ -372,10 +372,10 @@ public class GL2JNINative extends NativeActivity { GL2JNIView.rt[playerNum] = (int) (R2 * 255); if (prefs.getBoolean("right_buttons", true)) { - if (RS_Y > 0.5) { + if (RS_Y > 0.25) { handle_key(playerNum, pad.map[playerNum][0]/* A */, true); pad.wasKeyStick[playerNum] = true; - } else if (RS_Y < 0.5) { + } else if (RS_Y < 0.25) { handle_key(playerNum, pad.map[playerNum][1]/* B */, true); pad.wasKeyStick[playerNum] = true; } else if (pad.wasKeyStick[playerNum]){ @@ -384,10 +384,10 @@ public class GL2JNINative extends NativeActivity { pad.wasKeyStick[playerNum] = false; } } else { - if (RS_Y > 0.5) { + if (RS_Y > 0.25) { GL2JNIView.rt[playerNum] = (int) (RS_Y * 255); GL2JNIView.lt[playerNum] = (int) (L2 * 255); - } else if (RS_Y < 0.5) { + } else if (RS_Y < 0.25) { GL2JNIView.rt[playerNum] = (int) (R2 * 255); GL2JNIView.lt[playerNum] = (int) (-(RS_Y) * 255); } diff --git a/shell/android/src/com/reicast/emulator/MainActivity.java b/shell/android/src/com/reicast/emulator/MainActivity.java index 75c6d4428..68d9b7964 100644 --- a/shell/android/src/com/reicast/emulator/MainActivity.java +++ b/shell/android/src/com/reicast/emulator/MainActivity.java @@ -13,6 +13,7 @@ import android.content.pm.PackageManager; import android.content.pm.ResolveInfo; import android.content.res.Configuration; import android.net.Uri; +import android.os.AsyncTask; import android.os.Build; import android.os.Bundle; import android.os.Environment; @@ -22,10 +23,10 @@ import android.util.Log; import android.view.KeyEvent; import android.view.MotionEvent; import android.view.View; -import android.view.WindowManager; import android.view.View.OnClickListener; import android.view.View.OnSystemUiVisibilityChangeListener; import android.view.View.OnTouchListener; +import android.view.WindowManager; import android.widget.TextView; import android.widget.Toast; @@ -35,6 +36,7 @@ import com.jeremyfeinstein.slidingmenu.lib.app.SlidingFragmentActivity; import com.reicast.emulator.config.Config; import com.reicast.emulator.config.InputFragment; import com.reicast.emulator.config.OptionsFragment; +import com.reicast.emulator.debug.GenerateLogs; import com.reicast.emulator.emu.JNIdc; import com.reicast.emulator.periph.Gamepad; @@ -322,7 +324,11 @@ public class MainActivity extends SlidingFragmentActivity implements } }); } else { - messages.setVisibility(View.GONE); + messages.setOnClickListener(new OnClickListener() { + public void onClick(View view) { + generateErrorLog(); + } + }); } } }); @@ -336,6 +342,17 @@ public class MainActivity extends SlidingFragmentActivity implements } }); } + + public void generateErrorLog() { + GenerateLogs mGenerateLogs = new GenerateLogs(MainActivity.this); + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB) { + mGenerateLogs.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR, + getFilesDir().getAbsolutePath()); + } else { + mGenerateLogs.execute(getFilesDir().getAbsolutePath()); + } + + } /** * Display a dialog to notify the user of prior crash diff --git a/shell/android/src/com/reicast/emulator/config/Config.java b/shell/android/src/com/reicast/emulator/config/Config.java index 44a35db83..c6e670fad 100644 --- a/shell/android/src/com/reicast/emulator/config/Config.java +++ b/shell/android/src/com/reicast/emulator/config/Config.java @@ -58,6 +58,10 @@ public class Config { public static String cheatdisk = "null"; public static boolean nativeact = false; public static int vibrationDuration = 20; + + public static String git_issues = "https://github.com/reicast/reicast-emulator/issues/"; + public static String log_url = "http://loungekatt.no-ip.biz:3194/ReicastBot/report/submit.php"; + public static String report_url = "http://loungekatt.no-ip.biz:3194/ReicastBot/report/logs/"; private SharedPreferences mPrefs; diff --git a/shell/android/src/com/reicast/emulator/config/OptionsFragment.java b/shell/android/src/com/reicast/emulator/config/OptionsFragment.java index 4c76beef4..8c3985152 100644 --- a/shell/android/src/com/reicast/emulator/config/OptionsFragment.java +++ b/shell/android/src/com/reicast/emulator/config/OptionsFragment.java @@ -1,12 +1,10 @@ package com.reicast.emulator.config; import java.io.File; -import java.io.FileInputStream; import java.io.FileOutputStream; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; -import java.nio.channels.FileChannel; import android.app.Activity; import android.content.SharedPreferences; @@ -85,11 +83,6 @@ public class OptionsFragment extends Fragment { // setContentView(R.layout.activity_main); //parentActivity = getActivity(); - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) { - sdcard = getActivity().getExternalFilesDir(null); - home_directory = sdcard + "/dc"; - game_directory = sdcard + "/dc"; - } mPrefs = PreferenceManager.getDefaultSharedPreferences(getActivity()); @@ -124,11 +117,6 @@ public class OptionsFragment extends Fragment { Toast.makeText(getActivity(), R.string.data_folder, Toast.LENGTH_SHORT).show(); } - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) { - cleanHouse(getActivity().getExternalFilesDir(null)); - buildHouse(new File(home_directory), getActivity().getExternalFilesDir(null)); - home_directory = sdcard + "/dc"; - } mPrefs.edit().putString("home_directory", home_directory) .commit(); } @@ -518,43 +506,6 @@ public class OptionsFragment extends Fragment { }); } - private void cleanHouse(File dir) { - File[] existing = dir.listFiles(); - for (File item: existing) { - if (item.isDirectory()) { - cleanHouse(item); - } else { - item.delete(); - } - } - } - - private void buildHouse(File dir, File root) { - File[] existing = dir.listFiles(); - for (File item: existing) { - if (item.isDirectory()) { - item.mkdirs(); - buildHouse(item, item); - } else { - try { - copy(item, new File(root + "/" + item)); - } catch (IOException e) { - e.printStackTrace(); - } - } - } - } - - public void copy(File src, File dst) throws IOException { - FileInputStream inStream = new FileInputStream(src); - FileOutputStream outStream = new FileOutputStream(dst); - FileChannel inChannel = inStream.getChannel(); - FileChannel outChannel = outStream.getChannel(); - inChannel.transferTo(0, inChannel.size(), outChannel); - inStream.close(); - outStream.close(); - } - private void flashBios(String localized) { File local = new File(home_directory, "data/dc_flash[" + localized + "].bin"); diff --git a/shell/android/src/com/reicast/emulator/debug/GenerateLogs.java b/shell/android/src/com/reicast/emulator/debug/GenerateLogs.java new file mode 100644 index 000000000..b22db1606 --- /dev/null +++ b/shell/android/src/com/reicast/emulator/debug/GenerateLogs.java @@ -0,0 +1,246 @@ +package com.reicast.emulator.debug; + +import java.io.BufferedReader; +import java.io.BufferedWriter; +import java.io.File; +import java.io.FileInputStream; +import java.io.FileWriter; +import java.io.IOException; +import java.io.InputStream; +import java.io.InputStreamReader; + +import com.reicast.emulator.R; + +import android.content.Context; +import android.os.AsyncTask; +import android.os.Build; +import android.widget.Toast; + +public class GenerateLogs extends AsyncTask { + + public static final String build_model = android.os.Build.MODEL; + public static final String build_device = android.os.Build.DEVICE; + public static final String build_board = android.os.Build.BOARD; + public static final int build_sdk = android.os.Build.VERSION.SDK_INT; + + public static final String DN = "Donut"; + public static final String EC = "Eclair"; + public static final String FR = "Froyo"; + public static final String GB = "Gingerbread"; + public static final String HC = "Honeycomb"; + public static final String IC = "Ice Cream Sandwich"; + public static final String JB = "JellyBean"; + public static final String KK = "KitKat"; + public static final String NF = "Not Found"; + + private String unHandledIOE; + + private Context mContext; + private String currentTime; + + public GenerateLogs(Context mContext) { + this.mContext = mContext; + this.currentTime = String.valueOf(System.currentTimeMillis()); + } + + /** + * Obtain the specific parameters of the current device + * + */ + private String discoverCPUData() { + String s = "MODEL: " + Build.MODEL; + s += "\r\n"; + s += "DEVICE: " + build_device; + s += "\r\n"; + s += "BOARD: " + build_board; + s += "\r\n"; + if (String.valueOf(build_sdk) != null) { + String build_version = NF; + if (build_sdk >= 4 && build_sdk < 7) { + build_version = DN; + } else if (build_sdk == 7) { + build_version = EC; + } else if (build_sdk == 8) { + build_version = FR; + } else if (build_sdk >= 9 && build_sdk < 11) { + build_version = GB; + } else if (build_sdk >= 11 && build_sdk < 14) { + build_version = HC; + } else if (build_sdk >= 14 && build_sdk < 16) { + build_version = IC; + } else if (build_sdk >= 16 && build_sdk < 19) { + build_version = JB; + } else if (build_sdk >= 19) { + build_version = KK; + } + s += build_version + " (" + build_sdk + ")"; + } else { + String prop_build_version = "ro.build.version.release"; + String prop_sdk_version = "ro.build.version.sdk"; + String build_version = readOutput("/system/bin/getprop " + + prop_build_version); + String sdk_version = readOutput("/system/bin/getprop " + + prop_sdk_version); + s += build_version + " (" + sdk_version + ")"; + } + return s; + } + + /** + * Read the output of a shell command + * + * @param command + * The shell command being issued to the terminal + */ + public static String readOutput(String command) { + try { + Process p = Runtime.getRuntime().exec(command); + InputStream is = null; + if (p.waitFor() == 0) { + is = p.getInputStream(); + } else { + is = p.getErrorStream(); + } + BufferedReader br = new BufferedReader(new InputStreamReader(is), + 2048); + String line = br.readLine(); + br.close(); + return line; + } catch (Exception ex) { + return "ERROR: " + ex.getMessage(); + } + } + + public void setUnhandled(String unHandledIOE) { + this.unHandledIOE = unHandledIOE; + } + + @Override + protected String doInBackground(String... params) { + File logFile = new File(params[0], currentTime + ".txt"); + Process mLogcatProc = null; + BufferedReader reader = null; + final StringBuilder log = new StringBuilder(); + String separator = System.getProperty("line.separator"); + log.append(discoverCPUData()); + if (unHandledIOE != null) { + log.append(separator); + log.append(separator); + log.append("Unhandled Exceptions"); + log.append(separator); + log.append(separator); + log.append(unHandledIOE); + } + try { + mLogcatProc = Runtime.getRuntime().exec( + new String[] { "logcat", "-d", "AndroidRuntime:E *:S" }); + reader = new BufferedReader(new InputStreamReader( + mLogcatProc.getInputStream())); + String line; + log.append(separator); + log.append(separator); + log.append("AndroidRuntime Output"); + log.append(separator); + log.append(separator); + while ((line = reader.readLine()) != null) { + log.append(line); + log.append(separator); + } + reader.close(); + mLogcatProc = null; + reader = null; + int PID = android.os.Process.getUidForName("com.reicast.emulator"); + mLogcatProc = Runtime.getRuntime().exec( + new String[] { "logcat", "-d", "|", "grep " + PID }); + reader = new BufferedReader(new InputStreamReader( + mLogcatProc.getInputStream())); + log.append(separator); + log.append(separator); + log.append("Application Core Output"); + log.append(separator); + log.append(separator); + while ((line = reader.readLine()) != null) { + log.append(line); + log.append(separator); + } + reader.close(); + mLogcatProc = null; + reader = null; + mLogcatProc = Runtime.getRuntime().exec( + new String[] { "logcat", "-d", "reidc:V *:S" }); + reader = new BufferedReader(new InputStreamReader( + mLogcatProc.getInputStream())); + log.append(separator); + log.append(separator); + log.append("Native Interface Output"); + log.append(separator); + log.append(separator); + while ((line = reader.readLine()) != null) { + log.append(line); + log.append(separator); + } + reader.close(); + mLogcatProc = null; + reader = null; + mLogcatProc = Runtime.getRuntime().exec( + new String[] { "logcat", "-d", "GL2JNIView:E *:S" }); + reader = new BufferedReader(new InputStreamReader( + mLogcatProc.getInputStream())); + log.append(separator); + log.append(separator); + log.append("Open GLES View Output"); + log.append(separator); + log.append(separator); + while ((line = reader.readLine()) != null) { + log.append(line); + log.append(separator); + } + reader.close(); + mLogcatProc = null; + reader = null; + File memory = new File(mContext.getFilesDir(), "mem_alloc.txt"); + if (memory.exists()) { + log.append(separator); + log.append(separator); + log.append("Memory Allocation Table"); + log.append(separator); + log.append(separator); + FileInputStream fis = new FileInputStream(memory); + reader = new BufferedReader(new InputStreamReader(fis)); + while ((line = reader.readLine()) != null) { + log.append(line); + log.append(separator); + } + fis.close(); + fis = null; + reader.close(); + reader = null; + } + BufferedWriter writer = new BufferedWriter(new FileWriter(logFile)); + writer.write(log.toString()); + writer.flush(); + writer.close(); + return log.toString(); + } catch (IOException e) { + + } + return null; + } + + @Override + protected void onPostExecute(final String response) { + if (response != null && !response.equals(null)) { + Toast.makeText(mContext, mContext.getString(R.string.log_saved), + Toast.LENGTH_SHORT).show(); + Toast.makeText(mContext, mContext.getString(R.string.platform), + Toast.LENGTH_SHORT).show(); + UploadLogs mUploadLogs = new UploadLogs(mContext, currentTime); + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB) { + mUploadLogs.executeOnExecutor( + AsyncTask.THREAD_POOL_EXECUTOR, response); + } else { + mUploadLogs.execute(response); + } + } + } +} diff --git a/shell/android/src/com/reicast/emulator/debug/UploadLogs.java b/shell/android/src/com/reicast/emulator/debug/UploadLogs.java new file mode 100644 index 000000000..a776e3a99 --- /dev/null +++ b/shell/android/src/com/reicast/emulator/debug/UploadLogs.java @@ -0,0 +1,140 @@ +package com.reicast.emulator.debug; + +import java.io.IOException; +import java.net.MalformedURLException; +import java.util.ArrayList; + +import org.apache.http.Header; +import org.apache.http.HttpResponse; +import org.apache.http.HttpStatus; +import org.apache.http.NameValuePair; +import org.apache.http.client.HttpClient; +import org.apache.http.client.entity.UrlEncodedFormEntity; +import org.apache.http.client.methods.HttpPost; +import org.apache.http.impl.client.DefaultHttpClient; +import org.apache.http.message.BasicNameValuePair; +import org.apache.http.util.EntityUtils; + +import com.reicast.emulator.config.Config; + +import android.annotation.SuppressLint; +import android.annotation.TargetApi; +import android.content.Context; +import android.content.Intent; +import android.net.Uri; +import android.os.AsyncTask; +import android.os.Build; +import android.os.StrictMode; + +/** + * Upload the specialized logcat to reicast issues + * + * @param mContext + * The context this method will be executed from + * @param currentTime + * The system time at which the log was made + */ +public class UploadLogs extends AsyncTask { + + private String currentTime; + private String logUrl; + private Context mContext; + + public UploadLogs(Context mContext, String currentTime) { + this.mContext = mContext; + this.currentTime = currentTime; + } + + private void RedirectSubmission(Header[] headers, String content) { + UploadLogs mUploadLogs = new UploadLogs(mContext, + currentTime); + mUploadLogs.setPostUrl(headers[headers.length - 1] + .getValue()); + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB) { + mUploadLogs.executeOnExecutor( + AsyncTask.THREAD_POOL_EXECUTOR, content); + } else { + mUploadLogs.execute(content); + } + } + + /** + * Set the URL for where the log will be uploaded + * + * @param logUrl + * The URL of the log upload server + */ + public void setPostUrl(String logUrl) { + this.logUrl = logUrl; + } + + @SuppressLint("NewApi") + protected void onPreExecute() { + if (logUrl == null || logUrl.equals(null)) { + logUrl = Config.log_url; + } + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.GINGERBREAD) { + StrictMode.ThreadPolicy policy = new StrictMode.ThreadPolicy.Builder() + .permitAll().build(); + StrictMode.setThreadPolicy(policy); + } + } + + @TargetApi(Build.VERSION_CODES.HONEYCOMB) + @Override + protected Object doInBackground(String... params) { + HttpClient client = new DefaultHttpClient(); + HttpPost post = new HttpPost(logUrl); + try { + ArrayList mPairs = new ArrayList(); + mPairs.add(new BasicNameValuePair("name", currentTime)); + mPairs.add(new BasicNameValuePair("issue", params[0])); + post.setEntity(new UrlEncodedFormEntity(mPairs)); + HttpResponse getResponse = client.execute(post); + final int statusCode = getResponse.getStatusLine().getStatusCode(); + if (statusCode != HttpStatus.SC_OK) { + Header[] headers = getResponse.getHeaders("Location"); + if (headers != null && headers.length != 0) { + RedirectSubmission(headers, params[0]); + } else { + return null; + } + } else { + return EntityUtils.toString(getResponse.getEntity()); + } + } catch (MalformedURLException e) { + e.printStackTrace(); + post.abort(); + } catch (IOException e) { + e.printStackTrace(); + post.abort(); + } catch (Exception e) { + e.printStackTrace(); + post.abort(); + } + return null; + } + + @TargetApi(Build.VERSION_CODES.HONEYCOMB) + @SuppressWarnings("deprecation") + @Override + protected void onPostExecute(Object response) { + if (response != null && !response.equals(null)) { + String logLink = Config.report_url + currentTime + ".txt"; + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB) { + android.content.ClipboardManager clipboard = (android.content.ClipboardManager) mContext + .getSystemService(Context.CLIPBOARD_SERVICE); + android.content.ClipData clip = android.content.ClipData + .newPlainText("logcat", logLink); + clipboard.setPrimaryClip(clip); + } else { + android.text.ClipboardManager clipboard = (android.text.ClipboardManager) mContext + .getSystemService(Context.CLIPBOARD_SERVICE); + clipboard.setText(logLink); + } + Intent browserIntent = new Intent(Intent.ACTION_VIEW, + Uri.parse(Config.git_issues)); + mContext.startActivity(browserIntent); + } + } +}