├── .gitignore
├── .idea
├── .name
├── checkstyle-idea.xml
├── compiler.xml
├── copyright
│ └── profiles_settings.xml
├── dictionaries
│ └── angcyo.xml
├── encodings.xml
├── findbugs-idea.xml
├── gradle.xml
├── misc.xml
├── modules.xml
├── runConfigurations.xml
└── vcs.xml
├── app
├── .gitignore
├── build.gradle
├── proguard-rules.pro
└── src
│ ├── androidTest
│ └── java
│ │ └── com
│ │ └── angcyo
│ │ └── paintdemo
│ │ └── ApplicationTest.java
│ ├── main
│ ├── AndroidManifest.xml
│ ├── java
│ │ ├── com
│ │ │ └── angcyo
│ │ │ │ └── paintdemo
│ │ │ │ ├── MainActivity.java
│ │ │ │ ├── RUtil.java
│ │ │ │ ├── paint
│ │ │ │ ├── CircleShape.java
│ │ │ │ ├── ImageShape.java
│ │ │ │ ├── LineShape.java
│ │ │ │ ├── PaintConfig.java
│ │ │ │ ├── PaintShape.java
│ │ │ │ ├── PaintView.java
│ │ │ │ ├── PointShape.java
│ │ │ │ └── RectShape.java
│ │ │ │ └── socket
│ │ │ │ ├── ClientSocket.java
│ │ │ │ ├── ServerSocket.java
│ │ │ │ └── SocketConfig.java
│ │ ├── demo
│ │ │ ├── Demo.java
│ │ │ └── Demo2.java
│ │ └── nt
│ │ │ └── finger
│ │ │ └── paint
│ │ │ ├── DrawView.java
│ │ │ ├── FileChooser.java
│ │ │ ├── FingerPaint.java
│ │ │ ├── FriendlyPoint.java
│ │ │ └── Point.java
│ └── res
│ │ ├── anim
│ │ ├── translate_in.xml
│ │ └── translate_out.xml
│ │ ├── drawable-hdpi
│ │ └── icon.png
│ │ ├── drawable-ldpi
│ │ └── icon.png
│ │ ├── drawable-mdpi
│ │ └── icon.png
│ │ ├── drawable
│ │ ├── button_selector.xml
│ │ └── popup_button_selector.xml
│ │ ├── layout
│ │ ├── activity_main.xml
│ │ ├── content_main.xml
│ │ ├── guide_client_layout.xml
│ │ ├── guide_server_layout.xml
│ │ ├── layout_col_popup.xml
│ │ ├── layout_popup_tip.xml
│ │ ├── layout_width_popup.xml
│ │ └── main.xml
│ │ ├── menu
│ │ ├── menu_main.xml
│ │ └── paint_menu.xml
│ │ ├── mipmap-hdpi
│ │ └── ic_launcher.png
│ │ ├── mipmap-mdpi
│ │ └── ic_launcher.png
│ │ ├── mipmap-xhdpi
│ │ └── ic_launcher.png
│ │ ├── mipmap-xxhdpi
│ │ └── ic_launcher.png
│ │ ├── mipmap-xxxhdpi
│ │ └── ic_launcher.png
│ │ ├── values-v21
│ │ └── styles.xml
│ │ ├── values-w820dp
│ │ └── dimens.xml
│ │ └── values
│ │ ├── colors.xml
│ │ ├── dimens.xml
│ │ ├── strings.xml
│ │ └── styles.xml
│ └── test
│ └── java
│ └── com
│ └── angcyo
│ └── paintdemo
│ └── ExampleUnitTest.java
├── build.gradle
├── gradle.properties
├── gradle
└── wrapper
│ ├── gradle-wrapper.jar
│ └── gradle-wrapper.properties
├── gradlew
├── gradlew.bat
├── javademo
├── .gitignore
├── build.gradle
└── src
│ └── main
│ └── java
│ └── com
│ └── example
│ └── MyClass.java
└── settings.gradle
/.gitignore:
--------------------------------------------------------------------------------
1 | *.iml
2 | .gradle
3 | /local.properties
4 | /.idea/workspace.xml
5 | /.idea/libraries
6 | .DS_Store
7 | /build
8 | /captures
9 |
--------------------------------------------------------------------------------
/.idea/.name:
--------------------------------------------------------------------------------
1 | PaintDemo
--------------------------------------------------------------------------------
/.idea/checkstyle-idea.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
9 |
10 |
--------------------------------------------------------------------------------
/.idea/compiler.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
--------------------------------------------------------------------------------
/.idea/copyright/profiles_settings.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
--------------------------------------------------------------------------------
/.idea/dictionaries/angcyo.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
--------------------------------------------------------------------------------
/.idea/encodings.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/.idea/findbugs-idea.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
13 |
32 |
203 |
216 |
225 |
226 |
--------------------------------------------------------------------------------
/.idea/gradle.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
20 |
21 |
--------------------------------------------------------------------------------
/.idea/misc.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 | Android
46 |
47 |
48 |
49 |
50 |
51 |
52 |
53 |
54 |
55 |
56 |
57 |
58 |
59 |
60 |
61 |
62 |
63 |
64 |
65 |
66 |
67 |
68 |
69 |
70 |
71 |
72 |
73 |
74 |
75 |
76 |
77 |
78 |
79 |
80 |
81 |
82 |
83 |
84 |
85 |
86 |
87 |
88 |
89 |
90 |
91 |
92 |
93 |
94 |
95 |
96 |
--------------------------------------------------------------------------------
/.idea/modules.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
--------------------------------------------------------------------------------
/.idea/runConfigurations.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
--------------------------------------------------------------------------------
/.idea/vcs.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/app/.gitignore:
--------------------------------------------------------------------------------
1 | /build
2 |
--------------------------------------------------------------------------------
/app/build.gradle:
--------------------------------------------------------------------------------
1 | apply plugin: 'com.android.application'
2 |
3 | android {
4 | compileSdkVersion 23
5 | buildToolsVersion "23.0.1"
6 |
7 | defaultConfig {
8 | applicationId "com.angcyo.paintdemo"
9 | minSdkVersion 15
10 | targetSdkVersion 23
11 | versionCode 1
12 | versionName "1.0"
13 | }
14 | buildTypes {
15 | release {
16 | minifyEnabled false
17 | proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
18 | }
19 | }
20 | }
21 |
22 | dependencies {
23 | compile fileTree(dir: 'libs', include: ['*.jar'])
24 | testCompile 'junit:junit:4.12'
25 | compile 'com.android.support:appcompat-v7:23.1.0'
26 | compile 'com.android.support:design:23.1.0'
27 | }
28 |
--------------------------------------------------------------------------------
/app/proguard-rules.pro:
--------------------------------------------------------------------------------
1 | # Add project specific ProGuard rules here.
2 | # By default, the flags in this file are appended to flags specified
3 | # in D:\Android\sdk/tools/proguard/proguard-android.txt
4 | # You can edit the include path and order by changing the proguardFiles
5 | # directive in build.gradle.
6 | #
7 | # For more details, see
8 | # http://developer.android.com/guide/developing/tools/proguard.html
9 |
10 | # Add any project specific keep options here:
11 |
12 | # If your project uses WebView with JS, uncomment the following
13 | # and specify the fully qualified class name to the JavaScript interface
14 | # class:
15 | #-keepclassmembers class fqcn.of.javascript.interface.for.webview {
16 | # public *;
17 | #}
18 |
--------------------------------------------------------------------------------
/app/src/androidTest/java/com/angcyo/paintdemo/ApplicationTest.java:
--------------------------------------------------------------------------------
1 | package com.angcyo.paintdemo;
2 |
3 | import android.app.Application;
4 | import android.test.ApplicationTestCase;
5 |
6 | /**
7 | * Testing Fundamentals
8 | */
9 | public class ApplicationTest extends ApplicationTestCase {
10 | public ApplicationTest() {
11 | super(Application.class);
12 | }
13 | }
--------------------------------------------------------------------------------
/app/src/main/AndroidManifest.xml:
--------------------------------------------------------------------------------
1 |
2 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
16 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
--------------------------------------------------------------------------------
/app/src/main/java/com/angcyo/paintdemo/MainActivity.java:
--------------------------------------------------------------------------------
1 | package com.angcyo.paintdemo;
2 |
3 | import android.content.BroadcastReceiver;
4 | import android.content.Context;
5 | import android.content.Intent;
6 | import android.content.IntentFilter;
7 | import android.graphics.Color;
8 | import android.graphics.drawable.ColorDrawable;
9 | import android.net.Uri;
10 | import android.os.Bundle;
11 | import android.support.design.widget.FloatingActionButton;
12 | import android.support.v4.content.LocalBroadcastManager;
13 | import android.support.v7.app.AppCompatActivity;
14 | import android.text.TextUtils;
15 | import android.view.Gravity;
16 | import android.view.LayoutInflater;
17 | import android.view.Menu;
18 | import android.view.MenuItem;
19 | import android.view.View;
20 | import android.view.ViewGroup;
21 | import android.widget.Button;
22 | import android.widget.EditText;
23 | import android.widget.PopupWindow;
24 | import android.widget.RadioGroup;
25 | import android.widget.TextView;
26 | import android.widget.Toast;
27 |
28 | import com.angcyo.paintdemo.paint.PaintConfig;
29 | import com.angcyo.paintdemo.paint.PaintView;
30 | import com.angcyo.paintdemo.socket.ServerSocket;
31 | import com.angcyo.paintdemo.socket.SocketConfig;
32 |
33 | import java.io.File;
34 |
35 | import nt.finger.paint.FingerPaint;
36 |
37 | public class MainActivity extends AppCompatActivity {
38 |
39 | public static final int GUIDE_WIN_OFFSET = 80;
40 | public static LocalBroadcastManager localBroadcastManager;
41 | boolean isShare = false;
42 | private BroadcastReceiver broadcastReceiver;
43 | private RadioGroup shapeGroup;
44 | private Button btUndo, btColor, btClear, btWidth, btCapture, btShare;
45 | private PaintView paintView;
46 | private PopupWindow mColPopup, mWidthPopup, mGuideServer, mGuideClient, mPopupTips;
47 | private View rootView;
48 | private String localIp;
49 | private ServerSocket mServerSocket;
50 |
51 | @Override
52 | protected void onCreate(Bundle savedInstanceState) {
53 | super.onCreate(savedInstanceState);
54 | // getWindow().addFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS);
55 | setContentView(R.layout.activity_main);
56 | FloatingActionButton fab = (FloatingActionButton) findViewById(R.id.fab);
57 | fab.setOnClickListener(new View.OnClickListener() {
58 | @Override
59 | public void onClick(View view) {
60 | MainActivity.this.startActivity(new Intent(MainActivity.this, FingerPaint.class));
61 | }
62 | });
63 |
64 | fab.setVisibility(View.GONE);
65 | initView();
66 | initEvent();
67 | initData();
68 | initBroadcast();
69 | initShow();
70 | }
71 |
72 | private void initShow() {
73 | rootView.postDelayed(new Runnable() {
74 | @Override
75 | public void run() {
76 | mGuideServer.showAtLocation(rootView, Gravity.TOP | Gravity.CENTER_HORIZONTAL, 0, GUIDE_WIN_OFFSET);
77 | // showPopupTip("Hello Angcyo");
78 | }
79 | }, 1000);
80 | }
81 |
82 | private void showPopupTip(String tip) {
83 | TextView tipView = ((TextView) mPopupTips.getContentView().findViewById(R.id.txTips));
84 | tipView.setText(tip + "");
85 | mPopupTips.showAtLocation(rootView, Gravity.TOP | Gravity.CENTER_HORIZONTAL, 0, GUIDE_WIN_OFFSET);
86 | tipView.postDelayed(new Runnable() {
87 | @Override
88 | public void run() {
89 | if (mPopupTips != null && mPopupTips.isShowing()) {
90 | mPopupTips.dismiss();
91 | }
92 | }
93 | }, 3000);
94 | }
95 |
96 | private void initBroadcast() {
97 | localBroadcastManager = LocalBroadcastManager.getInstance(this);
98 | IntentFilter intentFilter = new IntentFilter(PaintView.BDC_CAPTURE);//监听截图成功的广播
99 | intentFilter.addAction(SocketConfig.BDC_CONNECT_CLIENT);
100 | intentFilter.addAction(SocketConfig.BDC_CONNECT_SERVER);
101 |
102 | broadcastReceiver = new BroadcastReceiver() {
103 | @Override
104 | public void onReceive(Context context, Intent intent) {
105 | final Bundle bundle = intent.getExtras();
106 | if (intent.getAction().equalsIgnoreCase(PaintView.BDC_CAPTURE)) {//截图广播
107 | if (bundle.getInt(PaintView.CAPTURE_CODE) == 1) {
108 | if (isShare) {
109 | share(bundle.getString(PaintView.CAPTURE_PATH));
110 | isShare = false;
111 | } else {
112 | Toast.makeText(MainActivity.this, "保存至:" + bundle.getString(PaintView.CAPTURE_PATH), Toast.LENGTH_LONG).show();
113 | }
114 | } else {
115 | Toast.makeText(MainActivity.this, "截图失败", Toast.LENGTH_LONG).show();
116 | }
117 | }
118 | if (intent.getAction().equalsIgnoreCase(SocketConfig.BDC_CONNECT_CLIENT)) {//客户端连接广播
119 | runOnUiThread(new Runnable() {
120 | @Override
121 | public void run() {
122 | showPopupTip("客户端:" + bundle.getString(SocketConfig.KEY_CLIENT_IP) + "已连接");
123 | }
124 | });
125 | }
126 | if (intent.getAction().equalsIgnoreCase(SocketConfig.BDC_CONNECT_SERVER)) {//连上服务端广播
127 | runOnUiThread(new Runnable() {
128 | @Override
129 | public void run() {
130 | showPopupTip("已连上:" + bundle.getString(SocketConfig.KEY_SERVER_IP) + " 服务端");
131 | }
132 | });
133 | }
134 | }
135 | };
136 | localBroadcastManager.registerReceiver(broadcastReceiver, intentFilter);
137 | }
138 |
139 | private void share(String file) {
140 | isShare = true;
141 | Intent intent = new Intent(Intent.ACTION_SEND);
142 | if (file != null) {
143 | intent.setType("image/*");
144 | intent.putExtra(Intent.EXTRA_STREAM, Uri.fromFile(new File(file)));
145 | } else {
146 | intent.setType("text/plain");
147 | }
148 | intent.putExtra(Intent.EXTRA_SUBJECT, "快快来围观");
149 | intent.putExtra(Intent.EXTRA_TEXT, "为何可以这么美");
150 | intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
151 | startActivity(Intent.createChooser(intent, "分享至"));
152 | }
153 |
154 | private void initData() {
155 | switch (getIndex((RadioGroup) mColPopup.getContentView().findViewById(R.id.colRG))) {
156 | case 1:
157 | PaintConfig.getInstance().setCurrentShapeColor(getResources().getColor(R.color.col2));
158 | break;
159 | case 2:
160 | PaintConfig.getInstance().setCurrentShapeColor(getResources().getColor(R.color.col3));
161 | break;
162 | case 3:
163 | PaintConfig.getInstance().setCurrentShapeColor(getResources().getColor(R.color.col4));
164 | break;
165 | case 4:
166 | PaintConfig.getInstance().setCurrentShapeColor(getResources().getColor(R.color.col5));
167 | break;
168 | case 0:
169 | default:
170 | PaintConfig.getInstance().setCurrentShapeColor(getResources().getColor(R.color.col1));
171 | break;
172 | }
173 | switch (getIndex((RadioGroup) mWidthPopup.getContentView().findViewById(R.id.widthRG))) {
174 | case 1:
175 | PaintConfig.getInstance().setCurrentShapeWidth(getResources().getDimension(R.dimen.width2));
176 | break;
177 | case 2:
178 | PaintConfig.getInstance().setCurrentShapeWidth(getResources().getDimension(R.dimen.width3));
179 | break;
180 | case 3:
181 | PaintConfig.getInstance().setCurrentShapeWidth(getResources().getDimension(R.dimen.width4));
182 | break;
183 | case 4:
184 | PaintConfig.getInstance().setCurrentShapeWidth(getResources().getDimension(R.dimen.width5));
185 | break;
186 | case 0:
187 | default:
188 | PaintConfig.getInstance().setCurrentShapeWidth(getResources().getDimension(R.dimen.width1));
189 | break;
190 | }
191 |
192 | localIp = RUtil.getIp(this);
193 | ((TextView) mGuideServer.getContentView().findViewById(R.id.tips)).setText("本机IP:" + localIp);
194 | }
195 |
196 | private void initEvent() {
197 | shapeGroup.setOnCheckedChangeListener(new RadioGroup.OnCheckedChangeListener() {
198 | @Override
199 | public void onCheckedChanged(RadioGroup group, int checkedId) {
200 | switch (checkedId) {
201 | case R.id.line:
202 | PaintConfig.getInstance().setCurrentShape(PaintConfig.Shape.Line);
203 | break;
204 | case R.id.circle:
205 | PaintConfig.getInstance().setCurrentShape(PaintConfig.Shape.Circle);
206 | break;
207 | case R.id.rect:
208 | PaintConfig.getInstance().setCurrentShape(PaintConfig.Shape.Rect);
209 | break;
210 | case R.id.point:
211 | default:
212 | PaintConfig.getInstance().setCurrentShape(PaintConfig.Shape.Point);
213 | break;
214 | }
215 | }
216 | });
217 |
218 | btUndo.setOnClickListener(new View.OnClickListener() {
219 | @Override
220 | public void onClick(View v) {
221 | paintView.removeLastOne();
222 | }
223 | });
224 | btClear.setOnClickListener(new View.OnClickListener() {
225 | @Override
226 | public void onClick(View v) {
227 | paintView.removeAll();
228 | }
229 | });
230 | btCapture.setOnClickListener(new View.OnClickListener() {
231 | @Override
232 | public void onClick(View v) {
233 | paintView.capture();
234 | }
235 | });
236 | btShare.setOnClickListener(new View.OnClickListener() {
237 | @Override
238 | public void onClick(View v) {
239 | paintView.capture();
240 | isShare = true;
241 | }
242 | });
243 |
244 | btColor.setOnClickListener(new View.OnClickListener() {
245 | @Override
246 | public void onClick(View v) {
247 | mColPopup.showAsDropDown(btColor, btColor.getWidth(), -btColor.getHeight() - 6);
248 | }
249 | });
250 |
251 | btWidth.setOnClickListener(new View.OnClickListener() {
252 | @Override
253 | public void onClick(View v) {
254 | mWidthPopup.showAsDropDown(btWidth, btWidth.getWidth(), -btWidth.getHeight() - 6);
255 | }
256 | });
257 |
258 | mColPopup.setOnDismissListener(new PopupWindow.OnDismissListener() {
259 | @Override
260 | public void onDismiss() {
261 | initData();
262 | }
263 | });
264 | mWidthPopup.setOnDismissListener(new PopupWindow.OnDismissListener() {
265 | @Override
266 | public void onDismiss() {
267 | initData();
268 | }
269 | });
270 |
271 | //作为服务端
272 | mGuideServer.getContentView().findViewById(R.id.btServer).setOnClickListener(new View.OnClickListener() {
273 | @Override
274 | public void onClick(View v) {
275 | mGuideServer.dismiss();
276 | SocketConfig.isServer = true;
277 | SocketConfig.SVR_IP = localIp;
278 | mServerSocket = new ServerSocket(paintView);
279 | new Thread(mServerSocket).start();
280 | showPopupTip("等待连接...");
281 | }
282 | });
283 |
284 | //作为客户端
285 | mGuideServer.getContentView().findViewById(R.id.btClient).setOnClickListener(new View.OnClickListener() {
286 | @Override
287 | public void onClick(View v) {
288 | mGuideServer.dismiss();
289 | SocketConfig.isServer = false;
290 | mGuideClient.showAtLocation(rootView, Gravity.TOP | Gravity.CENTER_HORIZONTAL, 0, GUIDE_WIN_OFFSET);
291 | }
292 | });
293 |
294 | //客户端输入服务器IP
295 | final EditText etServer = (EditText) mGuideClient.getContentView().findViewById(R.id.etServer);
296 | mGuideClient.getContentView().findViewById(R.id.btSaveIp).setOnClickListener(new View.OnClickListener() {
297 | @Override
298 | public void onClick(View v) {
299 | String svrIp = etServer.getText().toString();
300 | if (TextUtils.isEmpty(svrIp)) {
301 | etServer.setError("请输入有效值");
302 | etServer.requestFocus();
303 | return;
304 | }
305 | mGuideClient.dismiss();
306 | SocketConfig.SVR_IP = svrIp;
307 | // SocketConfig.isStartClient = true;
308 | paintView.connectServer();
309 | showPopupTip("正在连接...:" + svrIp);
310 | }
311 | });
312 | }
313 |
314 | private void initView() {
315 | rootView = findViewById(R.id.rootView);
316 | shapeGroup = (RadioGroup) findViewById(R.id.shape_group);
317 | btUndo = (Button) findViewById(R.id.cancel);
318 | btClear = (Button) findViewById(R.id.clear);
319 | btColor = (Button) findViewById(R.id.color);
320 | btWidth = (Button) findViewById(R.id.width);
321 | btCapture = (Button) findViewById(R.id.capture);
322 | btShare = (Button) findViewById(R.id.share);
323 | paintView = (PaintView) findViewById(R.id.paint_view);
324 |
325 | //颜色选择弹窗
326 | LayoutInflater inflater = LayoutInflater.from(this);
327 | View popColLayout = inflater.inflate(R.layout.layout_col_popup, null);
328 | mColPopup = new PopupWindow(popColLayout, ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT, true);
329 | mColPopup.setBackgroundDrawable(new ColorDrawable(Color.TRANSPARENT));//不设置背景,无法响应 返回键 和 界面外点击事件;应该算是谷歌大神的BUG
330 |
331 | //粗细选择弹窗
332 | View popWidthLayout = inflater.inflate(R.layout.layout_width_popup, null);
333 | mWidthPopup = new PopupWindow(popWidthLayout, ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT, true);
334 | mWidthPopup.setBackgroundDrawable(new ColorDrawable(Color.TRANSPARENT));
335 |
336 | //服务端向导
337 | View guideServer = inflater.inflate(R.layout.guide_server_layout, null);
338 | mGuideServer = new PopupWindow(guideServer, ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT, true);
339 | mGuideServer.setBackgroundDrawable(new ColorDrawable(Color.TRANSPARENT));
340 | mGuideServer.setAnimationStyle(R.style.GuideWindowAnimation);
341 |
342 | //客户端向导
343 | View guideClient = inflater.inflate(R.layout.guide_client_layout, null);
344 | mGuideClient = new PopupWindow(guideClient, ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT, true);
345 | mGuideClient.setBackgroundDrawable(new ColorDrawable(Color.TRANSPARENT));
346 | mGuideClient.setAnimationStyle(R.style.GuideWindowAnimation);
347 |
348 | //弹窗提示
349 | View popupTip = inflater.inflate(R.layout.layout_popup_tip, null);
350 | mPopupTips = new PopupWindow(popupTip, ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT, true);
351 | mPopupTips.setBackgroundDrawable(new ColorDrawable(Color.TRANSPARENT));
352 | mPopupTips.setAnimationStyle(R.style.GuideWindowAnimation);
353 | mPopupTips.setTouchable(false);
354 | mPopupTips.setOutsideTouchable(false);
355 | }
356 |
357 | private int getIndex(RadioGroup radioGroup) {
358 | return radioGroup.indexOfChild(radioGroup.findViewById(radioGroup.getCheckedRadioButtonId()));
359 | }
360 |
361 | private void setIndex(RadioGroup radioGroup, int index) {
362 | radioGroup.check(radioGroup.getChildAt(index).getId());
363 | }
364 |
365 |
366 | @Override
367 | protected void onDestroy() {
368 | if (mServerSocket != null) {
369 | mServerSocket.exit();
370 | }
371 | localBroadcastManager.unregisterReceiver(broadcastReceiver);
372 | localBroadcastManager = null;
373 | super.onDestroy();
374 | }
375 |
376 | @Override
377 | public void onBackPressed() {
378 | android.os.Process.killProcess(android.os.Process.myPid());
379 | super.onBackPressed();
380 | }
381 |
382 | @Override
383 | public boolean onCreateOptionsMenu(Menu menu) {
384 | // Inflate the menu; this adds items to the action bar if it is present.
385 | getMenuInflater().inflate(R.menu.menu_main, menu);
386 | return true;
387 | }
388 |
389 | @Override
390 | public boolean onOptionsItemSelected(MenuItem item) {
391 | // Handle action bar item clicks here. The action bar will
392 | // automatically handle clicks on the Home/Up button, so long
393 | // as you specify a parent activity in AndroidManifest.xml.
394 | int id = item.getItemId();
395 |
396 | //noinspection SimplifiableIfStatement
397 | if (id == R.id.action_settings) {
398 | return true;
399 | }
400 |
401 | return super.onOptionsItemSelected(item);
402 | }
403 | }
404 |
--------------------------------------------------------------------------------
/app/src/main/java/com/angcyo/paintdemo/RUtil.java:
--------------------------------------------------------------------------------
1 | package com.angcyo.paintdemo;
2 |
3 | import android.content.Context;
4 | import android.content.Intent;
5 | import android.content.pm.PackageInfo;
6 | import android.content.pm.PackageManager;
7 | import android.graphics.Point;
8 | import android.net.ConnectivityManager;
9 | import android.net.NetworkInfo;
10 | import android.net.Uri;
11 | import android.net.wifi.WifiInfo;
12 | import android.net.wifi.WifiManager;
13 | import android.os.Build;
14 | import android.os.Environment;
15 | import android.telephony.TelephonyManager;
16 | import android.text.TextUtils;
17 | import android.util.DisplayMetrics;
18 | import android.util.Log;
19 | import android.view.WindowManager;
20 |
21 | import java.io.File;
22 | import java.io.FileInputStream;
23 | import java.io.FileOutputStream;
24 | import java.io.InputStream;
25 | import java.io.OutputStream;
26 | import java.net.InetAddress;
27 | import java.net.NetworkInterface;
28 | import java.net.SocketException;
29 | import java.text.DecimalFormat;
30 | import java.text.SimpleDateFormat;
31 | import java.util.Date;
32 | import java.util.Enumeration;
33 | import java.util.Properties;
34 | import java.util.Random;
35 |
36 | /**
37 | * Created by angcyo on 15-09-08-008.
38 | */
39 | public class RUtil {
40 | static String config = getSDPath() + File.separator + "config.ini";
41 |
42 | /**
43 | * 去除字符串左右的字符
44 | */
45 | public static String trimMarks(String des) {
46 | return trimMarks(des, 1);
47 | }
48 |
49 | /**
50 | * 去除字符串左右指定个数的字符
51 | */
52 | public static String trimMarks(String des, int count) {
53 | if (des == null || count < 0 || des.length() < count + 1) {
54 | return des;
55 | }
56 | return des.substring(count, des.length() - count);
57 | }
58 |
59 | /**
60 | * 返回现在的时间,不包含日期
61 | */
62 | public static String getNowTime() {
63 | return getNowTime("HH:mm:ss");
64 | }
65 |
66 | public static String getNowTime(String pattern) {
67 | SimpleDateFormat dateFormat = new SimpleDateFormat(pattern);
68 | return dateFormat.format(new Date());
69 | }
70 |
71 | /**
72 | * 判断字符串是否为空
73 | */
74 | public static boolean isEmpty(String str) {
75 | return (str == null || str.trim().length() < 1);
76 | }
77 |
78 | /**
79 | * 判断网络是否可以用
80 | *
81 | * @param context the con
82 | * @return the boolean
83 | */
84 | public static boolean isNetOk(Context context) {
85 | ConnectivityManager cm = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE);
86 | if (cm == null)
87 | return false;
88 | NetworkInfo netInfo = cm.getActiveNetworkInfo();
89 | if (netInfo == null) {
90 | return false;
91 | }
92 | if (netInfo.isConnected()) {
93 | return true;
94 | }
95 | return false;
96 | }
97 |
98 | // 可以使用Time类,更简单
99 |
100 | /**
101 | * 获取网络的名字
102 | *
103 | * @param context the context
104 | * @return the net type name
105 | */
106 | public static String getNetTypeName(Context context) {
107 | ConnectivityManager connectivityManager = (ConnectivityManager) context
108 | .getSystemService(Context.CONNECTIVITY_SERVICE);
109 | if (connectivityManager != null) {
110 | NetworkInfo activeNetworkInfo = connectivityManager
111 | .getActiveNetworkInfo();
112 | if (activeNetworkInfo == null) {
113 | return "无网络";
114 | }
115 | if (activeNetworkInfo.getType() == ConnectivityManager.TYPE_WIFI) {
116 | return activeNetworkInfo.getTypeName();
117 | } else {
118 | String typeName = activeNetworkInfo.getSubtypeName();
119 | // MyLog.i("网络名称:", typeName);
120 | if (typeName == null || typeName.length() == 0) {
121 | return "未知网络";
122 | } else if (typeName.length() > 3) {
123 | return activeNetworkInfo.getSubtypeName().substring(0, 4);
124 | } else {
125 | return activeNetworkInfo.getSubtypeName().substring(0,
126 | typeName.length());
127 | }
128 | }
129 | } else {
130 | return "无网络";
131 | }
132 | }
133 |
134 | /**
135 | * @return 按照HH:mm:ss 返回时间
136 | */
137 | public static String getTime() {
138 | SimpleDateFormat format = new SimpleDateFormat("HH:mm:ss");
139 | return format.format(new Date());
140 | }
141 |
142 | /**
143 | * @return 按照yyyy-MM-dd 格式返回日期
144 | */
145 | public static String getDate() {
146 | SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd");
147 | return format.format(new Date());
148 | }
149 |
150 | /**
151 | * @return 按照yyyy-MM-dd HH:mm:ss 的格式返回日期和时间
152 | */
153 | public static String getDateAndTime() {
154 | SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
155 | return format.format(new Date());
156 | }
157 |
158 | /**
159 | * @param pattern 格式
160 | * @return 返回日期
161 | */
162 | public static String getDate(String pattern) {
163 | SimpleDateFormat format = new SimpleDateFormat(pattern);
164 | return format.format(new Date());
165 | }
166 |
167 | /**
168 | * @param pattern 格式
169 | * @return 按照指定格式返回时间
170 | */
171 | public static String getTime(String pattern) {
172 | SimpleDateFormat format = new SimpleDateFormat(pattern);
173 | return format.format(new Date());
174 | }
175 |
176 | /**
177 | * @param pattern 指定的格式
178 | * @return 按照指定格式返回日期和时间
179 | */
180 | public static String getDateAndTime(String pattern) {
181 | SimpleDateFormat format = new SimpleDateFormat(pattern);
182 | return format.format(new Date());
183 | }
184 |
185 | //
186 |
187 | /**
188 | * 需要权限
189 | *
190 | * @param context 上下文
191 | * @return 返回手机号码
192 | */
193 | public static String getTelNumber(Context context) {
194 | TelephonyManager tm = (TelephonyManager) context
195 | .getSystemService(Context.TELEPHONY_SERVICE);
196 | return tm.getLine1Number();
197 | }
198 |
199 | /**
200 | * 取得device的IP address
201 | *
202 | * 需要权限 android.permission.ACCESS_WIFI_STATE
203 | *
204 | * @param context
205 | * @return 返回ip
206 | */
207 | public static String getWifiIp(Context context) {
208 | WifiManager wifiManager = (WifiManager) context
209 | .getSystemService(Context.WIFI_SERVICE);
210 | WifiInfo wifiInfo = wifiManager.getConnectionInfo();
211 | int ipAddress = wifiInfo.getIpAddress();
212 |
213 | // 格式化IP address,例如:格式化前:1828825280,格式化后:192.168.1.109
214 | String ip = String.format("%d.%d.%d.%d", (ipAddress & 0xff),
215 | (ipAddress >> 8 & 0xff), (ipAddress >> 16 & 0xff),
216 | (ipAddress >> 24 & 0xff));
217 | return ip;
218 | }
219 |
220 | /**
221 | * 获取网络ip
222 | */
223 | public static String getIp(Context context) {
224 | if (isWifiConnected(context)) {
225 | return getWifiIp(context);
226 | } else {
227 | return getMobileIP();
228 | }
229 | }
230 |
231 | /**
232 | * Get IP For mobile
233 | */
234 | public static String getMobileIP() {
235 | try {
236 | for (Enumeration en = NetworkInterface.getNetworkInterfaces(); en.hasMoreElements(); ) {
237 | NetworkInterface intf = (NetworkInterface) en.nextElement();
238 | for (Enumeration enumIpAddr = intf.getInetAddresses(); enumIpAddr.hasMoreElements(); ) {
239 | InetAddress inetAddress = enumIpAddr.nextElement();
240 | if (!inetAddress.isLoopbackAddress()) {
241 | String ipaddress = inetAddress.getHostAddress().toString();
242 | return ipaddress;
243 | }
244 | }
245 | }
246 | } catch (SocketException ex) {
247 | Log.e("getMobileIP", "Exception in Get IP Address: " + ex.toString());
248 | }
249 | return "";
250 | }
251 |
252 | /**
253 | * @return 获取device的os version
254 | */
255 | public static String getOsVersion() {
256 | String string = Build.VERSION.RELEASE;
257 | return string;
258 | }
259 |
260 | /**
261 | * @return 返回设备型号
262 | */
263 | public static String getDeviceName() {
264 | String string = Build.MODEL;
265 | return string;
266 | }
267 |
268 | /**
269 | * INTERNAL method that returns the device model name with correct capitalization.
270 | * Taken from: http://stackoverflow.com/a/12707479/1254846
271 | *
272 | * @return The device model name (i.e., "LGE Nexus 5")
273 | */
274 | public static String getDeviceModelName() {
275 | String manufacturer = Build.MANUFACTURER;
276 | String model = Build.MODEL;
277 | if (model.startsWith(manufacturer)) {
278 | return capitalize(model);
279 | } else {
280 | return capitalize(manufacturer) + " " + model;
281 | }
282 | }
283 |
284 | /**
285 | * INTERNAL method that capitalizes the first character of a string
286 | *
287 | * @param s The string to capitalize
288 | * @return The capitalized string
289 | */
290 | public static String capitalize(String s) {
291 | if (s == null || s.length() == 0) {
292 | return "";
293 | }
294 | char first = s.charAt(0);
295 | if (Character.isUpperCase(first)) {
296 | return s;
297 | } else {
298 | return Character.toUpperCase(first) + s.substring(1);
299 | }
300 | }
301 |
302 | /**
303 | * @return 返回设备sdk版本
304 | */
305 | public static String getOsSdk() {
306 | int sdk = Build.VERSION.SDK_INT;
307 | return String.valueOf(sdk);
308 | }
309 |
310 | public static int getRandom() {
311 | Random random = new Random();
312 | return random.nextInt();
313 | }
314 |
315 | /**
316 | * 获取随机数
317 | *
318 | * @param n 最大范围
319 | * @return
320 | */
321 | public static int getRandom(int n) {
322 | Random random = new Random();
323 | return random.nextInt(n);
324 | }
325 |
326 | /**
327 | * 获取字符数组中随机的字符串
328 | *
329 | * @param context
330 | * @param resId
331 | * @return
332 | */
333 | public static String getRandomString(Context context, int resId) {
334 | String[] strings;
335 | strings = context.getResources().getStringArray(resId);
336 |
337 | return strings[getRandom(strings.length)];
338 | }
339 |
340 | /**
341 | * 从资源id获取字符串
342 | *
343 | * @param context 上下文
344 | * @param id 资源id
345 | * @return 字符串
346 | */
347 | public static String getStringForRes(Context context, int id) {
348 | if (context == null) {
349 | return "";
350 | }
351 | return context.getResources().getString(id);
352 | }
353 |
354 | /**
355 | * 返回app的版本名称.
356 | *
357 | * @param context
358 | * @return
359 | */
360 | public static String getAppVersionName(Context context) {
361 | String version = "unknown";
362 | // 获取package manager的实例
363 | PackageManager packageManager = context.getPackageManager();
364 | // getPackageName()是你当前类的包名,0代表是获取版本信息
365 | PackageInfo packInfo;
366 | try {
367 | packInfo = packageManager.getPackageInfo(context.getPackageName(),
368 | 0);
369 | version = packInfo.versionName;
370 | } catch (PackageManager.NameNotFoundException e) {
371 | e.printStackTrace();
372 | }
373 | // Log.i("版本名称:", version);
374 | return version;
375 | }
376 |
377 | /**
378 | * 返回app的版本代码.
379 | *
380 | * @param context
381 | * @return
382 | */
383 | public static int getAppVersionCode(Context context) {
384 | // 获取package manager的实例
385 | PackageManager packageManager = context.getPackageManager();
386 | // getPackageName()是你当前类的包名,0代表是获取版本信息
387 | int code = 1;
388 | PackageInfo packInfo;
389 | try {
390 | packInfo = packageManager.getPackageInfo(context.getPackageName(),
391 | 0);
392 | code = packInfo.versionCode;
393 | } catch (PackageManager.NameNotFoundException e) {
394 | e.printStackTrace();
395 | }
396 | // Log.i("版本代码:", version);
397 | return code;
398 | }
399 |
400 | /**
401 | * 判断网络是否可用
402 | *
403 | * @param context
404 | * @return
405 | */
406 | public static boolean isNetworkOK(Context context) {
407 | ConnectivityManager cm = (ConnectivityManager) context
408 | .getSystemService(Context.CONNECTIVITY_SERVICE);
409 |
410 | NetworkInfo info = cm.getActiveNetworkInfo();
411 |
412 | if (info != null && info.isConnectedOrConnecting()) {
413 | return true;
414 | }
415 | return false;
416 | }
417 |
418 | /**
419 | * 判断wifi是否可用
420 | *
421 | * @param context
422 | * @return
423 | */
424 | public static boolean isWifiConnected(Context context) {
425 | if (context != null) {
426 | ConnectivityManager mConnectivityManager = (ConnectivityManager) context
427 | .getSystemService(Context.CONNECTIVITY_SERVICE);
428 | NetworkInfo mWiFiNetworkInfo = mConnectivityManager
429 | .getNetworkInfo(ConnectivityManager.TYPE_WIFI); // 返回WIFI
430 | // 的连接info
431 | if (mWiFiNetworkInfo != null) {
432 | return mWiFiNetworkInfo.isAvailable();
433 | }
434 | }
435 | return false;
436 | }
437 |
438 | /**
439 | * 获取屏幕的宽度高度
440 | *
441 | * @param context
442 | * @param size
443 | */
444 | public static DisplayMetrics getDisplay(Context context, Point size) {
445 | WindowManager windowManager = (WindowManager) context
446 | .getSystemService(Context.WINDOW_SERVICE);
447 | windowManager.getDefaultDisplay().getSize(size);
448 | DisplayMetrics outMetrics = new DisplayMetrics();
449 | windowManager.getDefaultDisplay().getMetrics(outMetrics);
450 | return outMetrics;
451 | }
452 |
453 | /**
454 | * 格式化字节
455 | *
456 | * @param size
457 | * @return
458 | * @date 2014年12月3日
459 | */
460 | public static String formatSize(long size) {
461 | if (size / (1024 * 1024) > 0) {
462 | float tmpSize = (float) (size) / (float) (1024 * 1024);
463 | DecimalFormat df = new DecimalFormat("#.##");
464 | return "" + df.format(tmpSize) + "MB";
465 | } else if (size / 1024 > 0) {
466 | return "" + (size / (1024)) + "KB";
467 | } else
468 | return "" + size + "B";
469 | }
470 |
471 | public static String formatSize(String size) {
472 |
473 | if (size.substring(size.length() - 1).equalsIgnoreCase("B")
474 | || size.endsWith("-")) {
475 | return size;
476 | } else {
477 | return formatSize(Long.valueOf(size));
478 | }
479 |
480 | }
481 |
482 | /**
483 | * 是否分割kb单位
484 | *
485 | * @param size
486 | * @param isNewLine
487 | * @return
488 | * @date 2014年12月3日
489 | */
490 | public static String formatSize(long size, boolean isNewLine) {
491 | if (isNewLine == false) {
492 | return formatSize(size);
493 | }
494 | if (size / (1024 * 1024) > 0) {
495 | float tmpSize = (float) (size) / (float) (1024 * 1024);
496 | DecimalFormat df = new DecimalFormat("#.##");
497 | return "" + df.format(tmpSize) + "\nMB";
498 | } else if (size / 1024 > 0) {
499 | return "" + (size / (1024)) + "\nKB";
500 | } else
501 | return "" + size + "\nB";
502 | }
503 |
504 | public static String callMethodAndLine() {
505 | StringBuilder result = new StringBuilder();
506 | StackTraceElement thisMethodStack = (new Exception()).getStackTrace()[1];
507 | result.append(thisMethodStack.getClassName() + ".");
508 | result.append(thisMethodStack.getMethodName());
509 | result.append("(" + thisMethodStack.getFileName());
510 | result.append(":" + thisMethodStack.getLineNumber() + ")");
511 | return result.toString();
512 | }
513 |
514 | public static String callClassName() {
515 | StringBuilder result = new StringBuilder();
516 | StackTraceElement thisMethodStack = (new Exception()).getStackTrace()[1];
517 | result.append(thisMethodStack.getClassName());
518 | return result.toString();
519 | }
520 |
521 | public static String callMethodName() {
522 | StringBuilder result = new StringBuilder();
523 | StackTraceElement thisMethodStack = (new Exception()).getStackTrace()[1];
524 | result.append(thisMethodStack.getMethodName());
525 | return result.toString();
526 | }
527 |
528 | public static String callClassMethodName() {
529 | StringBuilder result = new StringBuilder();
530 | StackTraceElement thisMethodStack = (new Exception()).getStackTrace()[1];
531 | result.append(thisMethodStack.getClassName() + ".");
532 | result.append(thisMethodStack.getMethodName());
533 | return result.toString();
534 | }
535 |
536 | /**
537 | * 返回SD卡路径,如果没有返回默认的下载缓存路径
538 | *
539 | * @return the sD path
540 | */
541 | public static String getSDPath() {
542 | return isExternalStorageWritable() ? Environment
543 | .getExternalStorageDirectory().getPath() : Environment
544 | .getDownloadCacheDirectory().getPath();
545 | }
546 |
547 | /**
548 | * 判断是否有SD卡
549 | *
550 | * @return the boolean
551 | */
552 | public static boolean isExternalStorageWritable() {
553 | String state = Environment.getExternalStorageState();
554 | if (Environment.MEDIA_MOUNTED.equals(state)) {
555 | return true;
556 | }
557 | return false;
558 | }
559 |
560 | /**
561 | * 从配置文件中,获取值
562 | *
563 | * @param key the key
564 | * @param config the config
565 | * @return the string
566 | */
567 | public static String get(String key, String config) {
568 | FileInputStream s;
569 | String value = "";
570 | try {
571 | s = new FileInputStream(config);
572 | Properties properties = new Properties();
573 | properties.load(s);
574 | value = properties.getProperty(key, "");
575 | s.close();
576 | } catch (Exception e) {
577 | }
578 | return value;
579 | }
580 |
581 | /**
582 | * 保存到配置文件 格式: key!value
583 | *
584 | * @param content the content
585 | * @param config the config
586 | */
587 | public static void set(String content, String config) {
588 | Properties prop = new Properties();
589 | String[] values;
590 | InputStream fis = null;
591 | OutputStream fos = null;
592 | try {
593 | fis = new FileInputStream(config);
594 | fos = new FileOutputStream(config);
595 | prop.load(fis);
596 | values = content.split("!");
597 | String value = values.length == 1 ? "" : values[1].trim();
598 | prop.setProperty(values[0].trim(), value);
599 | prop.storeToXML(fos, " by angcyo", "utf-8");
600 | } catch (Exception e) {
601 | } finally {
602 | try {
603 | fis.close();
604 | fos.close();
605 | } catch (Exception e2) {
606 | }
607 | }
608 | }
609 |
610 | public static String get(String key) {
611 | return get(key, config);
612 | }
613 |
614 | public static void set(String content) {
615 | set(content, config);
616 | }
617 |
618 | /**
619 | * 打开网页
620 | *
621 | * @param context the context
622 | * @param url the url
623 | */
624 | public static void openUrl(Context context, String url) {
625 | if (TextUtils.isEmpty(url)) {
626 | return;
627 | }
628 |
629 | if (!url.toLowerCase().startsWith("http:") || !url.toLowerCase().startsWith("https:")) {
630 | url = "http:".concat(url);
631 | }
632 |
633 | Uri webPage = Uri.parse(url);
634 | Intent webIntent = new Intent(Intent.ACTION_VIEW, webPage);
635 | context.startActivity(webIntent);
636 | }
637 |
638 | /**
639 | * 检查是否有网络
640 | */
641 | public static boolean isNetworkAvailable(Context context) {
642 | NetworkInfo info = getNetworkInfo(context);
643 | if (info != null) {
644 | return info.isAvailable();
645 | }
646 | return false;
647 | }
648 |
649 | /**
650 | * 检查是否是WIFI
651 | */
652 | public static boolean isWifi(Context context) {
653 | NetworkInfo info = getNetworkInfo(context);
654 | if (info != null) {
655 | if (info.getType() == ConnectivityManager.TYPE_WIFI)
656 | return true;
657 | }
658 | return false;
659 | }
660 |
661 | /**
662 | * 检查是否是移动网络
663 | */
664 | public static boolean isMobile(Context context) {
665 | NetworkInfo info = getNetworkInfo(context);
666 | if (info != null) {
667 | if (info.getType() == ConnectivityManager.TYPE_MOBILE)
668 | return true;
669 | }
670 | return false;
671 | }
672 |
673 | private static NetworkInfo getNetworkInfo(Context context) {
674 |
675 | ConnectivityManager cm = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE);
676 | return cm.getActiveNetworkInfo();
677 | }
678 | }
679 |
--------------------------------------------------------------------------------
/app/src/main/java/com/angcyo/paintdemo/paint/CircleShape.java:
--------------------------------------------------------------------------------
1 | package com.angcyo.paintdemo.paint;
2 |
3 | import android.graphics.Canvas;
4 | import android.graphics.Paint;
5 |
6 | /**
7 | * Created by angcyo on 15-10-29-029.
8 | */
9 | public class CircleShape extends PaintShape {
10 |
11 |
12 | public CircleShape(float mStartX, float mStartY, Paint mPaint) {
13 | super(mStartX, mStartY, mPaint);
14 | }
15 |
16 | public CircleShape(Paint paint) {
17 | super(paint);
18 | }
19 |
20 | @Override
21 | public void onDraw(Canvas canvas) {
22 | float a = mEndX - mStartX;
23 | float b = mEndY - mStartY;
24 | float c = (float) Math.sqrt(Math.pow(Math.abs(a), 2) + Math.pow(Math.abs(b), 2));
25 |
26 | float centreX = Math.abs((mEndX - mStartX)) / 2 + Math.min(mStartX, mEndX);
27 | float centreY = Math.abs((mEndY - mStartY)) / 2 + Math.min(mStartY, mEndY);
28 | // float centreX = Math.pow(radius, 2) - Math.pow()
29 | // float centreY = Math.abs((mEndY - mStartY)) / 2 + Math.min(mStartY, mEndY);
30 | canvas.drawCircle(centreX, centreY, c / 2, mPaint);
31 | }
32 |
33 | @Override
34 | public String toString() {
35 | StringBuilder builder = new StringBuilder();
36 | builder.append(PaintConfig.Shape.Circle).append(FIELD_SEPARATOR);
37 | builder.append(getFieldString());
38 | return builder.toString();
39 | }
40 | }
41 |
--------------------------------------------------------------------------------
/app/src/main/java/com/angcyo/paintdemo/paint/ImageShape.java:
--------------------------------------------------------------------------------
1 | package com.angcyo.paintdemo.paint;
2 |
3 | import android.graphics.Canvas;
4 | import android.graphics.Paint;
5 |
6 | /**
7 | * Created by angcyo on 15-10-29-029.
8 | */
9 | public class ImageShape extends PaintShape {
10 |
11 |
12 | public ImageShape(float mStartX, float mStartY, Paint mPaint) {
13 | super(mStartX, mStartY, mPaint);
14 | }
15 |
16 | public ImageShape(Paint paint) {
17 | super(paint);
18 | }
19 |
20 | @Override
21 | public void onDraw(Canvas canvas) {
22 |
23 | }
24 |
25 | @Override
26 | public String toString() {
27 | StringBuilder builder = new StringBuilder();
28 | builder.append(PaintConfig.Shape.Image).append(FIELD_SEPARATOR);
29 | builder.append(getFieldString());
30 | return builder.toString();
31 | }
32 | }
33 |
--------------------------------------------------------------------------------
/app/src/main/java/com/angcyo/paintdemo/paint/LineShape.java:
--------------------------------------------------------------------------------
1 | package com.angcyo.paintdemo.paint;
2 |
3 | import android.graphics.Canvas;
4 | import android.graphics.Paint;
5 |
6 | /**
7 | * Created by angcyo on 15-10-29-029.
8 | */
9 | public class LineShape extends PaintShape {
10 |
11 |
12 | public LineShape(float mStartX, float mStartY, Paint mPaint) {
13 | super(mStartX, mStartY, mPaint);
14 | }
15 |
16 | public LineShape(Paint paint) {
17 | super(paint);
18 | }
19 |
20 | @Override
21 | public void onDraw(Canvas canvas) {
22 | canvas.drawLine(mStartX, mStartY, mEndX, mEndY, mPaint);
23 | }
24 |
25 | @Override
26 | public String toString() {
27 | StringBuilder builder = new StringBuilder();
28 | builder.append(PaintConfig.Shape.Line).append(FIELD_SEPARATOR);
29 | builder.append(getFieldString());
30 | return builder.toString();
31 | }
32 | }
33 |
--------------------------------------------------------------------------------
/app/src/main/java/com/angcyo/paintdemo/paint/PaintConfig.java:
--------------------------------------------------------------------------------
1 | package com.angcyo.paintdemo.paint;
2 |
3 | import android.graphics.Color;
4 | import android.support.annotation.ColorInt;
5 |
6 | /**
7 | * Created by angcyo on 15-10-29-029.
8 | */
9 | public class PaintConfig {
10 | static PaintConfig instance;
11 | /**
12 | * 画布宽高
13 | */
14 | int surfaceWidth, surfaceHeight;
15 | /**
16 | * 当前选择的形状
17 | */
18 | int currentShape;
19 | /**
20 | * 当前选择的形状颜色
21 | */
22 | int currentShapeColor;
23 | /**
24 | * 当前选择的形状宽度
25 | */
26 | float currentShapeWidth;
27 | /**
28 | * 画布背景颜色
29 | */
30 | @ColorInt
31 | int surfaceBackgroundColor;
32 |
33 | /**
34 | * 字体大小
35 | */
36 | float fontSize;
37 |
38 | private PaintConfig() {
39 | currentShape = Shape.Point;
40 | currentShapeColor = Color.GREEN;
41 | currentShapeWidth = 10f;
42 |
43 | fontSize = 30f;
44 | surfaceBackgroundColor = Color.WHITE;
45 | }
46 |
47 | public static PaintConfig getInstance() {
48 | if (instance == null) {
49 | synchronized (PaintConfig.class) {
50 | if (instance == null) {
51 | instance = new PaintConfig();
52 | }
53 | }
54 | }
55 | return instance;
56 | }
57 |
58 | public int getSurfaceWidth() {
59 | return surfaceWidth;
60 | }
61 |
62 | public void setSurfaceWidth(int surfaceWidth) {
63 | this.surfaceWidth = surfaceWidth;
64 | }
65 |
66 | public int getSurfaceHeight() {
67 | return surfaceHeight;
68 | }
69 |
70 | public void setSurfaceHeight(int surfaceHeight) {
71 | this.surfaceHeight = surfaceHeight;
72 | }
73 |
74 | public int getCurrentShape() {
75 | return currentShape;
76 | }
77 |
78 | public void setCurrentShape(int currentShape) {
79 | this.currentShape = currentShape;
80 | }
81 |
82 | public int getCurrentShapeColor() {
83 | return currentShapeColor;
84 | }
85 |
86 | public void setCurrentShapeColor(int currentShapeColor) {
87 | this.currentShapeColor = currentShapeColor;
88 | }
89 |
90 | public float getCurrentShapeWidth() {
91 | return currentShapeWidth;
92 | }
93 |
94 | public void setCurrentShapeWidth(float currentShapeWidth) {
95 | this.currentShapeWidth = currentShapeWidth;
96 | }
97 |
98 | public int getSurfaceBackgroundColor() {
99 | return surfaceBackgroundColor;
100 | }
101 |
102 | public void setSurfaceBackgroundColor(int surfaceBackgroundColor) {
103 | this.surfaceBackgroundColor = surfaceBackgroundColor;
104 | }
105 |
106 | public float getFontSize() {
107 | return fontSize;
108 | }
109 |
110 | public void setFontSize(float fontSize) {
111 | this.fontSize = fontSize;
112 | }
113 |
114 | public final static class Shape {
115 | /**
116 | * 点
117 | */
118 | public final static int Point = 1;
119 | /**
120 | * 线
121 | */
122 | public final static int Line = 2;
123 | /**
124 | * 圆
125 | */
126 | public final static int Circle = 3;
127 | /**
128 | * 矩形
129 | */
130 | public final static int Rect = 4;
131 | /**
132 | * 图片
133 | */
134 | public final static int Image = 5;
135 |
136 | }
137 | }
138 |
--------------------------------------------------------------------------------
/app/src/main/java/com/angcyo/paintdemo/paint/PaintShape.java:
--------------------------------------------------------------------------------
1 | package com.angcyo.paintdemo.paint;
2 |
3 | import android.graphics.Canvas;
4 | import android.graphics.Paint;
5 | import android.text.TextUtils;
6 |
7 | /**
8 | * Created by angcyo on 15-10-29-029.
9 | */
10 | public abstract class PaintShape {
11 | public static final String FIELD_SHAPE = "shape";
12 | public static final String FIELD_PAINT_COL = "paint_col";
13 | public static final String FIELD_PAINT_WIDTH = "paint_width";
14 | public static final String FIELD_PAINT_STYLE = "paint_style";
15 | public static final String FIELD_STARTXY = "start_xy";
16 | public static final String FIELD_ENDXY = "end_xy";
17 |
18 | public static final String FIELD_SEPARATOR_REG = "\\|";//匹配用
19 | public static final String FIELD_SEPARATOR = "|";//分隔图形的字段
20 | public static final String SHAPE_SEPARATOR = "@";//分隔不同的图形
21 | public static final String VALUE_SEPARATOR = ":";//分隔字段
22 |
23 | protected float mStartX, mStartY, mEndX, mEndY;
24 | protected Paint mPaint;
25 |
26 | public PaintShape(Paint paint) {
27 | this.mPaint = paint;
28 | }
29 |
30 | public PaintShape(float mStartX, float mStartY, Paint mPaint) {
31 | this.mStartX = mStartX;
32 | this.mStartY = mStartY;
33 | this.mPaint = mPaint;
34 | }
35 |
36 | public static PaintShape generateShape(String string) throws Exception {
37 | PaintShape shape = null;
38 | if (!TextUtils.isEmpty(string)) {
39 | String[] fields = string.split(FIELD_SEPARATOR_REG);
40 |
41 | //解析画笔
42 | Paint paint = new Paint();
43 | paint.setColor(Integer.parseInt(fields[1]));
44 | paint.setStrokeWidth(Float.parseFloat(fields[2]));
45 | String style = fields[3];
46 | if (style.equalsIgnoreCase("FILL")) {
47 | paint.setStyle(Paint.Style.FILL);
48 | } else if (style.equalsIgnoreCase("STROKE")) {
49 | paint.setStyle(Paint.Style.STROKE);
50 | } else if (style.equalsIgnoreCase("FILL_AND_STROKE")) {
51 | paint.setStyle(Paint.Style.FILL_AND_STROKE);
52 | }
53 |
54 | //解析图形
55 | String startXY, endXY;
56 | startXY = fields[4];
57 | endXY = fields[5];
58 |
59 | String[] sXY, eXY;
60 | sXY = startXY.split(VALUE_SEPARATOR);
61 | eXY = endXY.split(VALUE_SEPARATOR);
62 |
63 | switch (Integer.parseInt(fields[0])) {
64 | case PaintConfig.Shape.Point:
65 | shape = new PointShape(Float.parseFloat(sXY[0]), Float.parseFloat(sXY[1]), paint);
66 | break;
67 | case PaintConfig.Shape.Line:
68 | shape = new LineShape(Float.parseFloat(sXY[0]), Float.parseFloat(sXY[1]), paint);
69 | break;
70 | case PaintConfig.Shape.Circle:
71 | shape = new CircleShape(Float.parseFloat(sXY[0]), Float.parseFloat(sXY[1]), paint);
72 | break;
73 | case PaintConfig.Shape.Rect:
74 | shape = new RectShape(Float.parseFloat(sXY[0]), Float.parseFloat(sXY[1]), paint);
75 | break;
76 | case PaintConfig.Shape.Image:
77 | shape = new ImageShape(Float.parseFloat(sXY[0]), Float.parseFloat(sXY[1]), paint);
78 | break;
79 | default:
80 | break;
81 | }
82 |
83 | shape.setmEndX(Float.parseFloat(eXY[0]));
84 | shape.setmEndY(Float.parseFloat(eXY[1]));
85 | }
86 |
87 | return shape;
88 | }
89 |
90 | public float getmStartX() {
91 | return mStartX;
92 | }
93 |
94 | public void setmStartX(float mStartX) {
95 | this.mStartX = mStartX;
96 | }
97 |
98 | public float getmStartY() {
99 | return mStartY;
100 | }
101 |
102 | public void setmStartY(float mStartY) {
103 | this.mStartY = mStartY;
104 | }
105 |
106 | public float getmEndX() {
107 | return mEndX;
108 | }
109 |
110 | public void setmEndX(float mEndX) {
111 | this.mEndX = mEndX;
112 | }
113 |
114 | public float getmEndY() {
115 | return mEndY;
116 | }
117 |
118 | public void setmEndY(float mEndY) {
119 | this.mEndY = mEndY;
120 | }
121 |
122 | public abstract void onDraw(Canvas canvas);
123 |
124 | protected String getFieldString() {
125 | StringBuilder builder = new StringBuilder();
126 | builder.append(mPaint.getColor()).append(FIELD_SEPARATOR);
127 | builder.append(mPaint.getStrokeWidth()).append(FIELD_SEPARATOR);
128 | builder.append(mPaint.getStyle()).append(FIELD_SEPARATOR);
129 | builder.append(mStartX).append(VALUE_SEPARATOR).append(mStartY).append(FIELD_SEPARATOR);
130 | builder.append(mEndX).append(VALUE_SEPARATOR).append(mEndY);
131 | return builder.toString();
132 | }
133 |
134 | @Override
135 | public String toString() {
136 | return getFieldString();
137 | }
138 | }
139 |
--------------------------------------------------------------------------------
/app/src/main/java/com/angcyo/paintdemo/paint/PaintView.java:
--------------------------------------------------------------------------------
1 | package com.angcyo.paintdemo.paint;
2 |
3 | import android.content.Context;
4 | import android.content.Intent;
5 | import android.graphics.Bitmap;
6 | import android.graphics.Canvas;
7 | import android.graphics.Color;
8 | import android.graphics.Paint;
9 | import android.graphics.PixelFormat;
10 | import android.graphics.PorterDuff;
11 | import android.graphics.Rect;
12 | import android.os.Bundle;
13 | import android.os.Environment;
14 | import android.support.annotation.ColorInt;
15 | import android.support.v4.content.LocalBroadcastManager;
16 | import android.util.AttributeSet;
17 | import android.view.MotionEvent;
18 | import android.view.SurfaceHolder;
19 | import android.view.SurfaceView;
20 | import android.view.View;
21 |
22 | import com.angcyo.paintdemo.socket.ClientSocket;
23 |
24 | import java.io.File;
25 | import java.io.FileOutputStream;
26 | import java.util.UUID;
27 | import java.util.Vector;
28 |
29 | /**
30 | * Created by angcyo on 15-10-29-029.
31 | */
32 | public class PaintView extends SurfaceView implements SurfaceHolder.Callback, View.OnTouchListener, ClientSocket.OnDataChangeListener {
33 | public static final String TAG = "PaintView";
34 | public static final String BDC_CAPTURE = "bdc_capture";//
35 | public static final String CAPTURE_PATH = "file_path";
36 | public static final String CAPTURE_CODE = "capture_code";
37 |
38 | public static boolean isRunning = true;
39 | public static volatile boolean isChange = true;//先画一次
40 | public static volatile boolean isSendToServer = true;//是否是发送出去
41 | SurfaceHolder mSurfaceHolder;
42 | @ColorInt
43 | int mViewBGCol;
44 | float downX, downY;
45 | float moveX, moveY;
46 | Paint mFpsPaint;
47 | float fpsCount = 0;
48 | long startTime = 0;
49 | float fps;
50 | Vector mShapes;//所有需要绘制的数据
51 | Vector mBackShapes;//所有需要绘制的数据
52 | PaintShape mShape;
53 | volatile Rect mDirtyRect;
54 | Bitmap captureBmp;
55 | LocalBroadcastManager localBroadcastManager;
56 | private boolean isCapture = false;
57 |
58 | private ClientSocket mClientSocket;
59 |
60 | public PaintView(Context context) {
61 | this(context, null);
62 | }
63 |
64 | public PaintView(Context context, AttributeSet attrs) {
65 | this(context, attrs, 0);
66 | }
67 |
68 | public PaintView(Context context, AttributeSet attrs, int defStyleAttr) {
69 | super(context, attrs, defStyleAttr);
70 | init();
71 | }
72 |
73 | private void init() {
74 | mViewBGCol = PaintConfig.getInstance().getSurfaceBackgroundColor();
75 | mSurfaceHolder = getHolder();
76 | mSurfaceHolder.addCallback(this);
77 | setOnTouchListener(this);
78 |
79 | mShapes = new Vector<>();
80 | //
81 | mFpsPaint = new Paint();
82 | mFpsPaint.setColor(Color.RED);
83 | // mFpsPaint.setStrokeWidth(20f);
84 | mFpsPaint.setTextSize(30f);
85 | mFpsPaint.setAntiAlias(true);
86 | // setBackgroundColor(mViewBGCol);
87 |
88 | localBroadcastManager = LocalBroadcastManager.getInstance(getContext());
89 | }
90 |
91 | @Override
92 | public void surfaceCreated(SurfaceHolder holder) {
93 | // Log.e(TAG, "surfaceCreated");
94 | // setBackgroundColor(mViewBGCol);
95 | isRunning = true;
96 | mSurfaceHolder.setFormat(PixelFormat.TRANSLUCENT);
97 | // mDirtyRect = new Rect((int) downX - 10, (int) downY - 10, (int) downX + 10, (int) downY + 10);
98 | // new Thread(this).start();
99 | }
100 |
101 | @Override
102 | public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {
103 | isChange = true;
104 | PaintConfig.getInstance().setSurfaceWidth(width);
105 | PaintConfig.getInstance().setSurfaceHeight(height);
106 |
107 | doDraw();
108 | // Log.e(TAG, "surfaceChanged");
109 |
110 | // Canvas canvas = mSurfaceHolder.lockCanvas();
111 | // canvas.drawLine(2.0f, 2.0f, 500.0f, 500f, mFpsPaint);
112 | // mSurfaceHolder.unlockCanvasAndPost(canvas);
113 | }
114 |
115 | @Override
116 | public void surfaceDestroyed(SurfaceHolder holder) {
117 | // Log.e(TAG, "surfaceDestroyed");
118 | isRunning = false;
119 |
120 | disconnectServer();
121 | }
122 |
123 | @Override
124 | public boolean onTouch(View v, MotionEvent event) {
125 | switch (event.getAction()) {
126 | case MotionEvent.ACTION_DOWN:
127 | downX = event.getX();
128 | downY = event.getY();
129 | mShape = generateShape(downX, downY);
130 | mShape.setmEndX(downX);
131 | mShape.setmEndY(downY);
132 | mShapes.add(mShape);
133 | mDirtyRect = new Rect((int) downX - 10, (int) downY - 10, (int) downX + 10, (int) downY + 10);
134 | break;
135 | case MotionEvent.ACTION_MOVE:
136 | moveX = event.getX();
137 | moveY = event.getY();
138 | if (PaintConfig.getInstance().getCurrentShape() == PaintConfig.Shape.Point) {
139 | PaintShape shape = generateShape(moveX, moveY);
140 | shape.setmEndX(mShapes.lastElement().getmStartX());
141 | shape.setmEndY(mShapes.lastElement().getmStartY());
142 | mShapes.add(shape);
143 | } else {
144 | mShape.setmEndX(moveX);
145 | mShape.setmEndY(moveY);
146 | }
147 | int left = (int) Math.min(downX, moveX);
148 | int top = (int) Math.min(downY, moveY);
149 | int right = (int) Math.max(downX, moveX);
150 | int bottom = (int) Math.max(downY, moveY);
151 | mDirtyRect = new Rect(left - 10, top - 10, right + 10, bottom + 10);
152 | break;
153 | case MotionEvent.ACTION_UP:
154 | mDirtyRect = null;
155 | break;
156 | }
157 | isChange = true;
158 | isSendToServer = true;
159 | doDraw();
160 | return true;
161 | }
162 |
163 | private PaintShape generateShape(float downX, float downY) {
164 | PaintShape shape;
165 | Paint paint = new Paint();
166 | paint.setColor(PaintConfig.getInstance().getCurrentShapeColor());
167 | paint.setStrokeWidth(PaintConfig.getInstance().getCurrentShapeWidth());
168 | switch (PaintConfig.getInstance().getCurrentShape()) {
169 | case PaintConfig.Shape.Point:
170 | shape = new PointShape(downX, downY, paint);
171 | break;
172 | case PaintConfig.Shape.Line:
173 | shape = new LineShape(downX, downY, paint);
174 | break;
175 | case PaintConfig.Shape.Circle:
176 | paint.setStyle(Paint.Style.STROKE);
177 | shape = new CircleShape(downX, downY, paint);
178 | break;
179 | case PaintConfig.Shape.Rect:
180 | paint.setStyle(Paint.Style.STROKE);
181 | shape = new RectShape(downX, downY, paint);
182 | break;
183 | case PaintConfig.Shape.Image:
184 | shape = new ImageShape(downX, downY, paint);
185 | break;
186 | default:
187 | shape = new PointShape(downX, downY, paint);
188 | break;
189 | }
190 | return shape;
191 | }
192 |
193 | public void doDraw() {
194 | synchronized (this) {
195 | if (isChange) {
196 | //有变化重新绘制
197 | try {
198 | mBackShapes = (Vector) mShapes.clone();
199 | if (isSendToServer) {
200 | try {
201 | ClientSocket.updateWriteData(mBackShapes);
202 | isSendToServer = false;
203 | } catch (Exception e) {
204 | e.printStackTrace();
205 | }
206 | }
207 | } catch (Exception e) {
208 | }
209 | Canvas canvas = null;
210 | try {
211 | canvas = mSurfaceHolder.lockCanvas();
212 | drawBg(canvas);
213 | drawContent(canvas, mBackShapes);
214 |
215 | try {
216 | drawSvrContent(canvas, ClientSocket.getReadData());
217 | } catch (Exception e) {
218 | }
219 | } catch (Exception e) {
220 | } finally {
221 | if (canvas != null) {
222 | mSurfaceHolder.unlockCanvasAndPost(canvas);
223 | }
224 | }
225 | isChange = false;
226 | }
227 |
228 | //截图
229 | if (isCapture) {
230 | try {
231 | if (captureBmp != null) {
232 | captureBmp.recycle();
233 | }
234 | captureBmp = Bitmap.createBitmap(getWidth(), getHeight(), Bitmap.Config.ARGB_8888);
235 | Canvas bitCanvas = new Canvas(captureBmp);
236 | drawBg(bitCanvas);
237 | drawContent(bitCanvas, mBackShapes);
238 | try {
239 | drawSvrContent(bitCanvas, ClientSocket.getReadData());
240 | } catch (Exception e) {
241 | }
242 | // drawFps(bitCanvas);
243 | isCapture = false;
244 | saveBitmap();
245 | } catch (Exception e) {
246 |
247 | }
248 | }
249 | }
250 |
251 | }
252 |
253 | private void disconnectServer() {
254 | if (mClientSocket != null) {
255 | mClientSocket.exit();
256 | }
257 | }
258 |
259 | public void connectServer() {
260 | if (mClientSocket == null) {
261 | mClientSocket = new ClientSocket();
262 | mClientSocket.setDataChangeListener(this);
263 | }
264 | new Thread(mClientSocket).start();
265 | }
266 |
267 | public void setClientSocket(ClientSocket clientSocket) {
268 | if (mClientSocket == null) {
269 | mClientSocket = clientSocket;
270 | mClientSocket.setDataChangeListener(this);
271 | }
272 | }
273 |
274 | private void saveBitmap() {
275 | Intent intent = new Intent(BDC_CAPTURE);
276 | Bundle bundle = new Bundle();
277 | try {
278 | String filePath = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DCIM) + File.separator + UUID.randomUUID() + ".jpg";
279 | File file = new File(filePath);
280 | FileOutputStream fos = new FileOutputStream(file);
281 | captureBmp.compress(Bitmap.CompressFormat.JPEG, 100, fos);
282 | fos.close();
283 | bundle.putInt(CAPTURE_CODE, 1);
284 | bundle.putString(CAPTURE_PATH, filePath);
285 | } catch (Exception e) {
286 | bundle.putInt(CAPTURE_CODE, 0);
287 | }
288 | intent.putExtras(bundle);
289 | localBroadcastManager.sendBroadcast(intent);
290 | }
291 |
292 | /**
293 | * 绘制本地图形
294 | */
295 | private void drawContent(Canvas canvas, Vector shapes) {
296 | if (shapes == null) {
297 | return;
298 | }
299 | for (PaintShape shape : shapes) {
300 | shape.onDraw(canvas);
301 | }
302 | }
303 |
304 | /**
305 | * 绘制服务端发送过来的图形
306 | */
307 | private void drawSvrContent(Canvas canvas, Vector shapes) {
308 | if (shapes == null) {
309 | return;
310 | }
311 | for (PaintShape shape : shapes) {
312 | shape.onDraw(canvas);
313 | }
314 | }
315 |
316 | private void drawBg(Canvas canvas) {
317 | canvas.drawColor(Color.TRANSPARENT, PorterDuff.Mode.CLEAR);//清屏
318 | canvas.drawColor(PaintConfig.getInstance().getSurfaceBackgroundColor());//绘制背景
319 | }
320 |
321 | private void drawFps(Canvas canvas) {
322 | fpsCount++;
323 | long nowTime = System.currentTimeMillis();
324 | if (nowTime - startTime > 1000) {
325 | fps = fpsCount / (nowTime - startTime) * 1000;
326 | startTime = nowTime;
327 | fpsCount = 0;
328 | }
329 | canvas.drawText(String.format("FPS:%.3f", fps), PaintConfig.getInstance().getSurfaceWidth() - 200, 40, mFpsPaint);
330 | }
331 |
332 | public void removeLastOne() {
333 | if (mShapes != null && mShapes.size() > 0) {
334 | mShapes.remove(mShapes.size() - 1);
335 | isChange = true;
336 | isSendToServer = true;
337 | doDraw();
338 | }
339 | }
340 |
341 | public void removeAll() {
342 | if (mShapes != null && mShapes.size() > 0) {
343 | mShapes.clear();
344 | isChange = true;
345 | isSendToServer = true;
346 | doDraw();
347 | }
348 | }
349 |
350 | /**
351 | * 截屏
352 | */
353 | public void capture() {
354 | isCapture = true;
355 | doDraw();
356 | }
357 |
358 | @Override
359 | public void onDataChange() {
360 | isChange = true;
361 | isSendToServer = false;
362 | doDraw();
363 | }
364 | }
365 |
--------------------------------------------------------------------------------
/app/src/main/java/com/angcyo/paintdemo/paint/PointShape.java:
--------------------------------------------------------------------------------
1 | package com.angcyo.paintdemo.paint;
2 |
3 | import android.graphics.Canvas;
4 | import android.graphics.Paint;
5 |
6 | /**
7 | * Created by angcyo on 15-10-29-029.
8 | */
9 | public class PointShape extends PaintShape {
10 |
11 |
12 | public PointShape(float mStartX, float mStartY, Paint mPaint) {
13 | super(mStartX, mStartY, mPaint);
14 | }
15 |
16 | public PointShape(Paint paint) {
17 | super(paint);
18 | }
19 |
20 | @Override
21 | public void onDraw(Canvas canvas) {
22 | Paint paint = new Paint(mPaint);
23 | paint.setStrokeWidth(mPaint.getStrokeWidth());
24 | canvas.drawLine(mStartX, mStartY, mEndX, mEndY, paint);
25 | canvas.drawCircle(mStartX, mStartY, mPaint.getStrokeWidth() / 2, mPaint);
26 | }
27 |
28 | @Override
29 | public String toString() {
30 | StringBuilder builder = new StringBuilder();
31 | builder.append(PaintConfig.Shape.Point).append(FIELD_SEPARATOR);
32 | builder.append(getFieldString());
33 | return builder.toString();
34 | }
35 | }
36 |
--------------------------------------------------------------------------------
/app/src/main/java/com/angcyo/paintdemo/paint/RectShape.java:
--------------------------------------------------------------------------------
1 | package com.angcyo.paintdemo.paint;
2 |
3 | import android.graphics.Canvas;
4 | import android.graphics.Paint;
5 |
6 | /**
7 | * Created by angcyo on 15-10-29-029.
8 | */
9 | public class RectShape extends PaintShape {
10 |
11 |
12 | public RectShape(float mStartX, float mStartY, Paint mPaint) {
13 | super(mStartX, mStartY, mPaint);
14 | }
15 |
16 | public RectShape(Paint paint) {
17 | super(paint);
18 | }
19 |
20 | @Override
21 | public void onDraw(Canvas canvas) {
22 | canvas.drawRect(mStartX, mStartY, mEndX, mEndY, mPaint);
23 | }
24 |
25 | @Override
26 | public String toString() {
27 | StringBuilder builder = new StringBuilder();
28 | builder.append(PaintConfig.Shape.Rect).append(FIELD_SEPARATOR);
29 | builder.append(getFieldString());
30 | return builder.toString();
31 | }
32 | }
33 |
--------------------------------------------------------------------------------
/app/src/main/java/com/angcyo/paintdemo/socket/ClientSocket.java:
--------------------------------------------------------------------------------
1 | package com.angcyo.paintdemo.socket;
2 |
3 | import android.content.Intent;
4 | import android.os.Bundle;
5 | import android.text.TextUtils;
6 | import android.util.Log;
7 |
8 | import com.angcyo.paintdemo.MainActivity;
9 | import com.angcyo.paintdemo.paint.PaintShape;
10 |
11 | import java.io.IOException;
12 | import java.io.InputStream;
13 | import java.io.OutputStream;
14 | import java.net.InetSocketAddress;
15 | import java.net.Socket;
16 | import java.util.Vector;
17 |
18 | /**
19 | * Created by angcyo on 15-10-30-030.
20 | */
21 | public class ClientSocket implements Runnable {
22 | private static Vector writeData;
23 | private static Vector readData;
24 | private static Object lock = new Object();
25 | InputStream inputStream;
26 | OutputStream outputStream;
27 | private boolean isRunning = true;
28 | private boolean isReadWrite = true;
29 | private Socket mSocket;
30 | private ReadRunnable readRunnable;
31 | private WriteRunnable writeRunnable;
32 | private OnDataChangeListener listener;
33 |
34 | public ClientSocket() {
35 | }
36 |
37 | public ClientSocket(Socket mSocket) throws IOException {
38 | this.mSocket = mSocket;
39 | startReadWriteThread();
40 | }
41 |
42 | public static void updateWriteData(Vector newData) {
43 | writeData = (Vector) newData.clone();
44 | synchronized (lock) {
45 | lock.notifyAll();
46 | }
47 | }
48 |
49 | private static synchronized void updateReadData(Vector newData) {
50 | readData = newData;
51 | }
52 |
53 | public static Vector getReadData() {
54 | return readData;
55 | }
56 |
57 | public void setDataChangeListener(OnDataChangeListener listener) {
58 | this.listener = listener;
59 | }
60 |
61 | @Override
62 | public void run() {
63 | while (isRunning) {
64 | //连接服务器
65 | if (mSocket == null) {
66 | try {
67 | connect();
68 | } catch (IOException e) {
69 | mSocket = null;
70 | try {
71 | Thread.sleep(100);
72 | continue;
73 | } catch (InterruptedException e1) {
74 | }
75 | }
76 | }
77 | Thread.yield();
78 | try {
79 | Thread.sleep(500);
80 | } catch (InterruptedException e) {
81 | }
82 | }
83 | try {
84 | disconnect();
85 | } catch (IOException e) {
86 | }
87 | }
88 |
89 | public void exit() {
90 | isRunning = false;
91 | }
92 |
93 | /**
94 | * 连接服务器
95 | */
96 | private void connect() throws IOException {
97 | if (mSocket == null) {
98 | mSocket = new Socket();
99 | mSocket.setSoTimeout(SocketConfig.READ_TIME_OUT);
100 | }
101 | mSocket.connect(new InetSocketAddress(SocketConfig.SVR_IP, SocketConfig.SVR_PORT), SocketConfig.CONNECT_TIME_OUT);
102 | startReadWriteThread();
103 | sendBroadcast();
104 | }
105 |
106 | private void sendBroadcast() {
107 | Intent intent = new Intent(SocketConfig.BDC_CONNECT_SERVER);
108 | Bundle bundle = new Bundle();
109 | bundle.putString(SocketConfig.KEY_SERVER_IP, SocketConfig.SVR_IP);
110 | intent.putExtras(bundle);
111 | MainActivity.localBroadcastManager.sendBroadcast(intent);
112 | }
113 |
114 | private void startReadWriteThread() throws IOException {
115 | inputStream = mSocket.getInputStream();
116 | outputStream = mSocket.getOutputStream();
117 |
118 | readRunnable = new ReadRunnable();
119 | writeRunnable = new WriteRunnable();
120 |
121 | new Thread(readRunnable).start();
122 | new Thread(writeRunnable).start();
123 | }
124 |
125 | /**
126 | * 断开服务器
127 | */
128 | private void disconnect() throws IOException {
129 | if (mSocket != null) {
130 | mSocket.close();
131 | mSocket = null;
132 | isReadWrite = false;
133 | }
134 | }
135 |
136 | /**
137 | * 处理收到的数据
138 | */
139 | private void handleData(String data) {
140 | if (TextUtils.isEmpty(data)) {
141 | return;
142 | }
143 | String[] shapes = data.split(PaintShape.SHAPE_SEPARATOR);
144 | Vector paintShapes = new Vector<>();
145 | for (String shapeStr : shapes) {
146 | try {
147 | shapeStr = shapeStr.replaceAll(SocketConfig.FLAG_SOCKET_READ_END, "");
148 | PaintShape paintShape = PaintShape.generateShape(shapeStr);
149 | paintShapes.add(paintShape);
150 | } catch (Exception e) {
151 |
152 | }
153 | }
154 | updateReadData(paintShapes);
155 |
156 | if (listener != null) {
157 | listener.onDataChange();
158 | }
159 | }
160 |
161 | public interface OnDataChangeListener {
162 | void onDataChange();
163 | }
164 |
165 | /**
166 | * 数据读线程
167 | */
168 | private class ReadRunnable implements Runnable {
169 | @Override
170 | public void run() {//读线程
171 | int len;
172 | byte[] bytes = new byte[1024];
173 | StringBuilder stringBuilder = new StringBuilder();
174 | String line;
175 |
176 | while (isReadWrite) {
177 | try {
178 | len = inputStream.read(bytes);
179 | line = new String(bytes, 0, len);
180 | stringBuilder.append(line);
181 | if (line.endsWith(SocketConfig.FLAG_SOCKET_READ_END)) {
182 | StringBuffer buffer = new StringBuffer(stringBuilder.toString());
183 | Log.e("收到数据: " + buffer.length(), buffer.toString());
184 | handleData(buffer.toString());
185 | stringBuilder = new StringBuilder();
186 | }
187 | } catch (Exception e) {
188 | e.printStackTrace();
189 | }
190 | }
191 | }
192 | }
193 |
194 | /**
195 | * 数据写线程
196 | */
197 | private class WriteRunnable implements Runnable {
198 |
199 | @Override
200 | public void run() {//写数据
201 | while (isReadWrite) {
202 | if (writeData == null || writeData.size() < 1) {
203 | synchronized (lock) {
204 | try {
205 | lock.wait();
206 | } catch (InterruptedException e) {
207 |
208 | }
209 | }
210 | } else {
211 | try {
212 | while (writeData.size() > 0) {
213 | PaintShape shape = writeData.remove(0);
214 | outputStream.write(shape.toString().getBytes());
215 | outputStream.write(PaintShape.SHAPE_SEPARATOR.getBytes());
216 | }
217 | outputStream.write(SocketConfig.FLAG_SOCKET_READ_END.getBytes());
218 | outputStream.flush();
219 | writeData.clear();
220 | writeData = null;
221 | } catch (Exception e) {
222 | try {
223 | disconnect();
224 | } catch (IOException e1) {
225 | }
226 | }
227 | }
228 | }
229 | }
230 | }
231 | }
232 |
--------------------------------------------------------------------------------
/app/src/main/java/com/angcyo/paintdemo/socket/ServerSocket.java:
--------------------------------------------------------------------------------
1 | package com.angcyo.paintdemo.socket;
2 |
3 | import android.content.Intent;
4 | import android.os.Bundle;
5 |
6 | import com.angcyo.paintdemo.MainActivity;
7 | import com.angcyo.paintdemo.paint.PaintView;
8 |
9 | import java.io.IOException;
10 | import java.net.Socket;
11 |
12 | /**
13 | * Created by angcyo on 15-10-30-030.
14 | */
15 | public class ServerSocket implements Runnable {
16 |
17 | java.net.ServerSocket mServerSocket;
18 | Socket mClient;
19 | ClientSocket mClientSocket;
20 | PaintView paintView;
21 |
22 | private boolean isRunning = true;
23 |
24 | public ServerSocket(PaintView paintView) {
25 | this.paintView = paintView;
26 | }
27 |
28 | public void exit() {
29 | isRunning = false;
30 | }
31 |
32 | @Override
33 | public void run() {
34 | while (isRunning) {
35 | if (mClient == null) {
36 | try {
37 | mClient = accept();//监听连接
38 | SocketConfig.CLIENT_IP = mClient.getInetAddress().getHostAddress();
39 | sendBroadcast();
40 | } catch (IOException e) {
41 | mClient = null;
42 | mServerSocket = null;
43 | }
44 | }
45 | if (mClientSocket == null && mClient != null) {
46 | try {
47 | mClientSocket = new ClientSocket(mClient);
48 | paintView.setClientSocket(mClientSocket);
49 | } catch (IOException e) {
50 | try {
51 | mClient.close();
52 | } catch (IOException e1) {
53 | }
54 | mClient = null;
55 | mClientSocket = null;
56 | }
57 | }
58 |
59 | Thread.yield();
60 | try {
61 | Thread.sleep(500);
62 | } catch (InterruptedException e) {
63 | }
64 | }
65 | disconnect();
66 | }
67 |
68 | private void sendBroadcast() {
69 | Intent intent = new Intent(SocketConfig.BDC_CONNECT_CLIENT);
70 | Bundle bundle = new Bundle();
71 | bundle.putString(SocketConfig.KEY_CLIENT_IP, SocketConfig.CLIENT_IP);
72 | intent.putExtras(bundle);
73 | MainActivity.localBroadcastManager.sendBroadcast(intent);
74 | }
75 |
76 |
77 | private void disconnect() {
78 | mClientSocket.exit();
79 | try {
80 | mClient.close();
81 | } catch (IOException e) {
82 | }
83 | try {
84 | mServerSocket.close();
85 | } catch (IOException e) {
86 | e.printStackTrace();
87 | }
88 |
89 | mClientSocket = null;
90 | mClient = null;
91 | mServerSocket = null;
92 | }
93 |
94 | private Socket accept() throws IOException {
95 | if (mServerSocket == null) {
96 | mServerSocket = new java.net.ServerSocket(SocketConfig.SVR_PORT);
97 | }
98 | return mServerSocket.accept();
99 | }
100 | }
101 |
--------------------------------------------------------------------------------
/app/src/main/java/com/angcyo/paintdemo/socket/SocketConfig.java:
--------------------------------------------------------------------------------
1 | package com.angcyo.paintdemo.socket;
2 |
3 | /**
4 | * Created by angcyo on 15-10-30-030.
5 | */
6 | public class SocketConfig {
7 | /**
8 | * 服务端ip
9 | */
10 | public static String SVR_IP = "192.168.1.100";
11 | /**
12 | * 服务端端口
13 | */
14 | public static int SVR_PORT = 8720;
15 |
16 | public static int READ_TIME_OUT = 10000;
17 | public static int CONNECT_TIME_OUT = 10000;
18 |
19 | public static String FLAG_SOCKET_READ_END = "!end!";//数据分隔标示
20 |
21 | public static boolean isServer = false;//当前app属于哪种状态
22 | // public static boolean isStartClient = false;//客户端启动连接
23 |
24 | public static String BDC_CONNECT_SERVER = "connect_server";//连上服务器,发送的广播
25 | public static String BDC_CONNECT_CLIENT = "connect_client";//客户端连上,发送的广播
26 | public static String KEY_SERVER_IP = "server_ip";
27 | public static String KEY_CLIENT_IP = "client_ip";
28 | public static String CLIENT_IP = "192.168.1.100";
29 | }
30 |
--------------------------------------------------------------------------------
/app/src/main/java/demo/Demo.java:
--------------------------------------------------------------------------------
1 | package demo;
2 |
3 | /**
4 | * Created by robi on 2016-04-22 14:55.
5 | */
6 | public class Demo {
7 | }
8 |
--------------------------------------------------------------------------------
/app/src/main/java/demo/Demo2.java:
--------------------------------------------------------------------------------
1 | package demo;
2 |
3 | /**
4 | * Created by robi on 2016-04-22 15:06.
5 | */
6 | public class Demo2 {
7 | }
8 |
--------------------------------------------------------------------------------
/app/src/main/java/nt/finger/paint/DrawView.java:
--------------------------------------------------------------------------------
1 | package nt.finger.paint;
2 |
3 | import android.content.Context;
4 | import android.graphics.Canvas;
5 | import android.graphics.Color;
6 | import android.graphics.Paint;
7 | import android.util.Log;
8 | import android.view.MotionEvent;
9 | import android.view.View;
10 | import android.view.View.OnTouchListener;
11 |
12 | import java.util.ArrayList;
13 | import java.util.List;
14 | import java.util.Random;
15 |
16 | public class DrawView extends View implements OnTouchListener {
17 | private static final String TAG = "DrawView";
18 |
19 | List points = new ArrayList();
20 | Paint paint = new Paint();
21 | Random gen;
22 | int col_mode;
23 | int wid_mode;
24 |
25 | public DrawView(Context context) {
26 | super(context);
27 |
28 | // set default colour to white
29 | col_mode = 0;
30 |
31 | // set default width to 7px
32 | wid_mode = 10;
33 |
34 | setFocusable(true);
35 | setFocusableInTouchMode(true);
36 |
37 | this.setOnTouchListener(this);
38 |
39 | paint.setAntiAlias(true);
40 | }
41 |
42 | // used to clear the screen
43 | public void clearPoints () {
44 | points.clear();
45 | forceRedraw();
46 | }
47 |
48 | /**
49 | * Force view to redraw. Without this points aren't cleared until next action
50 | */
51 | public void forceRedraw() {
52 | invalidate();
53 | }
54 |
55 | // used to set drawing colour
56 | public void changeColour (int col_in) {
57 | col_mode = col_in;
58 | }
59 |
60 | // used to set drawing width
61 | public void changeWidth (int wid_in) {
62 | wid_mode = wid_in;
63 | }
64 |
65 | @Override
66 | public void onDraw(Canvas canvas) {
67 | // for each point, draw on canvas
68 | for (Point point : points) {
69 | point.draw(canvas, paint);
70 | Log.d(TAG, "pointcount: " + points.size());
71 | }
72 | }
73 |
74 | public boolean onTouch(View view, MotionEvent event) {
75 | int new_col = 0;
76 | if (col_mode < 0) {
77 | gen = new Random();
78 | col_mode = gen.nextInt( 8 );
79 | }
80 | // This if statement may be redundant now
81 | if (col_mode >= 0) {
82 | switch (col_mode) {
83 | case 0 : {
84 | new_col = Color.WHITE;
85 | break;
86 | }
87 | case 1 : {
88 | new_col = Color.BLUE;
89 | break;
90 | }
91 | case 2 : {
92 | new_col = Color.CYAN;
93 | break;
94 | }
95 | case 3 : {
96 | new_col = Color.GREEN;
97 | break;
98 | }
99 | case 4 : {
100 | new_col = Color.MAGENTA;
101 | break;
102 | }
103 | case 5 : {
104 | new_col = Color.RED;
105 | break;
106 | }
107 | case 6 : {
108 | new_col = Color.YELLOW;
109 | break;
110 | }
111 | case 7 : {
112 | new_col = Color.BLACK;
113 | break;
114 | }
115 | }
116 | }
117 | /* else {
118 | gen = new Random();
119 | new_col = gen.nextInt( 8 );
120 | } */
121 | Point point;
122 | if(event.getAction() == MotionEvent.ACTION_MOVE) {
123 | point = new FriendlyPoint(event.getX(), event.getY(), new_col, points.get(points.size() - 1), wid_mode);
124 | } else if (event.getAction() == MotionEvent.ACTION_DOWN) {
125 | point = new Point(event.getX(), event.getY(), new_col, wid_mode);
126 | } else {
127 | return false;
128 | }
129 | points.add(point);
130 | forceRedraw();
131 | Log.d(TAG, "point: " + point);
132 | return true;
133 | }
134 | }
--------------------------------------------------------------------------------
/app/src/main/java/nt/finger/paint/FileChooser.java:
--------------------------------------------------------------------------------
1 | package nt.finger.paint;
2 |
3 | import java.io.File;
4 | import java.io.FilenameFilter;
5 |
6 | import android.app.Activity;
7 | import android.app.AlertDialog;
8 | import android.app.AlertDialog.Builder;
9 | import android.app.Dialog;
10 | import android.content.DialogInterface;
11 | import android.graphics.Color;
12 | import android.os.Bundle;
13 | import android.os.Environment;
14 | import android.util.Log;
15 | import android.view.Window;
16 | import android.view.WindowManager;
17 |
18 | public class FileChooser extends Activity {
19 | private static final String TAG = "FileChooser";
20 | private String[] mFileList;
21 | private File mPath = new File(Environment.getExternalStorageDirectory() + "//yourdir//");
22 | private String mChosenFile;
23 | private static final String JPG = ".jpg";
24 | private static final String JPEG = ".jpeg";
25 | private static final String PNG = ".png";
26 | private static final int DIALOG_LOAD_FILE = 1000;
27 |
28 | @Override
29 | public void onCreate(Bundle savedInstanceState) {
30 | super.onCreate(savedInstanceState);
31 | // Set full screen view
32 | getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN, WindowManager.LayoutParams.FLAG_FULLSCREEN);
33 | requestWindowFeature(Window.FEATURE_NO_TITLE);
34 |
35 | loadFileList();
36 | }
37 |
38 | private void loadFileList() {
39 | try {
40 | mPath.mkdirs();
41 | }
42 | catch(SecurityException e) {
43 | Log.e(TAG, "unable to write on the SD card " + e.toString());
44 | }
45 |
46 | if (mPath.exists()) {
47 | FilenameFilter filter = new FilenameFilter() {
48 | public boolean accept(File dir, String filename) {
49 | File sel = new File(dir, filename);
50 | return filename.contains(JPG) || filename.contains(JPEG) || filename.contains(PNG) || sel.isDirectory();
51 | }
52 | };
53 | mFileList = mPath.list(filter);
54 | } else {
55 | mFileList = new String[0];
56 | }
57 | }
58 |
59 | protected Dialog onCreateDialog(int id) {
60 | Dialog dialog = null;
61 | Builder builder = new Builder(this);
62 |
63 | switch (id) {
64 | case DIALOG_LOAD_FILE :
65 | builder.setTitle("Choose your background");
66 | if (mFileList == null) {
67 | Log.e(TAG, "Showing file chooser before loading the file list");
68 | dialog = builder.create();
69 | return dialog;
70 | }
71 | builder.setItems(mFileList, new DialogInterface.OnClickListener(){
72 | public void onClick(DialogInterface dialog, int which){
73 | mChosenFile = mFileList[which];
74 | // do other shit with file
75 | }
76 | });
77 | break;
78 | }
79 | dialog = builder.show();
80 | return dialog;
81 | }
82 | }
83 |
--------------------------------------------------------------------------------
/app/src/main/java/nt/finger/paint/FingerPaint.java:
--------------------------------------------------------------------------------
1 | package nt.finger.paint;
2 |
3 | import android.content.Intent;
4 | import android.database.Cursor;
5 | import android.graphics.Color;
6 | import android.graphics.drawable.Drawable;
7 | import android.net.Uri;
8 | import android.os.Bundle;
9 | import android.provider.MediaStore;
10 | import android.support.v7.app.AppCompatActivity;
11 | import android.util.Log;
12 | import android.view.Menu;
13 | import android.view.MenuInflater;
14 | import android.view.MenuItem;
15 |
16 | import com.angcyo.paintdemo.R;
17 |
18 | public class FingerPaint extends AppCompatActivity {
19 | private static final String TAG = "FingerPaint";
20 | DrawView drawView;
21 |
22 | /** Called when the activity is first created. */
23 | @Override
24 | public void onCreate(Bundle savedInstanceState) {
25 | super.onCreate(savedInstanceState);
26 | // Set full screen view
27 | // getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN, WindowManager.LayoutParams.FLAG_FULLSCREEN);
28 | // requestWindowFeature(Window.FEATURE_NO_TITLE);
29 |
30 | // lock screen orientation (stops screen clearing when rotating phone)
31 | setRequestedOrientation(getResources().getConfiguration().orientation);
32 |
33 | drawView = new DrawView(this);
34 | setContentView(drawView);
35 | drawView.setBackgroundColor(Color.BLACK);
36 | drawView.requestFocus();
37 | }
38 |
39 | @Override
40 | public boolean onCreateOptionsMenu(Menu menu) {
41 | MenuInflater inflater = getMenuInflater();
42 | inflater.inflate(R.menu.paint_menu, menu);
43 | return true;
44 | }
45 |
46 | @Override
47 | public boolean onOptionsItemSelected(MenuItem item) {
48 | // Handle item selection
49 | switch (item.getItemId()) {
50 | case R.id.clear_id : {
51 | drawView.clearPoints();
52 | return true;
53 | }
54 | case R.id.p_white_id : {
55 | drawView.changeColour(0);
56 | return true;
57 | }
58 | case R.id.p_blue_id : {
59 | drawView.changeColour(1);
60 | return true;
61 | }
62 | case R.id.p_lblue_id : {
63 | drawView.changeColour(2);
64 | return true;
65 | }
66 | case R.id.p_green_id : {
67 | drawView.changeColour(3);
68 | return true;
69 | }
70 | case R.id.p_pink_id : {
71 | drawView.changeColour(4);
72 | return true;
73 | }
74 | case R.id.p_red_id : {
75 | drawView.changeColour(5);
76 | return true;
77 | }
78 | case R.id.p_yellow_id : {
79 | drawView.changeColour(6);
80 | return true;
81 | }
82 | case R.id.p_black_id : {
83 | drawView.changeColour(7);
84 | return true;
85 | }
86 | case R.id.p_random_id : {
87 | drawView.changeColour(-1);
88 | return true;
89 | }
90 | case R.id.b_white_id : {
91 | drawView.setBackgroundColor(Color.WHITE);
92 | return true;
93 | }
94 | case R.id.b_blue_id : {
95 | drawView.setBackgroundColor(Color.BLUE);
96 | return true;
97 | }
98 | case R.id.b_lblue_id : {
99 | drawView.setBackgroundColor(Color.CYAN);
100 | return true;
101 | }
102 | case R.id.b_green_id : {
103 | drawView.setBackgroundColor(Color.GREEN);
104 | return true;
105 | }
106 | case R.id.b_pink_id : {
107 | drawView.setBackgroundColor(Color.MAGENTA);
108 | return true;
109 | }
110 | case R.id.b_red_id : {
111 | drawView.setBackgroundColor(Color.RED);
112 | return true;
113 | }
114 | case R.id.b_yellow_id : {
115 | drawView.setBackgroundColor(Color.YELLOW);
116 | return true;
117 | }
118 | case R.id.b_black_id : {
119 | drawView.setBackgroundColor(Color.BLACK);
120 | return true;
121 | }
122 | case R.id.b_custom_id : {
123 | setCustomBackground(drawView);
124 | return true;
125 | }
126 | case R.id.w_xsmall : {
127 | drawView.changeWidth(0);
128 | return true;
129 | }
130 | case R.id.w_small : {
131 | drawView.changeWidth(5);
132 | return true;
133 | }
134 | case R.id.w_medium : {
135 | drawView.changeWidth(10);
136 | return true;
137 | }
138 | case R.id.w_large : {
139 | drawView.changeWidth(15);
140 | return true;
141 | }
142 | case R.id.w_xlarge : {
143 | drawView.changeWidth(20);
144 | return true;
145 | }
146 | default : {
147 | return true;
148 | }
149 | }
150 | }
151 |
152 | void setCustomBackground(DrawView v) {
153 | Intent fileChooserIntent = new Intent();
154 | fileChooserIntent.addCategory(Intent.CATEGORY_OPENABLE);
155 | fileChooserIntent.setType("image/*");
156 | fileChooserIntent.setAction(Intent.ACTION_GET_CONTENT);
157 | startActivityForResult(Intent.createChooser(fileChooserIntent, "Select Picture"), 1);
158 | /*
159 | // menu option for setting a custom background
160 | String Url = "http://www.google.ca"; // http://www.google.ca
161 | Intent fileChooserIntent = new Intent(Intent.ACTION_CHOOSER, Uri.parse(Url));
162 | this.startActivity(fileChooserIntent);
163 | */
164 | }
165 |
166 | @Override
167 | protected void onActivityResult(int requestCode, int resultCode, Intent data) {
168 | // if statement prevents force close error when picture isn't selected
169 | if (resultCode == RESULT_OK)
170 | {
171 | Uri resultUri = data.getData();
172 | //String resultString = data.getData().toString();
173 |
174 | String drawString = resultUri.getPath();
175 | String galleryString = getGalleryPath(resultUri);
176 |
177 | // if Gallery app was used
178 | if (galleryString != null)
179 | {
180 | Log.d(TAG, galleryString);
181 | drawString = galleryString;
182 | }
183 | // else another file manager was used
184 | else
185 | {
186 | Log.d(TAG, drawString);
187 | //File Manager: "content://org.openintents.cmfilemanager/mimetype//mnt/sdcard/DCIM/Camera/IMG_20110909_210412.jpg"
188 | //ASTRO: "file:///mnt/sdcard/DCIM/Camera/IMG_20110924_133324.jpg"
189 | if (drawString.contains("//"))
190 | {
191 | drawString = drawString.substring(drawString.lastIndexOf("//"));
192 | }
193 | }
194 |
195 | // set the background to the selected picture
196 | if (drawString.length() > 0)
197 | {
198 | Drawable drawBackground = Drawable.createFromPath(drawString);
199 | drawView.setBackgroundDrawable(drawBackground);
200 | }
201 |
202 | }
203 | }
204 |
205 | // used when trying to get an image path from the URI returned by the Gallery app
206 | public String getGalleryPath(Uri uri) {
207 | String[] projection = { MediaStore.Images.Media.DATA };
208 | Cursor cursor = managedQuery(uri, projection, null, null, null);
209 |
210 | if (cursor != null)
211 | {
212 | int column_index = cursor.getColumnIndexOrThrow(MediaStore.Images.Media.DATA);
213 | cursor.moveToFirst();
214 | return cursor.getString(column_index);
215 | }
216 |
217 |
218 | return null;
219 | }
220 |
221 | }
--------------------------------------------------------------------------------
/app/src/main/java/nt/finger/paint/FriendlyPoint.java:
--------------------------------------------------------------------------------
1 | package nt.finger.paint;
2 |
3 | import android.graphics.Canvas;
4 | import android.graphics.Paint;
5 |
6 | public class FriendlyPoint extends Point {
7 |
8 | private final Point neighbour;
9 |
10 | public FriendlyPoint(final float x, final float y, final int col, final Point neighbour, final int width) {
11 | super(x, y, col, width);
12 | this.neighbour = neighbour;
13 | }
14 |
15 | @Override
16 | public void draw(final Canvas canvas, final Paint paint) {
17 | paint.setColor(col);
18 | paint.setStrokeWidth(width);
19 | canvas.drawLine(x, y, neighbour.x, neighbour.y, paint);
20 | // experimenting with smoother drawing --
21 | // the circle should hopefully act as a smoothing hinge between line segments
22 | // o----o----o------o
23 | canvas.drawCircle(x, y, width/2, paint);
24 | }
25 |
26 | @Override
27 | public String toString() {
28 | return x + ", " + y + ", " + col + "; N[" + neighbour.toString() + "]";
29 | }
30 | }
31 |
--------------------------------------------------------------------------------
/app/src/main/java/nt/finger/paint/Point.java:
--------------------------------------------------------------------------------
1 | package nt.finger.paint;
2 |
3 | import android.graphics.Canvas;
4 | import android.graphics.Paint;
5 |
6 | public class Point {
7 | public final float x, y;
8 | public final int col;
9 | public final int width;
10 |
11 | public Point(final float x, final float y, final int col, final int width) {
12 | this.x = x;
13 | this.y = y;
14 | this.col = col;
15 | this.width = width;
16 | }
17 |
18 | public void draw(final Canvas canvas, final Paint paint) {
19 | paint.setColor(col);
20 | canvas.drawCircle(x, y, width/2, paint);
21 | }
22 |
23 | @Override
24 | public String toString() {
25 | return x + ", " + y + ", " + col;
26 | }
27 | }
28 |
--------------------------------------------------------------------------------
/app/src/main/res/anim/translate_in.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
10 |
--------------------------------------------------------------------------------
/app/src/main/res/anim/translate_out.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
10 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable-hdpi/icon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/angcyo/PaintDemo/0fc20dd32bf69a9188fb3216ea5b365a5838757a/app/src/main/res/drawable-hdpi/icon.png
--------------------------------------------------------------------------------
/app/src/main/res/drawable-ldpi/icon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/angcyo/PaintDemo/0fc20dd32bf69a9188fb3216ea5b365a5838757a/app/src/main/res/drawable-ldpi/icon.png
--------------------------------------------------------------------------------
/app/src/main/res/drawable-mdpi/icon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/angcyo/PaintDemo/0fc20dd32bf69a9188fb3216ea5b365a5838757a/app/src/main/res/drawable-mdpi/icon.png
--------------------------------------------------------------------------------
/app/src/main/res/drawable/button_selector.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | -
4 |
5 |
6 |
7 |
8 |
9 | -
10 |
11 |
12 |
13 |
14 |
15 | -
16 |
17 |
18 |
19 |
20 |
21 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/popup_button_selector.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | -
4 |
5 |
6 |
7 |
8 |
9 |
10 | -
11 |
12 |
13 |
14 |
15 |
16 |
17 | -
18 |
19 |
20 |
21 |
22 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/activity_main.xml:
--------------------------------------------------------------------------------
1 |
2 |
10 |
11 |
12 |
13 |
20 |
21 |
22 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/content_main.xml:
--------------------------------------------------------------------------------
1 |
2 |
10 |
11 |
15 |
16 |
24 |
25 |
29 |
30 |
34 |
35 |
39 |
40 |
44 |
45 |
49 |
50 |
54 |
55 |
59 |
60 |
64 |
65 |
69 |
70 |
74 |
75 |
76 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/guide_client_layout.xml:
--------------------------------------------------------------------------------
1 |
2 |
10 |
11 |
21 |
22 |
29 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/guide_server_layout.xml:
--------------------------------------------------------------------------------
1 |
2 |
11 |
12 |
17 |
18 |
25 |
26 |
33 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/layout_col_popup.xml:
--------------------------------------------------------------------------------
1 |
2 |
5 |
6 |
12 |
13 |
16 |
17 |
20 |
21 |
24 |
25 |
28 |
29 |
32 |
33 |
34 |
39 |
40 |
44 |
45 |
49 |
50 |
54 |
55 |
59 |
60 |
64 |
65 |
66 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/layout_popup_tip.xml:
--------------------------------------------------------------------------------
1 |
2 |
9 |
10 |
15 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/layout_width_popup.xml:
--------------------------------------------------------------------------------
1 |
2 |
5 |
6 |
12 |
13 |
16 |
17 |
20 |
21 |
24 |
25 |
28 |
29 |
32 |
33 |
34 |
39 |
40 |
43 |
44 |
47 |
48 |
51 |
52 |
55 |
56 |
59 |
60 |
61 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/main.xml:
--------------------------------------------------------------------------------
1 |
2 |
7 |
12 |
13 |
--------------------------------------------------------------------------------
/app/src/main/res/menu/menu_main.xml:
--------------------------------------------------------------------------------
1 |
11 |
--------------------------------------------------------------------------------
/app/src/main/res/menu/paint_menu.xml:
--------------------------------------------------------------------------------
1 |
2 |
126 |
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-hdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/angcyo/PaintDemo/0fc20dd32bf69a9188fb3216ea5b365a5838757a/app/src/main/res/mipmap-hdpi/ic_launcher.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-mdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/angcyo/PaintDemo/0fc20dd32bf69a9188fb3216ea5b365a5838757a/app/src/main/res/mipmap-mdpi/ic_launcher.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/angcyo/PaintDemo/0fc20dd32bf69a9188fb3216ea5b365a5838757a/app/src/main/res/mipmap-xhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xxhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/angcyo/PaintDemo/0fc20dd32bf69a9188fb3216ea5b365a5838757a/app/src/main/res/mipmap-xxhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/angcyo/PaintDemo/0fc20dd32bf69a9188fb3216ea5b365a5838757a/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/app/src/main/res/values-v21/styles.xml:
--------------------------------------------------------------------------------
1 | >
2 |
3 |
9 |
10 |
--------------------------------------------------------------------------------
/app/src/main/res/values-w820dp/dimens.xml:
--------------------------------------------------------------------------------
1 |
2 |
5 | 64dp
6 |
7 |
--------------------------------------------------------------------------------
/app/src/main/res/values/colors.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | #3F51B5
4 | #303F9F
5 | #FF4081
6 |
7 | #169CDB
8 | #E8461F
9 | #7045AB
10 | #009688
11 | #FF00FF
12 |
13 |
--------------------------------------------------------------------------------
/app/src/main/res/values/dimens.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | 16dp
4 | 16dp
5 | 16dp
6 | 30dp
7 | 30dp
8 | 26dp
9 | 2dp
10 | 2dp
11 | 2dp
12 | 4dp
13 | 6dp
14 | 8dp
15 | 10dp
16 |
17 |
--------------------------------------------------------------------------------
/app/src/main/res/values/strings.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | Hello World!
4 | Paint Demo
5 | Setting
6 |
7 |
--------------------------------------------------------------------------------
/app/src/main/res/values/styles.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
10 |
11 |
15 |
16 |
17 |
18 |
19 |
20 |
28 |
29 |
36 |
37 |
42 |
43 |
47 |
--------------------------------------------------------------------------------
/app/src/test/java/com/angcyo/paintdemo/ExampleUnitTest.java:
--------------------------------------------------------------------------------
1 | package com.angcyo.paintdemo;
2 |
3 | import org.junit.Test;
4 |
5 | import static org.junit.Assert.*;
6 |
7 | /**
8 | * To work on unit tests, switch the Test Artifact in the Build Variants view.
9 | */
10 | public class ExampleUnitTest {
11 | @Test
12 | public void addition_isCorrect() throws Exception {
13 | assertEquals(4, 2 + 2);
14 | }
15 | }
--------------------------------------------------------------------------------
/build.gradle:
--------------------------------------------------------------------------------
1 | // Top-level build file where you can add configuration options common to all sub-projects/modules.
2 |
3 | buildscript {
4 | repositories {
5 | jcenter()
6 | }
7 | dependencies {
8 | classpath 'com.android.tools.build:gradle:1.3.0'
9 |
10 | // NOTE: Do not place your application dependencies here; they belong
11 | // in the individual module build.gradle files
12 | }
13 | }
14 |
15 | allprojects {
16 | repositories {
17 | jcenter()
18 | }
19 | }
20 |
21 | task clean(type: Delete) {
22 | delete rootProject.buildDir
23 | }
24 |
--------------------------------------------------------------------------------
/gradle.properties:
--------------------------------------------------------------------------------
1 | # Project-wide Gradle settings.
2 |
3 | # IDE (e.g. Android Studio) users:
4 | # Gradle settings configured through the IDE *will override*
5 | # any settings specified in this file.
6 |
7 | # For more details on how to configure your build environment visit
8 | # http://www.gradle.org/docs/current/userguide/build_environment.html
9 |
10 | # Specifies the JVM arguments used for the daemon process.
11 | # The setting is particularly useful for tweaking memory settings.
12 | # Default value: -Xmx10248m -XX:MaxPermSize=256m
13 | # org.gradle.jvmargs=-Xmx2048m -XX:MaxPermSize=512m -XX:+HeapDumpOnOutOfMemoryError -Dfile.encoding=UTF-8
14 |
15 | # When configured, Gradle will run in incubating parallel mode.
16 | # This option should only be used with decoupled projects. More details, visit
17 | # http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects
18 | # org.gradle.parallel=true
--------------------------------------------------------------------------------
/gradle/wrapper/gradle-wrapper.jar:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/angcyo/PaintDemo/0fc20dd32bf69a9188fb3216ea5b365a5838757a/gradle/wrapper/gradle-wrapper.jar
--------------------------------------------------------------------------------
/gradle/wrapper/gradle-wrapper.properties:
--------------------------------------------------------------------------------
1 | #Thu Oct 29 11:09:33 CST 2015
2 | distributionBase=GRADLE_USER_HOME
3 | distributionPath=wrapper/dists
4 | zipStoreBase=GRADLE_USER_HOME
5 | zipStorePath=wrapper/dists
6 | distributionUrl=https\://services.gradle.org/distributions/gradle-2.4-all.zip
7 |
--------------------------------------------------------------------------------
/gradlew:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env bash
2 |
3 | ##############################################################################
4 | ##
5 | ## Gradle start up script for UN*X
6 | ##
7 | ##############################################################################
8 |
9 | # Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
10 | DEFAULT_JVM_OPTS=""
11 |
12 | APP_NAME="Gradle"
13 | APP_BASE_NAME=`basename "$0"`
14 |
15 | # Use the maximum available, or set MAX_FD != -1 to use that value.
16 | MAX_FD="maximum"
17 |
18 | warn ( ) {
19 | echo "$*"
20 | }
21 |
22 | die ( ) {
23 | echo
24 | echo "$*"
25 | echo
26 | exit 1
27 | }
28 |
29 | # OS specific support (must be 'true' or 'false').
30 | cygwin=false
31 | msys=false
32 | darwin=false
33 | case "`uname`" in
34 | CYGWIN* )
35 | cygwin=true
36 | ;;
37 | Darwin* )
38 | darwin=true
39 | ;;
40 | MINGW* )
41 | msys=true
42 | ;;
43 | esac
44 |
45 | # For Cygwin, ensure paths are in UNIX format before anything is touched.
46 | if $cygwin ; then
47 | [ -n "$JAVA_HOME" ] && JAVA_HOME=`cygpath --unix "$JAVA_HOME"`
48 | fi
49 |
50 | # Attempt to set APP_HOME
51 | # Resolve links: $0 may be a link
52 | PRG="$0"
53 | # Need this for relative symlinks.
54 | while [ -h "$PRG" ] ; do
55 | ls=`ls -ld "$PRG"`
56 | link=`expr "$ls" : '.*-> \(.*\)$'`
57 | if expr "$link" : '/.*' > /dev/null; then
58 | PRG="$link"
59 | else
60 | PRG=`dirname "$PRG"`"/$link"
61 | fi
62 | done
63 | SAVED="`pwd`"
64 | cd "`dirname \"$PRG\"`/" >&-
65 | APP_HOME="`pwd -P`"
66 | cd "$SAVED" >&-
67 |
68 | CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
69 |
70 | # Determine the Java command to use to start the JVM.
71 | if [ -n "$JAVA_HOME" ] ; then
72 | if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
73 | # IBM's JDK on AIX uses strange locations for the executables
74 | JAVACMD="$JAVA_HOME/jre/sh/java"
75 | else
76 | JAVACMD="$JAVA_HOME/bin/java"
77 | fi
78 | if [ ! -x "$JAVACMD" ] ; then
79 | die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME
80 |
81 | Please set the JAVA_HOME variable in your environment to match the
82 | location of your Java installation."
83 | fi
84 | else
85 | JAVACMD="java"
86 | which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
87 |
88 | Please set the JAVA_HOME variable in your environment to match the
89 | location of your Java installation."
90 | fi
91 |
92 | # Increase the maximum file descriptors if we can.
93 | if [ "$cygwin" = "false" -a "$darwin" = "false" ] ; then
94 | MAX_FD_LIMIT=`ulimit -H -n`
95 | if [ $? -eq 0 ] ; then
96 | if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then
97 | MAX_FD="$MAX_FD_LIMIT"
98 | fi
99 | ulimit -n $MAX_FD
100 | if [ $? -ne 0 ] ; then
101 | warn "Could not set maximum file descriptor limit: $MAX_FD"
102 | fi
103 | else
104 | warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT"
105 | fi
106 | fi
107 |
108 | # For Darwin, add options to specify how the application appears in the dock
109 | if $darwin; then
110 | GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\""
111 | fi
112 |
113 | # For Cygwin, switch paths to Windows format before running java
114 | if $cygwin ; then
115 | APP_HOME=`cygpath --path --mixed "$APP_HOME"`
116 | CLASSPATH=`cygpath --path --mixed "$CLASSPATH"`
117 |
118 | # We build the pattern for arguments to be converted via cygpath
119 | ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null`
120 | SEP=""
121 | for dir in $ROOTDIRSRAW ; do
122 | ROOTDIRS="$ROOTDIRS$SEP$dir"
123 | SEP="|"
124 | done
125 | OURCYGPATTERN="(^($ROOTDIRS))"
126 | # Add a user-defined pattern to the cygpath arguments
127 | if [ "$GRADLE_CYGPATTERN" != "" ] ; then
128 | OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)"
129 | fi
130 | # Now convert the arguments - kludge to limit ourselves to /bin/sh
131 | i=0
132 | for arg in "$@" ; do
133 | CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -`
134 | CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option
135 |
136 | if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition
137 | eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"`
138 | else
139 | eval `echo args$i`="\"$arg\""
140 | fi
141 | i=$((i+1))
142 | done
143 | case $i in
144 | (0) set -- ;;
145 | (1) set -- "$args0" ;;
146 | (2) set -- "$args0" "$args1" ;;
147 | (3) set -- "$args0" "$args1" "$args2" ;;
148 | (4) set -- "$args0" "$args1" "$args2" "$args3" ;;
149 | (5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;;
150 | (6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;;
151 | (7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;;
152 | (8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;;
153 | (9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;;
154 | esac
155 | fi
156 |
157 | # Split up the JVM_OPTS And GRADLE_OPTS values into an array, following the shell quoting and substitution rules
158 | function splitJvmOpts() {
159 | JVM_OPTS=("$@")
160 | }
161 | eval splitJvmOpts $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS
162 | JVM_OPTS[${#JVM_OPTS[*]}]="-Dorg.gradle.appname=$APP_BASE_NAME"
163 |
164 | exec "$JAVACMD" "${JVM_OPTS[@]}" -classpath "$CLASSPATH" org.gradle.wrapper.GradleWrapperMain "$@"
165 |
--------------------------------------------------------------------------------
/gradlew.bat:
--------------------------------------------------------------------------------
1 | @if "%DEBUG%" == "" @echo off
2 | @rem ##########################################################################
3 | @rem
4 | @rem Gradle startup script for Windows
5 | @rem
6 | @rem ##########################################################################
7 |
8 | @rem Set local scope for the variables with windows NT shell
9 | if "%OS%"=="Windows_NT" setlocal
10 |
11 | @rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
12 | set DEFAULT_JVM_OPTS=
13 |
14 | set DIRNAME=%~dp0
15 | if "%DIRNAME%" == "" set DIRNAME=.
16 | set APP_BASE_NAME=%~n0
17 | set APP_HOME=%DIRNAME%
18 |
19 | @rem Find java.exe
20 | if defined JAVA_HOME goto findJavaFromJavaHome
21 |
22 | set JAVA_EXE=java.exe
23 | %JAVA_EXE% -version >NUL 2>&1
24 | if "%ERRORLEVEL%" == "0" goto init
25 |
26 | echo.
27 | echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
28 | echo.
29 | echo Please set the JAVA_HOME variable in your environment to match the
30 | echo location of your Java installation.
31 |
32 | goto fail
33 |
34 | :findJavaFromJavaHome
35 | set JAVA_HOME=%JAVA_HOME:"=%
36 | set JAVA_EXE=%JAVA_HOME%/bin/java.exe
37 |
38 | if exist "%JAVA_EXE%" goto init
39 |
40 | echo.
41 | echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
42 | echo.
43 | echo Please set the JAVA_HOME variable in your environment to match the
44 | echo location of your Java installation.
45 |
46 | goto fail
47 |
48 | :init
49 | @rem Get command-line arguments, handling Windowz variants
50 |
51 | if not "%OS%" == "Windows_NT" goto win9xME_args
52 | if "%@eval[2+2]" == "4" goto 4NT_args
53 |
54 | :win9xME_args
55 | @rem Slurp the command line arguments.
56 | set CMD_LINE_ARGS=
57 | set _SKIP=2
58 |
59 | :win9xME_args_slurp
60 | if "x%~1" == "x" goto execute
61 |
62 | set CMD_LINE_ARGS=%*
63 | goto execute
64 |
65 | :4NT_args
66 | @rem Get arguments from the 4NT Shell from JP Software
67 | set CMD_LINE_ARGS=%$
68 |
69 | :execute
70 | @rem Setup the command line
71 |
72 | set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
73 |
74 | @rem Execute Gradle
75 | "%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS%
76 |
77 | :end
78 | @rem End local scope for the variables with windows NT shell
79 | if "%ERRORLEVEL%"=="0" goto mainEnd
80 |
81 | :fail
82 | rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
83 | rem the _cmd.exe /c_ return code!
84 | if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1
85 | exit /b 1
86 |
87 | :mainEnd
88 | if "%OS%"=="Windows_NT" endlocal
89 |
90 | :omega
91 |
--------------------------------------------------------------------------------
/javademo/.gitignore:
--------------------------------------------------------------------------------
1 | /build
2 |
--------------------------------------------------------------------------------
/javademo/build.gradle:
--------------------------------------------------------------------------------
1 | apply plugin: 'java'
2 |
3 | dependencies {
4 | compile fileTree(dir: 'libs', include: ['*.jar'])
5 | }
--------------------------------------------------------------------------------
/javademo/src/main/java/com/example/MyClass.java:
--------------------------------------------------------------------------------
1 | package com.example;
2 |
3 | import java.io.IOException;
4 | import java.net.ServerSocket;
5 | import java.net.Socket;
6 |
7 | public class MyClass {
8 | public static void main(String... args) {
9 | String string = "1|-15295269|5.5|FILL|1179.3857:292.67807|@1179.3857:292.67807";
10 | String sep = "|";
11 |
12 | String[] ss = string.split(sep);
13 |
14 | string += "|";
15 | string += "\\|";
16 |
17 | String[] ss1 = string.split("|");
18 | String[] ss2 = string.split("\\\\" + sep);
19 |
20 | System.out.println();
21 |
22 | testSocket();
23 | }
24 |
25 | private static void testSocket() {
26 | ServerSocket serverSocket;
27 | Socket socket;
28 |
29 | while (true) {
30 | try {
31 | serverSocket = new ServerSocket(8776);
32 | socket = serverSocket.accept();
33 | // socket = new Socket();
34 | // socket.connect(new InetSocketAddress("192.168.1.101", 8777));
35 | String data = new String("angcyo");
36 | while (true) {
37 | socket.getOutputStream().write(data.getBytes());
38 | }
39 | } catch (IOException e) {
40 | e.printStackTrace();
41 | }
42 | }
43 | }
44 | }
45 |
--------------------------------------------------------------------------------
/settings.gradle:
--------------------------------------------------------------------------------
1 | include ':app', ':javademo'
2 | include ':sdk_chat_lib'
3 | include ':sdk_chat_demo'
4 |
--------------------------------------------------------------------------------