Initial commit

This commit is contained in:
Victor 2013-08-24 15:24:40 +03:00
commit 3218c762c1
30 changed files with 819 additions and 0 deletions

7
.gitignore vendored Normal file
View File

@ -0,0 +1,7 @@
.classpath
.cproject
.project
bin/
gen/
obj/
tmp/

31
AndroidManifest.xml Normal file
View File

@ -0,0 +1,31 @@
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.annimon.donetskwebcam"
android:versionCode="1"
android:versionName="1.1" >
<uses-sdk
android:minSdkVersion="8"
android:targetSdkVersion="18" />
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<application
android:allowBackup="true"
android:icon="@drawable/ic_launcher"
android:label="@string/app_name"
android:theme="@style/AppTheme" >
<activity
android:name=".MainActivity"
android:label="@string/app_name" >
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<activity android:name=".WebcamViewerActvity" />
</application>
</manifest>

70
assets/webcams.txt Normal file
View File

@ -0,0 +1,70 @@
Äîíåöê
Çîëîòîå Êîëüöî http://img1.videoprobki.com.ua/camimg/cam704-5.jpg
Ïëîùàäü Ëåíèíà http://85.90.192.233/cams.php?pathkey=cam5
ÄÒÏÀ http://img1.videoprobki.com.ua/camimg/cam710-5.jpg
Ìèðíûé http://img1.videoprobki.com.ua/camimg/cam705-5.jpg
óë. Àðò¸ìà http://img1.videoprobki.com.ua/camimg/cam703-5.jpg
óë. Àðò¸ìà. Îñòàíîâêà http://img1.videoprobki.com.ua/camimg/cam701-5.jpg
Êðûòûé Ðûíîê http://img1.videoprobki.com.ua/camimg/cam717-5.jpg
ïðîñï. Êèðîâñêèé http://img1.videoprobki.com.ua/camimg/cam716-5.jpg
ïðîñï. Èëüè÷à - Ìàêååâñêîå øîññå http://img1.videoprobki.com.ua/camimg/cam715-5.jpg
Ìàêååâñêîå øîññå http://img1.videoprobki.com.ua/camimg/cam904-5.jpg
Êàòîê 1 http://www.doncity.com.ua/cam/image1.jpg
Êàòîê 2 http://www.doncity.com.ua/cam/image2.jpg
Êàòîê 3 http://www.doncity.com.ua/cam/image3.jpg
Êàòîê 4 http://www.doncity.com.ua/cam/image4.jpg
Äîíáàññ Àðåíà 1 http://shakhtar.com/data/img/webcam/exc003.jpg
Äîíáàññ Àðåíà 2 http://shakhtar.com/data/img/webcam/exc004.jpg
Äîíáàññ Àðåíà 3 http://shakhtar.com/data/img/webcam/exc047.jpg
Äîíáàññ Àðåíà 4 http://shakhtar.com/data/img/webcam/exc048.jpg
Äîíáàññ Àðåíà 5 http://shakhtar.com/data/img/webcam/exc049.jpg
Äîíáàññ Àðåíà 6 http://shakhtar.com/data/img/webcam/southt5.jpg
Ñâÿòîãîðñê http://scs.com.ua/webcam/sgiaz1.jpg
Ïðî÷åå
Ïàðèæ http://www.parisrama.com/webcam9.jpg
**Ãðåöèÿ 1 http://users.otenet.gr/~vbb/snapshot.jpg
Ãðåöèÿ 2 http://www.liveweather.gr/camz.php
Òîêèî 1 http://180.131.126.151/onejpeg.cgi
Òîêèî 2 http://vso.aa0.netvolante.jp/record/current.jpg
Òîêèî 3 http://webcam.dice-k.jp/mjpg/video.mjpg
Ïëÿæ äå-ëàñ-Âèñòàñ http://webcamftp.arona.org/webcam/webcam/LasVistas1.jpg
Ïëÿæ äå-ëàñ-Ãàëüåòàñ http://webcamftp.arona.org/webcam/webcam/LasGalletas1.jpg
ÑØÀ
Ëîñ-Àíæåëåñ 1 http://abclocal.go.com/three/kabc/webcam/web1-1.jpg
Ëîñ-Àíæåëåñ 2 http://abclocal.go.com/three/kabc/webcam/web1-2.jpg
Ëîñ-Àíæåëåñ 3 http://abclocal.go.com/three/kabc/webcam/web2-1.jpg
Ëîñ-Àíæåëåñ 4 http://abclocal.go.com/three/kabc/webcam/web2-2.jpg
Íüþ-Éîðê 1 http://207.251.86.238/cctv377.jpg
Íüþ-Éîðê 2 http://207.251.86.238/cctv382.jpg
Íüþ-Éîðê 3 http://207.251.86.238/cctv19.jpg
Íüþ-Éîðê 4 http://207.251.86.238/cctv20.jpg
Íüþ-Éîðê 5 http://207.251.86.238/cctv387.jpg
Íüþ-Éîðê 6 http://207.251.86.238/cctv400.jpg
Íüþ-Éîðê 7 http://207.251.86.238/cctv403.jpg
Íüþ-Éîðê 8 http://207.251.86.238/cctv414.jpg
Íüþ-Éîðê 9 http://207.251.86.238/cctv426.jpg
Íüþ-Éîðê Ìîñò 1 http://207.251.86.238/cctv371.jpg
Íüþ-Éîðê Ìîñò 2 http://207.251.86.238/cctv374.jpg
Íüþ-Éîðê Ìîñò 3 http://207.251.86.238/cctv375.jpg
Íüþ-Éîðê Ìîñò 4 http://207.251.86.238/cctv386.jpg
Âåëèêîáðèòàíèÿ
Ëîíäîí http://common.gcstatic.com/u/webcam/Webcam73-roof
UK. Hotel Victoria 1 http://www.tiger24.com:8080/cam_1.jpg
UK. Hotel Victoria 2 http://www.tiger24.com:8080/cam_3.jpg
UK. Hotel Victoria 3 http://www.tiger24.com:8080/cam_5.jpg
Õàðüêîâ
óë. Êâèòêè-Îâüÿíåíêî http://img1.videoprobki.com.ua/camimg/cam603-5.jpg
Ïëîùàäü Êîíñòèòóöèè http://img1.videoprobki.com.ua/camimg/cam615-5.jpg
Ïëîùàäü Êîíñòèòóöèè http://img1.videoprobki.com.ua/camimg/cam616-5.jpg
Ïëîùàäü Ïîýçèè http://img1.videoprobki.com.ua/camimg/cam601-5.jpg
Ïëîùàäü Ñâîáîäû http://85.90.192.233/cams.php?pathkey=cam4
Ôîíòàí Çåðêàëüíàÿ Ñòðóÿ http://85.90.192.233/cams.php?pathkey=cam7
óë. Àëåêñåÿ Äåðåâÿíêî http://img1.videoprobki.com.ua/camimg/cam612-5.jpg

BIN
assets/windows-1251.cp Normal file

Binary file not shown.

33
donetsk.htm Normal file
View File

@ -0,0 +1,33 @@
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<title>Донецк</title>
</head>
<body>
<table>
<tr><td>
<img src="http://img1.videoprobki.com.ua/camimg/cam704-5.jpg" alt="Золотое Кольцо">
<img src="http://img1.videoprobki.com.ua/camimg/cam710-5.jpg" alt="Технарь">
<img src="http://img1.videoprobki.com.ua/camimg/cam705-5.jpg" alt="Мирный">
</td></tr>
</table>
<table>
<tr><td>
<img src="http://img1.videoprobki.com.ua/camimg/cam701-5.jpg" alt="ул. Артёма. Остановка">
<img src="http://img1.videoprobki.com.ua/camimg/cam703-5.jpg" alt="ул. Артёма">
<img src="http://img1.videoprobki.com.ua/camimg/cam717-5.jpg" alt="Крытый Рынок">
</td></tr>
</table>
<table>
<tr><td>
<img src="http://img1.videoprobki.com.ua/camimg/cam716-5.jpg" alt="просп. Кировский">
<img src="http://img1.videoprobki.com.ua/camimg/cam715-5.jpg" alt="просп. Ильича - Макеевское шоссе">
<img src="http://img1.videoprobki.com.ua/camimg/cam904-5.jpg" alt="Макеевское шоссе">
</td></tr>
</table>
</body>
</html>

BIN
ic_launcher-web.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 16 KiB

BIN
libs/android-support-v4.jar Normal file

Binary file not shown.

20
proguard-project.txt Normal file
View File

@ -0,0 +1,20 @@
# To enable ProGuard in your project, edit project.properties
# to define the proguard.config property as described in that file.
#
# Add project specific ProGuard rules here.
# By default, the flags in this file are appended to flags specified
# in ${sdk.dir}/tools/proguard/proguard-android.txt
# You can edit the include path and order by changing the ProGuard
# include property in project.properties.
#
# For more details, see
# http://developer.android.com/guide/developing/tools/proguard.html
# Add any project specific keep options here:
# If your project uses WebView with JS, uncomment the following
# and specify the fully qualified class name to the JavaScript interface
# class:
#-keepclassmembers class fqcn.of.javascript.interface.for.webview {
# public *;
#}

14
project.properties Normal file
View File

@ -0,0 +1,14 @@
# This file is automatically generated by Android Tools.
# Do not modify this file -- YOUR CHANGES WILL BE ERASED!
#
# This file must be checked in Version Control Systems.
#
# To customize properties used by the Ant build system edit
# "ant.properties", and override values to adapt the script to your
# project structure.
#
# To enable ProGuard to shrink and obfuscate your code, uncomment this (available properties: sdk.dir, user.home):
#proguard.config=${sdk.dir}/tools/proguard/proguard-android.txt:proguard-project.txt
# Project target.
target=android-18

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 769 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 989 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.8 KiB

26
res/layout-land/main.xml Normal file
View File

@ -0,0 +1,26 @@
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent" >
<fragment
android:id="@+id/webcamViewerFragment"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_gravity="fill"
class="com.annimon.donetskwebcam.WebcamViewerFragment"/>
<LinearLayout
android:layout_width="120dp"
android:layout_height="match_parent">
<fragment
android:id="@+id/webcamChooserFragment"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:layout_gravity="left"
class="com.annimon.donetskwebcam.WebcamChooserFragment" />
</LinearLayout>
</FrameLayout>

12
res/layout-port/main.xml Normal file
View File

@ -0,0 +1,12 @@
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent" >
<fragment
android:id="@+id/webcamChooserFragment"
android:layout_width="match_parent"
android:layout_height="match_parent"
class="com.annimon.donetskwebcam.WebcamChooserFragment" />
</LinearLayout>

View File

@ -0,0 +1,13 @@
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical" >
<fragment
android:id="@+id/webcamViewerFragment"
android:layout_width="match_parent"
android:layout_height="match_parent"
class="com.annimon.donetskwebcam.WebcamViewerFragment" />
</LinearLayout>

21
res/menu/main.xml Normal file
View File

@ -0,0 +1,21 @@
<menu xmlns:android="http://schemas.android.com/apk/res/android" >
<item
android:id="@+id/menu_update"
android:orderInCategory="100"
android:showAsAction="always"
android:title="@string/menu_update"/>
<item
android:id="@+id/menu_auto_update"
android:orderInCategory="100"
android:showAsAction="always"
android:title="@string/menu_auto_update"/>
<item
android:id="@+id/menu_save"
android:orderInCategory="100"
android:showAsAction="ifRoom"
android:title="@string/menu_save"/>
</menu>

11
res/values-v11/styles.xml Normal file
View File

@ -0,0 +1,11 @@
<resources>
<!--
Base application theme for API 11+. This theme completely replaces
AppBaseTheme from res/values/styles.xml on API 11+ devices.
-->
<style name="AppBaseTheme" parent="android:Theme.Holo.Light.NoActionBar.Fullscreen">
<!-- API 11 theme customizations can go here. -->
</style>
</resources>

9
res/values/strings.xml Normal file
View File

@ -0,0 +1,9 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<string name="app_name">Donetsk Webcam</string>
<string name="menu_update">Обновить</string>
<string name="menu_auto_update">Автообновление</string>
<string name="menu_save">Сохранить</string>
</resources>

20
res/values/styles.xml Normal file
View File

@ -0,0 +1,20 @@
<resources>
<!--
Base application theme, dependent on API level. This theme is replaced
by AppBaseTheme from res/values-vXX/styles.xml on newer devices.
-->
<style name="AppBaseTheme" parent="android:Theme.Light.NoTitleBar.Fullscreen">
<!--
Theme customizations available in newer API levels can go in
res/values-vXX/styles.xml, while customizations related to
backward-compatibility can go here.
-->
</style>
<!-- Application theme. -->
<style name="AppTheme" parent="AppBaseTheme">
<!-- All customizations that are NOT specific to a particular API-level can go here. -->
</style>
</resources>

View File

@ -0,0 +1,46 @@
package com.annimon.donetskwebcam;
import java.io.IOException;
import java.io.InputStream;
import java.net.URL;
import java.net.URLConnection;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.os.AsyncTask;
import android.util.Log;
import android.widget.ImageView;
public class ImageDownloadTask extends AsyncTask<String, Void, Bitmap> {
private ImageView imageView;
public ImageDownloadTask(ImageView imageView) {
this.imageView = imageView;
}
@Override
protected Bitmap doInBackground(String... params) {
try {
URL url = new URL(params[0]);
URLConnection urlConn = url.openConnection();
InputStream is = urlConn.getInputStream();
final Bitmap bitmap = BitmapFactory.decodeStream(is);
if (is != null) is.close();
return bitmap;
} catch (IOException ex) {
Log.d(getClass().getName(), ex.getMessage(), ex);
}
return null;
}
@Override
protected void onPostExecute(Bitmap result) {
super.onPostExecute(result);
if (result != null) {
imageView.setImageBitmap(result);
}
}
}

View File

@ -0,0 +1,57 @@
package com.annimon.donetskwebcam;
import android.content.Intent;
import android.content.res.Configuration;
import android.os.Bundle;
import android.support.v4.app.FragmentActivity;
import android.view.Menu;
public class MainActivity extends FragmentActivity implements WebcamChooserFragment.OnWebcamSelectedListener {
private String lastUrl;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
if (savedInstanceState != null) {
lastUrl = savedInstanceState.getString("url");
}
if (isLandscape() && lastUrl != null) {
onWebcamSelected(lastUrl);
}
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
if (isLandscape()) {
getMenuInflater().inflate(R.menu.main, menu);
}
return true;
}
@Override
protected void onSaveInstanceState(Bundle outState) {
super.onSaveInstanceState(outState);
outState.putString("url", lastUrl);
}
@Override
public void onWebcamSelected(String url) {
lastUrl = url;
WebcamViewerFragment viewer = (WebcamViewerFragment) getSupportFragmentManager()
.findFragmentById(R.id.webcamViewerFragment);
if ( (viewer != null) && (viewer.isInLayout()) ) {
viewer.setImageUrl(url);
} else {
Intent intent = new Intent(this, WebcamViewerActvity.class);
intent.putExtra("url", url);
startActivity(intent);
}
}
private boolean isLandscape() {
return (getResources().getConfiguration().orientation == Configuration.ORIENTATION_LANDSCAPE);
}
}

View File

@ -0,0 +1,20 @@
package com.annimon.donetskwebcam;
public class Webcam {
private String name, url;
public Webcam(String name, String url) {
this.name = name;
this.url = url;
}
public String getName() {
return name;
}
public String getUrl() {
return url;
}
}

View File

@ -0,0 +1,88 @@
package com.annimon.donetskwebcam;
import java.util.ArrayList;
import android.annotation.SuppressLint;
import android.content.Context;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.BaseAdapter;
import android.widget.TextView;
public class WebcamAdapter extends BaseAdapter {
private final LayoutInflater mInflater;
private final ArrayList<Webcam> webcams;
@SuppressLint("DefaultLocale")
public WebcamAdapter(Context context, String[] lineText) {
mInflater = LayoutInflater.from(context);
webcams = new ArrayList<Webcam>();
for (String line : lineText) {
if (line == null || line.length() <= 1) continue;
String name, url;
int tabIndex = line.indexOf('\t');
if (tabIndex == -1) {
// Group title
name = line.trim().toUpperCase();
url = null;
} else {
name = line.substring(0, tabIndex).trim();
url = line.substring(tabIndex).trim();
}
webcams.add( new Webcam(name, url) );
}
}
@Override
public int getCount() {
return webcams.size();
}
@Override
public Object getItem(int position) {
return webcams.get(position);
}
@Override
public long getItemId(int position) {
return position;
}
@Override
public View getView(int position, View convertView, ViewGroup parent) {
boolean isGroupTitle = !isEnabled(position);
final ViewHolder holder;
if (convertView == null) {
convertView = mInflater.inflate(android.R.layout.simple_list_item_1, parent, false);
holder = new ViewHolder();
holder.text = (TextView) convertView.findViewById(android.R.id.text1);
convertView.setTag(holder);
} else {
holder = (ViewHolder) convertView.getTag();
}
String name = webcams.get(position).getName();
holder.text.setTextSize(isGroupTitle ? 18 : 13);
holder.text.setText(name);
return convertView;
}
@Override
public boolean isEnabled(int position) {
return webcams.get(position).getUrl() != null;
}
private static class ViewHolder {
TextView text;
}
}

View File

@ -0,0 +1,77 @@
package com.annimon.donetskwebcam;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import android.app.Activity;
import android.os.Bundle;
import android.support.v4.app.ListFragment;
import android.view.View;
import android.widget.ListView;
import com.annimon.encodings.StringCoder;
public class WebcamChooserFragment extends ListFragment {
private WebcamAdapter adapter;
public interface OnWebcamSelectedListener {
public void onWebcamSelected(String url);
}
private OnWebcamSelectedListener listener;
@Override
public void onActivityCreated(Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
String text = getText("webcams.txt", "windows-1251");
adapter = new WebcamAdapter(getActivity(), text.split("\n"));
setListAdapter(adapter);
getListView().setChoiceMode(ListView.CHOICE_MODE_SINGLE);
}
@Override
public void onListItemClick(ListView l, View v, int position, long id) {
String url = ((Webcam)adapter.getItem(position)).getUrl();
listener.onWebcamSelected(url);
}
@Override
public void onAttach(Activity activity) {
super.onAttach(activity);
if (activity instanceof OnWebcamSelectedListener) {
listener = (OnWebcamSelectedListener) activity;
} else {
throw new ClassCastException(activity.toString() + " must implement OnWebcamSelectedListener");
}
}
@Override
public void onDetach() {
super.onDetach();
listener = null;
}
private String getText(String textpath, String encoding) {
String text;
try {
InputStream is = getActivity().getAssets().open(textpath);
ByteArrayOutputStream baos = new ByteArrayOutputStream();
int oneByte;
while ((oneByte = is.read()) != -1) {
baos.write((byte) oneByte);
}
baos.flush();
text = StringCoder.decodeString(baos.toByteArray(), encoding);
is.close();
} catch (IOException ex) {
text = "No data";
}
return text;
}
}

View File

@ -0,0 +1,33 @@
package com.annimon.donetskwebcam;
import android.content.res.Configuration;
import android.os.Bundle;
import android.support.v4.app.FragmentActivity;
import android.view.Menu;
public class WebcamViewerActvity extends FragmentActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
if (getResources().getConfiguration().orientation == Configuration.ORIENTATION_LANDSCAPE) {
finish();
return;
}
setContentView(R.layout.webcam_view);
Bundle extras = getIntent().getExtras();
if (extras != null) {
String url = extras.getString("url");
WebcamViewerFragment viewer = (WebcamViewerFragment) getSupportFragmentManager()
.findFragmentById(R.id.webcamViewerFragment);
viewer.setImageUrl(url);
}
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
getMenuInflater().inflate(R.menu.main, menu);
return true;
}
}

View File

@ -0,0 +1,102 @@
package com.annimon.donetskwebcam;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Timer;
import java.util.TimerTask;
import android.graphics.Bitmap;
import android.graphics.drawable.BitmapDrawable;
import android.os.Bundle;
import android.os.Environment;
import android.support.v4.app.Fragment;
import android.view.LayoutInflater;
import android.view.MenuItem;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ImageView;
import android.widget.Toast;
public class WebcamViewerFragment extends Fragment {
private String imageUrl;
private ImageView contentImage;
private boolean autoUpdate;
private Timer timer;
public WebcamViewerFragment() {
autoUpdate = false;
timer = new Timer();
}
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
setHasOptionsMenu(true);
contentImage = new ImageView(getActivity());
return contentImage;
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()) {
case R.id.menu_auto_update:
autoUpdate = !autoUpdate;
autoUpdate();
break;
case R.id.menu_update:
update();
break;
case R.id.menu_save:
try {
save("image" + File.separator + "Äîíåöê");
Toast.makeText(getActivity(), "Ñîõðàíåíî", Toast.LENGTH_SHORT).show();
} catch (IOException ex) {
ex.printStackTrace();
}
break;
}
return true;
}
public void setImageUrl(String url) {
imageUrl = url;
update();
}
public void update() {
new ImageDownloadTask(contentImage).execute(imageUrl);
}
private void autoUpdate() {
TimerTask task = new TimerTask() {
@Override
public void run() {
update();
}
};
if (autoUpdate) timer.schedule(task, 500, 100);
else {
timer.cancel();
timer = new Timer();
}
}
public void save(String path) throws IOException {
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd_HH.mm.ss");
String fullPath = Environment.getExternalStorageDirectory() +
File.separator + path +
File.separator + sdf.format(new Date()) + ".jpg";
OutputStream out = new FileOutputStream(new File(fullPath));
Bitmap bitmap = ((BitmapDrawable)contentImage.getDrawable()).getBitmap();
bitmap.compress(Bitmap.CompressFormat.JPEG, 85, out);
out.flush();
out.close();
}
}

View File

@ -0,0 +1,44 @@
package com.annimon.encodings;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
public class Charset {
private char[] codepage;
private String charsetName;
public Charset(String charsetName) {
codepage = new char[0x80];
this.charsetName = charsetName;
}
public void loadCodepage() throws UnsupportedEncodingException {
try {
codepage = CharsetLoader.getCodepage(charsetName);
} catch (IOException ioe) {
throw new UnsupportedEncodingException();
}
}
public final char decodeChar(byte signedByte) {
int unsigned = signedByte & 0xff;
int charIndex = unsigned - 0x80;
if ( (0 <= charIndex) && (charIndex < codepage.length) ) {
return codepage[charIndex];
}
return (char) unsigned;
}
public final byte encodeChar(char ch) {
if ( (0 <= ch) && (ch < 0x80) ) return (byte) ch;
for (int i = 0; i < codepage.length; i++) {
if (ch == codepage[i]) return (byte) (i + 0x80);
}
return (byte) ch;
}
}

View File

@ -0,0 +1,28 @@
package com.annimon.encodings;
import java.io.DataInputStream;
import java.io.IOException;
import android.content.res.AssetManager;
public class CharsetLoader {
private static AssetManager assets;
public static void setAssetManager(AssetManager assets) {
CharsetLoader.assets = assets;
}
public static char[] getCodepage(String charsetName) throws IOException {
String assetPath = charsetName + ".cp";
DataInputStream dis = new DataInputStream( assets.open(assetPath) );
char[] codepage = new char[0x80];
for (int i = 0; i < codepage.length; i++) {
codepage[i] = dis.readChar();
}
dis.close();
return codepage;
}
}

View File

@ -0,0 +1,37 @@
package com.annimon.encodings;
import java.io.UnsupportedEncodingException;
public class StringCoder {
public static byte[] encodeString(String s, String enc) throws UnsupportedEncodingException {
byte[] bs;
try {
bs = s.getBytes(enc);
} catch (UnsupportedEncodingException x) {
Charset charset = new Charset(enc);
charset.loadCodepage();
bs = new byte[s.length()];
for (int i = 0; i < s.length(); i++) {
bs[i] = charset.encodeChar(s.charAt(i));
}
}
return bs;
}
public static String decodeString(byte[] bs, String enc) throws UnsupportedEncodingException {
try {
return new String(bs, enc);
} catch (UnsupportedEncodingException x) {
Charset charset = new Charset(enc);
charset.loadCodepage();
StringBuilder sb = new StringBuilder();
for (int i = 0; i < bs.length; i++) {
sb.append( charset.decodeChar(bs[i]) );
}
return sb.toString();
}
}
}