Skip to content
Projects
Groups
Snippets
Help
This project
Loading...
Sign in / Register
Toggle navigation
A
abook_check
Overview
Overview
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
abook_android
abook_check
Commits
3e307bda
Commit
3e307bda
authored
Feb 15, 2019
by
Lee Jaebin
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
ソース分離
parent
32ec4e3a
Hide whitespace changes
Inline
Side-by-side
Showing
43 changed files
with
137 additions
and
6583 deletions
+137
-6583
ABVJE_BL/src/fi/iki/elonen/NanoHTTPD.java
+0
-2165
ABVJE_BL/src/jp/agentec/abook/abv/bl/common/Constant.java
+0
-4
ABVJE_BL/src/jp/agentec/abook/abv/bl/common/constant/ABookKeys.java
+21
-0
ABVJE_BL/src/jp/agentec/abook/abv/bl/data/DatabaseVersions.java
+1
-1
ABVJE_BL/src/jp/agentec/abook/abv/bl/data/dao/ContentDao.java
+1
-1
ABVJE_BL/src/jp/agentec/abook/abv/bl/data/dao/ProjectContentDao.java
+0
-4
ABVJE_BL/src/jp/agentec/abook/abv/bl/download/ReaderContentDownloader.java
+0
-245
ABVJE_BL/src/jp/agentec/abook/abv/bl/logic/ContractLogic.java
+0
-102
ABVJE_BL/src/jp/agentec/abook/abv/bl/logic/ProjectLogic.java
+1
-55
ABVJE_BL/src/jp/agentec/abook/abv/bl/net/PanoServer.java
+0
-128
ABVJE_BL/src/jp/agentec/abook/abv/bl/repo/RepoClient.java
+0
-27
ABVJE_BL/src/jp/agentec/adf/net/http/SimpleWebServer.java
+0
-307
ABVJE_Launcher_Android/AndroidManifest.xml
+0
-13
ABVJE_Res_Default_Android/build.gradle
+0
-4
ABVJE_UI_Android/build.gradle
+0
-1
ABVJE_UI_Android/src/jp/agentec/abook/abv/cl/beacon/Beacon.java
+0
-20
ABVJE_UI_Android/src/jp/agentec/abook/abv/cl/beacon/BeaconBroadcastReceiver.java
+0
-24
ABVJE_UI_Android/src/jp/agentec/abook/abv/cl/beacon/BeaconIntentService.java
+0
-82
ABVJE_UI_Android/src/jp/agentec/abook/abv/cl/beacon/BeaconPeriodicService.java
+0
-309
ABVJE_UI_Android/src/jp/agentec/abook/abv/launcher/android/ABVUIDataCache.java
+0
-3
ABVJE_UI_Android/src/jp/agentec/abook/abv/launcher/android/OnBootReceiver.java
+0
-2
ABVJE_UI_Android/src/jp/agentec/abook/abv/ui/common/activity/ABVAuthenticatedActivity.java
+1
-24
ABVJE_UI_Android/src/jp/agentec/abook/abv/ui/common/activity/ABVUIActivity.java
+0
-293
ABVJE_UI_Android/src/jp/agentec/abook/abv/ui/home/activity/ABookSettingFragment.java
+0
-7
ABVJE_UI_Android/src/jp/agentec/abook/abv/ui/home/activity/ContentDetailViewActivity.java
+0
-1396
ABVJE_UI_Android/src/jp/agentec/abook/abv/ui/home/activity/GuideViewActivity.java
+0
-1
ABVJE_UI_Android/src/jp/agentec/abook/abv/ui/home/adapter/ContentDetailLinkAdapter.java
+0
-337
ABVJE_UI_Android/src/jp/agentec/abook/abv/ui/home/adapter/ContentDetailListAdapter.java
+0
-94
ABVJE_UI_Android/src/jp/agentec/abook/abv/ui/home/adapter/PushMessageContractListAdapter.java
+0
-91
ABVJE_UI_Android/src/jp/agentec/abook/abv/ui/home/dialog/HtmlViewDialog.java
+0
-51
ABVJE_UI_Android/src/jp/agentec/abook/abv/ui/home/dialog/PushMessageSettingDialog.java
+0
-104
ABVJE_UI_Android/src/jp/agentec/abook/abv/ui/home/dto/ContentLinkAdapterDto.java
+0
-18
ABVJE_UI_Android/src/jp/agentec/abook/abv/ui/home/helper/ActivityHandlingHelper.java
+2
-139
ABVJE_UI_Android/src/jp/agentec/abook/abv/ui/home/helper/PanoViewHelper.java
+0
-244
ABVJE_UI_Android/src/jp/agentec/abook/abv/ui/home/view/BreadCrumbButton.java
+0
-29
ABVJE_UI_Android/src/jp/agentec/abook/abv/ui/home/view/CustomListPreference.java
+0
-41
ABVJE_UI_Android/src/jp/agentec/abook/abv/ui/viewer/activity/ContentViewActivity.java
+3
-121
ABVJE_UI_Android/src/jp/agentec/abook/abv/ui/viewer/activity/HTMLWebViewActivity.java
+4
-9
ABVJE_UI_Android/src/jp/agentec/abook/abv/ui/viewer/activity/HTMLXWalkWebViewActivity.java
+18
-28
ABVJE_UI_Android/src/jp/agentec/abook/abv/ui/viewer/activity/PanoViewActivity.java
+0
-53
ABVJE_UI_Android/src/jp/agentec/abook/abv/ui/viewer/activity/ParentWebViewActivity.java
+84
-0
ABVJE_UI_Android/src/jp/agentec/abook/abv/ui/viewer/adapter/PDFIndexDialog.java
+1
-1
gradle.properties
+0
-5
No files found.
ABVJE_BL/src/fi/iki/elonen/NanoHTTPD.java
deleted
100644 → 0
View file @
32ec4e3a
package
fi
.
iki
.
elonen
;
/*
* #%L
* NanoHttpd-Core
* %%
* Copyright (C) 2012 - 2015 nanohttpd
* %%
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* 3. Neither the name of the nanohttpd nor the names of its contributors
* may be used to endorse or promote products derived from this software without
* specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
* INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
* OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
* OF THE POSSIBILITY OF SUCH DAMAGE.
* #L%
*/
import
java.io.BufferedInputStream
;
import
java.io.BufferedReader
;
import
java.io.BufferedWriter
;
import
java.io.ByteArrayInputStream
;
import
java.io.ByteArrayOutputStream
;
import
java.io.Closeable
;
import
java.io.DataOutput
;
import
java.io.DataOutputStream
;
import
java.io.File
;
import
java.io.FileOutputStream
;
import
java.io.FilterOutputStream
;
import
java.io.IOException
;
import
java.io.InputStream
;
import
java.io.InputStreamReader
;
import
java.io.OutputStream
;
import
java.io.OutputStreamWriter
;
import
java.io.PrintWriter
;
import
java.io.RandomAccessFile
;
import
java.io.UnsupportedEncodingException
;
import
java.net.InetAddress
;
import
java.net.InetSocketAddress
;
import
java.net.ServerSocket
;
import
java.net.Socket
;
import
java.net.SocketException
;
import
java.net.SocketTimeoutException
;
import
java.net.URLDecoder
;
import
java.nio.ByteBuffer
;
import
java.nio.channels.FileChannel
;
import
java.nio.charset.Charset
;
import
java.security.KeyStore
;
import
java.text.SimpleDateFormat
;
import
java.util.ArrayList
;
import
java.util.Calendar
;
import
java.util.Collections
;
import
java.util.Date
;
import
java.util.HashMap
;
import
java.util.Iterator
;
import
java.util.List
;
import
java.util.Locale
;
import
java.util.Map
;
import
java.util.StringTokenizer
;
import
java.util.TimeZone
;
import
java.util.logging.Level
;
import
java.util.logging.Logger
;
import
java.util.regex.Matcher
;
import
java.util.regex.Pattern
;
import
java.util.zip.GZIPOutputStream
;
import
javax.net.ssl.KeyManager
;
import
javax.net.ssl.KeyManagerFactory
;
import
javax.net.ssl.SSLContext
;
import
javax.net.ssl.SSLServerSocket
;
import
javax.net.ssl.SSLServerSocketFactory
;
import
javax.net.ssl.TrustManagerFactory
;
import
fi.iki.elonen.NanoHTTPD.Response.IStatus
;
import
fi.iki.elonen.NanoHTTPD.Response.Status
;
/**
* A simple, tiny, nicely embeddable HTTP server in Java
* <p/>
* <p/>
* NanoHTTPD
* <p>
* Copyright (c) 2012-2013 by Paul S. Hawke, 2001,2005-2013 by Jarno Elonen,
* 2010 by Konstantinos Togias
* </p>
* <p/>
* <p/>
* <b>Features + limitations: </b>
* <ul>
* <p/>
* <li>Only one Java file</li>
* <li>Java 5 compatible</li>
* <li>Released as open source, Modified BSD licence</li>
* <li>No fixed config files, logging, authorization etc. (Implement yourself if
* you need them.)</li>
* <li>Supports parameter parsing of GET and POST methods (+ rudimentary PUT
* support in 1.25)</li>
* <li>Supports both dynamic content and file serving</li>
* <li>Supports file upload (since version 1.2, 2010)</li>
* <li>Supports partial content (streaming)</li>
* <li>Supports ETags</li>
* <li>Never caches anything</li>
* <li>Doesn't limit bandwidth, request time or simultaneous connections</li>
* <li>Default code serves files and shows all HTTP parameters and headers</li>
* <li>File server supports directory listing, index.html and index.htm</li>
* <li>File server supports partial content (streaming)</li>
* <li>File server supports ETags</li>
* <li>File server does the 301 redirection trick for directories without '/'</li>
* <li>File server supports simple skipping for files (continue download)</li>
* <li>File server serves also very long files without memory overhead</li>
* <li>Contains a built-in list of most common MIME types</li>
* <li>All header names are converted to lower case so they don't vary between
* browsers/clients</li>
* <p/>
* </ul>
* <p/>
* <p/>
* <b>How to use: </b>
* <ul>
* <p/>
* <li>Subclass and implement serve() and embed to your own program</li>
* <p/>
* </ul>
* <p/>
* See the separate "LICENSE.md" file for the distribution license (Modified BSD
* licence)
*/
public
abstract
class
NanoHTTPD
{
private
long
lastAccess
;
static
{
loadMimeTypes
();
}
/**
* Pluggable strategy for asynchronously executing requests.
*/
public
interface
AsyncRunner
{
void
closeAll
();
void
closed
(
ClientHandler
clientHandler
);
void
exec
(
ClientHandler
code
);
}
/**
* The runnable that will be used for every new client connection.
*/
public
class
ClientHandler
implements
Runnable
{
private
final
InputStream
inputStream
;
private
final
Socket
acceptSocket
;
private
ClientHandler
(
InputStream
inputStream
,
Socket
acceptSocket
)
{
this
.
inputStream
=
inputStream
;
this
.
acceptSocket
=
acceptSocket
;
}
public
void
close
()
{
safeClose
(
this
.
inputStream
);
safeClose
(
this
.
acceptSocket
);
}
@Override
public
void
run
()
{
OutputStream
outputStream
=
null
;
try
{
outputStream
=
this
.
acceptSocket
.
getOutputStream
();
TempFileManager
tempFileManager
=
NanoHTTPD
.
this
.
tempFileManagerFactory
.
create
();
HTTPSession
session
=
new
HTTPSession
(
tempFileManager
,
this
.
inputStream
,
outputStream
,
this
.
acceptSocket
.
getInetAddress
());
while
(!
this
.
acceptSocket
.
isClosed
())
{
session
.
execute
();
}
}
catch
(
Exception
e
)
{
// When the socket is closed by the client,
// we throw our own SocketException
// to break the "keep alive" loop above. If
// the exception was anything other
// than the expected SocketException OR a
// SocketTimeoutException, print the
// stacktrace
if
(!(
e
instanceof
SocketException
&&
"NanoHttpd Shutdown"
.
equals
(
e
.
getMessage
()))
&&
!(
e
instanceof
SocketTimeoutException
))
{
NanoHTTPD
.
LOG
.
log
(
Level
.
FINE
,
"Communication with the client broken"
,
e
);
}
}
finally
{
safeClose
(
outputStream
);
safeClose
(
this
.
inputStream
);
safeClose
(
this
.
acceptSocket
);
NanoHTTPD
.
this
.
asyncRunner
.
closed
(
this
);
}
}
}
public
static
class
Cookie
{
public
static
String
getHTTPTime
(
int
days
)
{
Calendar
calendar
=
Calendar
.
getInstance
();
SimpleDateFormat
dateFormat
=
new
SimpleDateFormat
(
"EEE, dd MMM yyyy HH:mm:ss z"
,
Locale
.
US
);
dateFormat
.
setTimeZone
(
TimeZone
.
getTimeZone
(
"GMT"
));
calendar
.
add
(
Calendar
.
DAY_OF_MONTH
,
days
);
return
dateFormat
.
format
(
calendar
.
getTime
());
}
private
final
String
n
;
private
final
String
v
;
private
final
String
e
;
public
Cookie
(
String
name
,
String
value
)
{
this
(
name
,
value
,
30
);
}
public
Cookie
(
String
name
,
String
value
,
int
numDays
)
{
this
.
n
=
name
;
this
.
v
=
value
;
this
.
e
=
getHTTPTime
(
numDays
);
}
public
Cookie
(
String
name
,
String
value
,
String
expires
)
{
this
.
n
=
name
;
this
.
v
=
value
;
this
.
e
=
expires
;
}
public
String
getHTTPHeader
()
{
String
fmt
=
"%s=%s; expires=%s"
;
return
String
.
format
(
fmt
,
this
.
n
,
this
.
v
,
this
.
e
);
}
}
/**
* Provides rudimentary support for cookies. Doesn't support 'path',
* 'secure' nor 'httpOnly'. Feel free to improve it and/or add unsupported
* features.
*
* @author LordFokas
*/
public
class
CookieHandler
implements
Iterable
<
String
>
{
private
final
HashMap
<
String
,
String
>
cookies
=
new
HashMap
<
String
,
String
>();
private
final
ArrayList
<
Cookie
>
queue
=
new
ArrayList
<
Cookie
>();
public
CookieHandler
(
Map
<
String
,
String
>
httpHeaders
)
{
String
raw
=
httpHeaders
.
get
(
"cookie"
);
if
(
raw
!=
null
)
{
String
[]
tokens
=
raw
.
split
(
";"
);
for
(
String
token
:
tokens
)
{
String
[]
data
=
token
.
trim
().
split
(
"="
);
if
(
data
.
length
==
2
)
{
this
.
cookies
.
put
(
data
[
0
],
data
[
1
]);
}
}
}
}
/**
* Set a cookie with an expiration date from a month ago, effectively
* deleting it on the client side.
*
* @param name
* The cookie name.
*/
public
void
delete
(
String
name
)
{
set
(
name
,
"-delete-"
,
-
30
);
}
@Override
public
Iterator
<
String
>
iterator
()
{
return
this
.
cookies
.
keySet
().
iterator
();
}
/**
* Read a cookie from the HTTP Headers.
*
* @param name
* The cookie's name.
* @return The cookie's value if it exists, null otherwise.
*/
public
String
read
(
String
name
)
{
return
this
.
cookies
.
get
(
name
);
}
public
void
set
(
Cookie
cookie
)
{
this
.
queue
.
add
(
cookie
);
}
/**
* Sets a cookie.
*
* @param name
* The cookie's name.
* @param value
* The cookie's value.
* @param expires
* How many days until the cookie expires.
*/
public
void
set
(
String
name
,
String
value
,
int
expires
)
{
this
.
queue
.
add
(
new
Cookie
(
name
,
value
,
Cookie
.
getHTTPTime
(
expires
)));
}
/**
* Internally used by the webserver to add all queued cookies into the
* Response's HTTP Headers.
*
* @param response
* The Response object to which headers the queued cookies
* will be added.
*/
public
void
unloadQueue
(
Response
response
)
{
for
(
Cookie
cookie
:
this
.
queue
)
{
response
.
addHeader
(
"Set-Cookie"
,
cookie
.
getHTTPHeader
());
}
}
}
/**
* Default threading strategy for NanoHTTPD.
* <p/>
* <p>
* By default, the server spawns a new Thread for every incoming request.
* These are set to <i>daemon</i> status, and named according to the request
* number. The name is useful when profiling the application.
* </p>
*/
public
static
class
DefaultAsyncRunner
implements
AsyncRunner
{
private
long
requestCount
;
private
final
List
<
ClientHandler
>
running
=
Collections
.
synchronizedList
(
new
ArrayList
<
NanoHTTPD
.
ClientHandler
>());
/**
* @return a list with currently running clients.
*/
public
List
<
ClientHandler
>
getRunning
()
{
return
running
;
}
@Override
public
void
closeAll
()
{
// copy of the list for concurrency
for
(
ClientHandler
clientHandler
:
new
ArrayList
<
ClientHandler
>(
this
.
running
))
{
clientHandler
.
close
();
}
}
@Override
public
void
closed
(
ClientHandler
clientHandler
)
{
this
.
running
.
remove
(
clientHandler
);
}
@Override
public
void
exec
(
ClientHandler
clientHandler
)
{
++
this
.
requestCount
;
Thread
t
=
new
Thread
(
clientHandler
);
t
.
setDaemon
(
true
);
t
.
setName
(
"NanoHttpd Request Processor (#"
+
this
.
requestCount
+
")"
);
this
.
running
.
add
(
clientHandler
);
t
.
start
();
}
}
/**
* Default strategy for creating and cleaning up temporary files.
* <p/>
* <p>
* By default, files are created by <code>File.createTempFile()</code> in
* the directory specified.
* </p>
*/
public
static
class
DefaultTempFile
implements
TempFile
{
private
final
File
file
;
private
final
OutputStream
fstream
;
public
DefaultTempFile
(
File
tempdir
)
throws
IOException
{
this
.
file
=
File
.
createTempFile
(
"NanoHTTPD-"
,
""
,
tempdir
);
this
.
fstream
=
new
FileOutputStream
(
this
.
file
);
}
@Override
public
void
delete
()
throws
Exception
{
safeClose
(
this
.
fstream
);
if
(!
this
.
file
.
delete
())
{
throw
new
Exception
(
"could not delete temporary file"
);
}
}
@Override
public
String
getName
()
{
return
this
.
file
.
getAbsolutePath
();
}
@Override
public
OutputStream
open
()
throws
Exception
{
return
this
.
fstream
;
}
}
/**
* Default strategy for creating and cleaning up temporary files.
* <p/>
* <p>
* This class stores its files in the standard location (that is, wherever
* <code>java.io.tmpdir</code> points to). Files are added to an internal
* list, and deleted when no longer needed (that is, when
* <code>clear()</code> is invoked at the end of processing a request).
* </p>
*/
public
static
class
DefaultTempFileManager
implements
TempFileManager
{
private
final
File
tmpdir
;
private
final
List
<
TempFile
>
tempFiles
;
public
DefaultTempFileManager
()
{
this
.
tmpdir
=
new
File
(
System
.
getProperty
(
"java.io.tmpdir"
));
if
(!
tmpdir
.
exists
())
{
tmpdir
.
mkdirs
();
}
this
.
tempFiles
=
new
ArrayList
<
TempFile
>();
}
@Override
public
void
clear
()
{
for
(
TempFile
file
:
this
.
tempFiles
)
{
try
{
file
.
delete
();
}
catch
(
Exception
ignored
)
{
NanoHTTPD
.
LOG
.
log
(
Level
.
WARNING
,
"could not delete file "
,
ignored
);
}
}
this
.
tempFiles
.
clear
();
}
@Override
public
TempFile
createTempFile
(
String
filename_hint
)
throws
Exception
{
DefaultTempFile
tempFile
=
new
DefaultTempFile
(
this
.
tmpdir
);
this
.
tempFiles
.
add
(
tempFile
);
return
tempFile
;
}
}
/**
* Default strategy for creating and cleaning up temporary files.
*/
private
class
DefaultTempFileManagerFactory
implements
TempFileManagerFactory
{
@Override
public
TempFileManager
create
()
{
return
new
DefaultTempFileManager
();
}
}
private
static
final
String
CHARSET_REGEX
=
"[ |\t]*(charset)[ |\t]*=[ |\t]*['|\"]?([^\"^'^;]*)['|\"]?"
;
private
static
final
Pattern
CHARSET_PATTERN
=
Pattern
.
compile
(
CHARSET_REGEX
,
Pattern
.
CASE_INSENSITIVE
);
private
static
final
String
BOUNDARY_REGEX
=
"[ |\t]*(boundary)[ |\t]*=[ |\t]*['|\"]?([^\"^'^;]*)['|\"]?"
;
private
static
final
Pattern
BOUNDARY_PATTERN
=
Pattern
.
compile
(
BOUNDARY_REGEX
,
Pattern
.
CASE_INSENSITIVE
);
/**
* Creates a normal ServerSocket for TCP connections
*/
public
static
class
DefaultServerSocketFactory
implements
ServerSocketFactory
{
@Override
public
ServerSocket
create
()
throws
IOException
{
return
new
ServerSocket
();
}
}
/**
* Creates a new SSLServerSocket
*/
public
static
class
SecureServerSocketFactory
implements
ServerSocketFactory
{
private
SSLServerSocketFactory
sslServerSocketFactory
;
private
String
[]
sslProtocols
;
public
SecureServerSocketFactory
(
SSLServerSocketFactory
sslServerSocketFactory
,
String
[]
sslProtocols
)
{
this
.
sslServerSocketFactory
=
sslServerSocketFactory
;
this
.
sslProtocols
=
sslProtocols
;
}
@Override
public
ServerSocket
create
()
throws
IOException
{
SSLServerSocket
ss
;
ss
=
(
SSLServerSocket
)
this
.
sslServerSocketFactory
.
createServerSocket
();
if
(
this
.
sslProtocols
!=
null
)
{
ss
.
setEnabledProtocols
(
this
.
sslProtocols
);
}
else
{
ss
.
setEnabledProtocols
(
ss
.
getSupportedProtocols
());
}
ss
.
setUseClientMode
(
false
);
ss
.
setWantClientAuth
(
false
);
ss
.
setNeedClientAuth
(
false
);
return
ss
;
}
}
private
static
final
String
CONTENT_DISPOSITION_REGEX
=
"([ |\t]*Content-Disposition[ |\t]*:)(.*)"
;
private
static
final
Pattern
CONTENT_DISPOSITION_PATTERN
=
Pattern
.
compile
(
CONTENT_DISPOSITION_REGEX
,
Pattern
.
CASE_INSENSITIVE
);
private
static
final
String
CONTENT_TYPE_REGEX
=
"([ |\t]*content-type[ |\t]*:)(.*)"
;
private
static
final
Pattern
CONTENT_TYPE_PATTERN
=
Pattern
.
compile
(
CONTENT_TYPE_REGEX
,
Pattern
.
CASE_INSENSITIVE
);
private
static
final
String
CONTENT_DISPOSITION_ATTRIBUTE_REGEX
=
"[ |\t]*([a-zA-Z]*)[ |\t]*=[ |\t]*['|\"]([^\"^']*)['|\"]"
;
private
static
final
Pattern
CONTENT_DISPOSITION_ATTRIBUTE_PATTERN
=
Pattern
.
compile
(
CONTENT_DISPOSITION_ATTRIBUTE_REGEX
);
protected
class
HTTPSession
implements
IHTTPSession
{
private
static
final
int
REQUEST_BUFFER_LEN
=
512
;
private
static
final
int
MEMORY_STORE_LIMIT
=
1024
;
public
static
final
int
BUFSIZE
=
8192
;
public
static
final
int
MAX_HEADER_SIZE
=
1024
;
private
final
TempFileManager
tempFileManager
;
private
final
OutputStream
outputStream
;
private
final
BufferedInputStream
inputStream
;
private
int
splitbyte
;
private
int
rlen
;
private
String
uri
;
private
Method
method
;
private
Map
<
String
,
String
>
parms
;
private
Map
<
String
,
String
>
headers
;
private
CookieHandler
cookies
;
private
String
queryParameterString
;
private
String
remoteIp
;
private
String
protocolVersion
;
public
HTTPSession
(
TempFileManager
tempFileManager
,
InputStream
inputStream
,
OutputStream
outputStream
)
{
this
.
tempFileManager
=
tempFileManager
;
this
.
inputStream
=
new
BufferedInputStream
(
inputStream
,
HTTPSession
.
BUFSIZE
);
this
.
outputStream
=
outputStream
;
}
public
HTTPSession
(
TempFileManager
tempFileManager
,
InputStream
inputStream
,
OutputStream
outputStream
,
InetAddress
inetAddress
)
{
this
.
tempFileManager
=
tempFileManager
;
this
.
inputStream
=
new
BufferedInputStream
(
inputStream
,
HTTPSession
.
BUFSIZE
);
this
.
outputStream
=
outputStream
;
this
.
remoteIp
=
inetAddress
.
isLoopbackAddress
()
||
inetAddress
.
isAnyLocalAddress
()
?
"127.0.0.1"
:
inetAddress
.
getHostAddress
();
this
.
headers
=
new
HashMap
<
String
,
String
>();
}
/**
* Decodes the sent headers and loads the data into Key/value pairs
*/
private
void
decodeHeader
(
BufferedReader
in
,
Map
<
String
,
String
>
pre
,
Map
<
String
,
String
>
parms
,
Map
<
String
,
String
>
headers
)
throws
ResponseException
{
headers
.
put
(
"range"
,
"bytes=0-"
);
try
{
// Read the request line
String
inLine
=
in
.
readLine
();
if
(
inLine
==
null
)
{
return
;
}
StringTokenizer
st
=
new
StringTokenizer
(
inLine
);
if
(!
st
.
hasMoreTokens
())
{
throw
new
ResponseException
(
Response
.
Status
.
BAD_REQUEST
,
"BAD REQUEST: Syntax error. Usage: GET /example/file.html"
);
}
pre
.
put
(
"method"
,
st
.
nextToken
());
if
(!
st
.
hasMoreTokens
())
{
throw
new
ResponseException
(
Response
.
Status
.
BAD_REQUEST
,
"BAD REQUEST: Missing URI. Usage: GET /example/file.html"
);
}
String
uri
=
st
.
nextToken
();
// Decode parameters from the URI
int
qmi
=
uri
.
indexOf
(
'?'
);
if
(
qmi
>=
0
)
{
decodeParms
(
uri
.
substring
(
qmi
+
1
),
parms
);
uri
=
decodePercent
(
uri
.
substring
(
0
,
qmi
));
}
else
{
uri
=
decodePercent
(
uri
);
}
// If there's another token, its protocol version,
// followed by HTTP headers.
// NOTE: this now forces header names lower case since they are
// case insensitive and vary by client.
if
(
st
.
hasMoreTokens
())
{
protocolVersion
=
st
.
nextToken
();
}
else
{
protocolVersion
=
"HTTP/1.1"
;
NanoHTTPD
.
LOG
.
log
(
Level
.
FINE
,
"no protocol version specified, strange. Assuming HTTP/1.1."
);
}
String
line
=
in
.
readLine
();
while
(
line
!=
null
&&
line
.
trim
().
length
()
>
0
)
{
int
p
=
line
.
indexOf
(
':'
);
if
(
p
>=
0
)
{
headers
.
put
(
line
.
substring
(
0
,
p
).
trim
().
toLowerCase
(
Locale
.
US
),
line
.
substring
(
p
+
1
).
trim
());
}
line
=
in
.
readLine
();
}
pre
.
put
(
"uri"
,
uri
);
}
catch
(
IOException
ioe
)
{
throw
new
ResponseException
(
Response
.
Status
.
INTERNAL_ERROR
,
"SERVER INTERNAL ERROR: IOException: "
+
ioe
.
getMessage
(),
ioe
);
}
}
/**
* Decodes the Multipart Body data and put it into Key/Value pairs.
*/
private
void
decodeMultipartFormData
(
String
boundary
,
String
encoding
,
ByteBuffer
fbuf
,
Map
<
String
,
String
>
parms
,
Map
<
String
,
String
>
files
)
throws
ResponseException
{
try
{
int
[]
boundary_idxs
=
getBoundaryPositions
(
fbuf
,
boundary
.
getBytes
());
if
(
boundary_idxs
.
length
<
2
)
{
throw
new
ResponseException
(
Response
.
Status
.
BAD_REQUEST
,
"BAD REQUEST: Content type is multipart/form-data but contains less than two boundary strings."
);
}
byte
[]
part_header_buff
=
new
byte
[
MAX_HEADER_SIZE
];
for
(
int
bi
=
0
;
bi
<
boundary_idxs
.
length
-
1
;
bi
++)
{
fbuf
.
position
(
boundary_idxs
[
bi
]);
int
len
=
(
fbuf
.
remaining
()
<
MAX_HEADER_SIZE
)
?
fbuf
.
remaining
()
:
MAX_HEADER_SIZE
;
fbuf
.
get
(
part_header_buff
,
0
,
len
);
BufferedReader
in
=
new
BufferedReader
(
new
InputStreamReader
(
new
ByteArrayInputStream
(
part_header_buff
,
0
,
len
),
Charset
.
forName
(
encoding
)),
len
);
int
headerLines
=
0
;
// First line is boundary string
String
mpline
=
in
.
readLine
();
headerLines
++;
if
(
mpline
==
null
||
!
mpline
.
contains
(
boundary
))
{
throw
new
ResponseException
(
Response
.
Status
.
BAD_REQUEST
,
"BAD REQUEST: Content type is multipart/form-data but chunk does not start with boundary."
);
}
String
part_name
=
null
;
String
file_name
=
null
;
String
content_type
=
null
;
// Parse the reset of the header lines
mpline
=
in
.
readLine
();
headerLines
++;
while
(
mpline
!=
null
&&
mpline
.
trim
().
length
()
>
0
)
{
Matcher
matcher
=
CONTENT_DISPOSITION_PATTERN
.
matcher
(
mpline
);
if
(
matcher
.
matches
())
{
String
attributeString
=
matcher
.
group
(
2
);
matcher
=
CONTENT_DISPOSITION_ATTRIBUTE_PATTERN
.
matcher
(
attributeString
);
while
(
matcher
.
find
())
{
String
key
=
matcher
.
group
(
1
);
if
(
"name"
.
equalsIgnoreCase
(
key
))
{
part_name
=
matcher
.
group
(
2
);
}
else
if
(
"filename"
.
equalsIgnoreCase
(
key
))
{
file_name
=
matcher
.
group
(
2
);
}
}
}
matcher
=
CONTENT_TYPE_PATTERN
.
matcher
(
mpline
);
if
(
matcher
.
matches
())
{
content_type
=
matcher
.
group
(
2
).
trim
();
}
mpline
=
in
.
readLine
();
headerLines
++;
}
int
part_header_len
=
0
;
while
(
headerLines
--
>
0
)
{
part_header_len
=
scipOverNewLine
(
part_header_buff
,
part_header_len
);
}
// Read the part data
if
(
part_header_len
>=
len
-
4
)
{
throw
new
ResponseException
(
Response
.
Status
.
INTERNAL_ERROR
,
"Multipart header size exceeds MAX_HEADER_SIZE."
);
}
int
part_data_start
=
boundary_idxs
[
bi
]
+
part_header_len
;
int
part_data_end
=
boundary_idxs
[
bi
+
1
]
-
4
;
fbuf
.
position
(
part_data_start
);
if
(
content_type
==
null
)
{
// Read the part into a string
byte
[]
data_bytes
=
new
byte
[
part_data_end
-
part_data_start
];
fbuf
.
get
(
data_bytes
);
parms
.
put
(
part_name
,
new
String
(
data_bytes
,
encoding
));
}
else
{
// Read it into a file
String
path
=
saveTmpFile
(
fbuf
,
part_data_start
,
part_data_end
-
part_data_start
,
file_name
);
if
(
files
.
containsKey
(
part_name
))
{
int
count
=
2
;
while
(
files
.
containsKey
(
part_name
+
count
))
{
count
++;
}
files
.
put
(
part_name
+
count
,
path
);
}
else
{
files
.
put
(
part_name
,
path
);
}
parms
.
put
(
part_name
,
file_name
);
}
}
}
catch
(
ResponseException
re
)
{
throw
re
;
}
catch
(
Exception
e
)
{
throw
new
ResponseException
(
Response
.
Status
.
INTERNAL_ERROR
,
e
.
toString
());
}
}
private
int
scipOverNewLine
(
byte
[]
part_header_buff
,
int
index
)
{
while
(
part_header_buff
[
index
]
!=
'\n'
)
{
index
++;
}
return
++
index
;
}
/**
* Decodes parameters in percent-encoded URI-format ( e.g.
* "name=Jack%20Daniels&pass=Single%20Malt" ) and adds them to given
* Map. NOTE: this doesn't support multiple identical keys due to the
* simplicity of Map.
*/
private
void
decodeParms
(
String
parms
,
Map
<
String
,
String
>
p
)
{
if
(
parms
==
null
)
{
this
.
queryParameterString
=
""
;
return
;
}
this
.
queryParameterString
=
parms
;
StringTokenizer
st
=
new
StringTokenizer
(
parms
,
"&"
);
while
(
st
.
hasMoreTokens
())
{
String
e
=
st
.
nextToken
();
int
sep
=
e
.
indexOf
(
'='
);
if
(
sep
>=
0
)
{
p
.
put
(
decodePercent
(
e
.
substring
(
0
,
sep
)).
trim
(),
decodePercent
(
e
.
substring
(
sep
+
1
)));
}
else
{
p
.
put
(
decodePercent
(
e
).
trim
(),
""
);
}
}
}
@Override
public
void
execute
()
throws
IOException
{
Response
r
=
null
;
try
{
// Read the first 8192 bytes.
// The full header should fit in here.
// Apache's default header limit is 8KB.
// Do NOT assume that a single read will get the entire header
// at once!
byte
[]
buf
=
new
byte
[
HTTPSession
.
BUFSIZE
];
this
.
splitbyte
=
0
;
this
.
rlen
=
0
;
int
read
;
this
.
inputStream
.
mark
(
HTTPSession
.
BUFSIZE
);
try
{
read
=
this
.
inputStream
.
read
(
buf
,
0
,
HTTPSession
.
BUFSIZE
);
}
catch
(
Exception
e
)
{
safeClose
(
this
.
inputStream
);
safeClose
(
this
.
outputStream
);
throw
new
SocketException
(
"NanoHttpd Shutdown"
);
}
if
(
read
==
-
1
)
{
// socket was been closed
safeClose
(
this
.
inputStream
);
safeClose
(
this
.
outputStream
);
throw
new
SocketException
(
"NanoHttpd Shutdown"
);
}
while
(
read
>
0
)
{
this
.
rlen
+=
read
;
this
.
splitbyte
=
findHeaderEnd
(
buf
,
this
.
rlen
);
if
(
this
.
splitbyte
>
0
)
{
break
;
}
read
=
this
.
inputStream
.
read
(
buf
,
this
.
rlen
,
HTTPSession
.
BUFSIZE
-
this
.
rlen
);
}
if
(
this
.
splitbyte
<
this
.
rlen
)
{
this
.
inputStream
.
reset
();
this
.
inputStream
.
skip
(
this
.
splitbyte
);
}
this
.
parms
=
new
HashMap
<
String
,
String
>();
if
(
null
==
this
.
headers
)
{
this
.
headers
=
new
HashMap
<
String
,
String
>();
}
else
{
this
.
headers
.
clear
();
}
// Create a BufferedReader for parsing the header.
BufferedReader
hin
=
new
BufferedReader
(
new
InputStreamReader
(
new
ByteArrayInputStream
(
buf
,
0
,
this
.
rlen
)));
// Decode the header into parms and header java properties
Map
<
String
,
String
>
pre
=
new
HashMap
<
String
,
String
>();
decodeHeader
(
hin
,
pre
,
this
.
parms
,
this
.
headers
);
if
(
null
!=
this
.
remoteIp
)
{
this
.
headers
.
put
(
"remote-addr"
,
this
.
remoteIp
);
this
.
headers
.
put
(
"http-client-ip"
,
this
.
remoteIp
);
}
this
.
method
=
Method
.
lookup
(
pre
.
get
(
"method"
));
if
(
this
.
method
==
null
)
{
throw
new
ResponseException
(
Response
.
Status
.
BAD_REQUEST
,
"BAD REQUEST: Syntax error."
);
}
this
.
uri
=
pre
.
get
(
"uri"
);
this
.
cookies
=
new
CookieHandler
(
this
.
headers
);
String
connection
=
this
.
headers
.
get
(
"connection"
);
boolean
keepAlive
=
"HTTP/1.1"
.
equals
(
protocolVersion
)
&&
(
connection
==
null
||
!
connection
.
matches
(
"(?i).*close.*"
));
// Ok, now do the serve()
// TODO: long body_size = getBodySize();
// TODO: long pos_before_serve = this.inputStream.totalRead()
// (requires implementaion for totalRead())
r
=
serve
(
this
);
// TODO: this.inputStream.skip(body_size -
// (this.inputStream.totalRead() - pos_before_serve))
if
(
r
==
null
)
{
throw
new
ResponseException
(
Response
.
Status
.
INTERNAL_ERROR
,
"SERVER INTERNAL ERROR: Serve() returned a null response."
);
}
else
{
String
acceptEncoding
=
this
.
headers
.
get
(
"accept-encoding"
);
this
.
cookies
.
unloadQueue
(
r
);
r
.
setRequestMethod
(
this
.
method
);
r
.
setGzipEncoding
(
useGzipWhenAccepted
(
r
)
&&
acceptEncoding
!=
null
&&
acceptEncoding
.
contains
(
"gzip"
));
r
.
setKeepAlive
(
keepAlive
);
r
.
send
(
this
.
outputStream
);
}
if
(!
keepAlive
||
"close"
.
equalsIgnoreCase
(
r
.
getHeader
(
"connection"
)))
{
throw
new
SocketException
(
"NanoHttpd Shutdown"
);
}
}
catch
(
SocketException
e
)
{
// throw it out to close socket object (finalAccept)
throw
e
;
}
catch
(
SocketTimeoutException
ste
)
{
// treat socket timeouts the same way we treat socket exceptions
// i.e. close the stream & finalAccept object by throwing the
// exception up the call stack.
throw
ste
;
}
catch
(
IOException
ioe
)
{
Response
resp
=
newFixedLengthResponse
(
Response
.
Status
.
INTERNAL_ERROR
,
NanoHTTPD
.
MIME_PLAINTEXT
,
"SERVER INTERNAL ERROR: IOException: "
+
ioe
.
getMessage
());
resp
.
send
(
this
.
outputStream
);
safeClose
(
this
.
outputStream
);
}
catch
(
ResponseException
re
)
{
Response
resp
=
newFixedLengthResponse
(
re
.
getStatus
(),
NanoHTTPD
.
MIME_PLAINTEXT
,
re
.
getMessage
());
resp
.
send
(
this
.
outputStream
);
safeClose
(
this
.
outputStream
);
}
finally
{
safeClose
(
r
);
this
.
tempFileManager
.
clear
();
}
}
/**
* Find byte index separating header from body. It must be the last byte
* of the first two sequential new lines.
*/
private
int
findHeaderEnd
(
final
byte
[]
buf
,
int
rlen
)
{
int
splitbyte
=
0
;
while
(
splitbyte
+
1
<
rlen
)
{
// RFC2616
if
(
buf
[
splitbyte
]
==
'\r'
&&
buf
[
splitbyte
+
1
]
==
'\n'
&&
splitbyte
+
3
<
rlen
&&
buf
[
splitbyte
+
2
]
==
'\r'
&&
buf
[
splitbyte
+
3
]
==
'\n'
)
{
return
splitbyte
+
4
;
}
// tolerance
if
(
buf
[
splitbyte
]
==
'\n'
&&
buf
[
splitbyte
+
1
]
==
'\n'
)
{
return
splitbyte
+
2
;
}
splitbyte
++;
}
return
0
;
}
/**
* Find the byte positions where multipart boundaries start. This reads
* a large block at a time and uses a temporary buffer to optimize
* (memory mapped) file access.
*/
private
int
[]
getBoundaryPositions
(
ByteBuffer
b
,
byte
[]
boundary
)
{
int
[]
res
=
new
int
[
0
];
if
(
b
.
remaining
()
<
boundary
.
length
)
{
return
res
;
}
int
search_window_pos
=
0
;
byte
[]
search_window
=
new
byte
[
4
*
1024
+
boundary
.
length
];
int
first_fill
=
(
b
.
remaining
()
<
search_window
.
length
)
?
b
.
remaining
()
:
search_window
.
length
;
b
.
get
(
search_window
,
0
,
first_fill
);
int
new_bytes
=
first_fill
-
boundary
.
length
;
do
{
// Search the search_window
for
(
int
j
=
0
;
j
<
new_bytes
;
j
++)
{
for
(
int
i
=
0
;
i
<
boundary
.
length
;
i
++)
{
if
(
search_window
[
j
+
i
]
!=
boundary
[
i
])
{
break
;
}
if
(
i
==
boundary
.
length
-
1
)
{
// Match found, add it to results
int
[]
new_res
=
new
int
[
res
.
length
+
1
];
System
.
arraycopy
(
res
,
0
,
new_res
,
0
,
res
.
length
);
new_res
[
res
.
length
]
=
search_window_pos
+
j
;
res
=
new_res
;
}
}
}
search_window_pos
+=
new_bytes
;
// Copy the end of the buffer to the start
System
.
arraycopy
(
search_window
,
search_window
.
length
-
boundary
.
length
,
search_window
,
0
,
boundary
.
length
);
// Refill search_window
new_bytes
=
search_window
.
length
-
boundary
.
length
;
new_bytes
=
(
b
.
remaining
()
<
new_bytes
)
?
b
.
remaining
()
:
new_bytes
;
b
.
get
(
search_window
,
boundary
.
length
,
new_bytes
);
}
while
(
new_bytes
>
0
);
return
res
;
}
@Override
public
CookieHandler
getCookies
()
{
return
this
.
cookies
;
}
@Override
public
final
Map
<
String
,
String
>
getHeaders
()
{
return
this
.
headers
;
}
@Override
public
final
InputStream
getInputStream
()
{
return
this
.
inputStream
;
}
@Override
public
final
Method
getMethod
()
{
return
this
.
method
;
}
@Override
public
final
Map
<
String
,
String
>
getParms
()
{
return
this
.
parms
;
}
@Override
public
String
getQueryParameterString
()
{
return
this
.
queryParameterString
;
}
private
RandomAccessFile
getTmpBucket
()
{
try
{
TempFile
tempFile
=
this
.
tempFileManager
.
createTempFile
(
null
);
return
new
RandomAccessFile
(
tempFile
.
getName
(),
"rw"
);
}
catch
(
Exception
e
)
{
throw
new
Error
(
e
);
// we won't recover, so throw an error
}
}
@Override
public
final
String
getUri
()
{
return
this
.
uri
;
}
/**
* Deduce body length in bytes. Either from "content-length" header or
* read bytes.
*/
public
long
getBodySize
()
{
if
(
this
.
headers
.
containsKey
(
"content-length"
))
{
return
Long
.
parseLong
(
this
.
headers
.
get
(
"content-length"
));
}
else
if
(
this
.
splitbyte
<
this
.
rlen
)
{
return
this
.
rlen
-
this
.
splitbyte
;
}
return
0
;
}
@Override
public
void
parseBody
(
Map
<
String
,
String
>
files
)
throws
IOException
,
ResponseException
{
RandomAccessFile
randomAccessFile
=
null
;
try
{
long
size
=
getBodySize
();
ByteArrayOutputStream
baos
=
null
;
DataOutput
request_data_output
;
// Store the request in memory or a file, depending on size
if
(
size
<
MEMORY_STORE_LIMIT
)
{
baos
=
new
ByteArrayOutputStream
();
request_data_output
=
new
DataOutputStream
(
baos
);
}
else
{
randomAccessFile
=
getTmpBucket
();
request_data_output
=
randomAccessFile
;
}
// Read all the body and write it to request_data_output
byte
[]
buf
=
new
byte
[
REQUEST_BUFFER_LEN
];
while
(
this
.
rlen
>=
0
&&
size
>
0
)
{
this
.
rlen
=
this
.
inputStream
.
read
(
buf
,
0
,
(
int
)
Math
.
min
(
size
,
REQUEST_BUFFER_LEN
));
size
-=
this
.
rlen
;
if
(
this
.
rlen
>
0
)
{
request_data_output
.
write
(
buf
,
0
,
this
.
rlen
);
}
}
ByteBuffer
fbuf
;
if
(
baos
!=
null
)
{
fbuf
=
ByteBuffer
.
wrap
(
baos
.
toByteArray
(),
0
,
baos
.
size
());
}
else
{
fbuf
=
randomAccessFile
.
getChannel
().
map
(
FileChannel
.
MapMode
.
READ_ONLY
,
0
,
randomAccessFile
.
length
());
randomAccessFile
.
seek
(
0
);
}
// If the method is POST, there may be parameters
// in data section, too, read it:
if
(
Method
.
POST
.
equals
(
this
.
method
))
{
String
contentType
=
""
;
String
contentTypeHeader
=
this
.
headers
.
get
(
"content-type"
);
StringTokenizer
st
=
null
;
if
(
contentTypeHeader
!=
null
)
{
st
=
new
StringTokenizer
(
contentTypeHeader
,
",; "
);
if
(
st
.
hasMoreTokens
())
{
contentType
=
st
.
nextToken
();
}
}
if
(
"multipart/form-data"
.
equalsIgnoreCase
(
contentType
))
{
// Handle multipart/form-data
if
(!
st
.
hasMoreTokens
())
{
throw
new
ResponseException
(
Response
.
Status
.
BAD_REQUEST
,
"BAD REQUEST: Content type is multipart/form-data but boundary missing. Usage: GET /example/file.html"
);
}
decodeMultipartFormData
(
getAttributeFromContentHeader
(
contentTypeHeader
,
BOUNDARY_PATTERN
,
null
),
//
getAttributeFromContentHeader
(
contentTypeHeader
,
CHARSET_PATTERN
,
"US-ASCII"
),
fbuf
,
this
.
parms
,
files
);
}
else
{
byte
[]
postBytes
=
new
byte
[
fbuf
.
remaining
()];
fbuf
.
get
(
postBytes
);
String
postLine
=
new
String
(
postBytes
).
trim
();
// Handle application/x-www-form-urlencoded
if
(
"application/x-www-form-urlencoded"
.
equalsIgnoreCase
(
contentType
))
{
decodeParms
(
postLine
,
this
.
parms
);
}
else
if
(
postLine
.
length
()
!=
0
)
{
// Special case for raw POST data => create a
// special files entry "postData" with raw content
// data
files
.
put
(
"postData"
,
postLine
);
}
}
}
else
if
(
Method
.
PUT
.
equals
(
this
.
method
))
{
files
.
put
(
"content"
,
saveTmpFile
(
fbuf
,
0
,
fbuf
.
limit
(),
null
));
}
}
finally
{
safeClose
(
randomAccessFile
);
}
}
private
String
getAttributeFromContentHeader
(
String
contentTypeHeader
,
Pattern
pattern
,
String
defaultValue
)
{
Matcher
matcher
=
pattern
.
matcher
(
contentTypeHeader
);
return
matcher
.
find
()
?
matcher
.
group
(
2
)
:
defaultValue
;
}
/**
* Retrieves the content of a sent file and saves it to a temporary
* file. The full path to the saved file is returned.
*/
private
String
saveTmpFile
(
ByteBuffer
b
,
int
offset
,
int
len
,
String
filename_hint
)
{
String
path
=
""
;
if
(
len
>
0
)
{
FileOutputStream
fileOutputStream
=
null
;
try
{
TempFile
tempFile
=
this
.
tempFileManager
.
createTempFile
(
filename_hint
);
ByteBuffer
src
=
b
.
duplicate
();
fileOutputStream
=
new
FileOutputStream
(
tempFile
.
getName
());
FileChannel
dest
=
fileOutputStream
.
getChannel
();
src
.
position
(
offset
).
limit
(
offset
+
len
);
dest
.
write
(
src
.
slice
());
path
=
tempFile
.
getName
();
}
catch
(
Exception
e
)
{
// Catch exception if any
throw
new
Error
(
e
);
// we won't recover, so throw an error
}
finally
{
safeClose
(
fileOutputStream
);
}
}
return
path
;
}
}
/**
* Handles one session, i.e. parses the HTTP request and returns the
* response.
*/
public
interface
IHTTPSession
{
void
execute
()
throws
IOException
;
CookieHandler
getCookies
();
Map
<
String
,
String
>
getHeaders
();
InputStream
getInputStream
();
Method
getMethod
();
Map
<
String
,
String
>
getParms
();
String
getQueryParameterString
();
/**
* @return the path part of the URL.
*/
String
getUri
();
/**
* Adds the files in the request body to the files map.
*
* @param files
* map to modify
*/
void
parseBody
(
Map
<
String
,
String
>
files
)
throws
IOException
,
ResponseException
;
}
/**
* HTTP Request methods, with the ability to decode a <code>String</code>
* back to its enum value.
*/
public
enum
Method
{
GET
,
PUT
,
POST
,
DELETE
,
HEAD
,
OPTIONS
,
TRACE
,
CONNECT
,
PATCH
;
static
Method
lookup
(
String
method
)
{
for
(
Method
m
:
Method
.
values
())
{
if
(
m
.
toString
().
equalsIgnoreCase
(
method
))
{
return
m
;
}
}
return
null
;
}
}
/**
* HTTP response. Return one of these from serve().
*/
public
static
class
Response
implements
Closeable
{
public
interface
IStatus
{
String
getDescription
();
int
getRequestStatus
();
}
/**
* Some HTTP response status codes
*/
public
enum
Status
implements
IStatus
{
SWITCH_PROTOCOL
(
101
,
"Switching Protocols"
),
OK
(
200
,
"OK"
),
CREATED
(
201
,
"Created"
),
ACCEPTED
(
202
,
"Accepted"
),
NO_CONTENT
(
204
,
"No Content"
),
PARTIAL_CONTENT
(
206
,
"Partial Content"
),
REDIRECT
(
301
,
"Moved Permanently"
),
NOT_MODIFIED
(
304
,
"Not Modified"
),
BAD_REQUEST
(
400
,
"Bad Request"
),
UNAUTHORIZED
(
401
,
"Unauthorized"
),
FORBIDDEN
(
403
,
"Forbidden"
),
NOT_FOUND
(
404
,
"Not Found"
),
METHOD_NOT_ALLOWED
(
405
,
"Method Not Allowed"
),
NOT_ACCEPTABLE
(
406
,
"Not Acceptable"
),
REQUEST_TIMEOUT
(
408
,
"Request Timeout"
),
CONFLICT
(
409
,
"Conflict"
),
RANGE_NOT_SATISFIABLE
(
416
,
"Requested Range Not Satisfiable"
),
INTERNAL_ERROR
(
500
,
"Internal Server Error"
),
NOT_IMPLEMENTED
(
501
,
"Not Implemented"
),
UNSUPPORTED_HTTP_VERSION
(
505
,
"HTTP Version Not Supported"
);
private
final
int
requestStatus
;
private
final
String
description
;
Status
(
int
requestStatus
,
String
description
)
{
this
.
requestStatus
=
requestStatus
;
this
.
description
=
description
;
}
@Override
public
String
getDescription
()
{
return
""
+
this
.
requestStatus
+
" "
+
this
.
description
;
}
@Override
public
int
getRequestStatus
()
{
return
this
.
requestStatus
;
}
}
/**
* Output stream that will automatically send every write to the wrapped
* OutputStream according to chunked transfer:
* http://www.w3.org/Protocols/rfc2616/rfc2616-sec3.html#sec3.6.1
*/
private
static
class
ChunkedOutputStream
extends
FilterOutputStream
{
public
ChunkedOutputStream
(
OutputStream
out
)
{
super
(
out
);
}
@Override
public
void
write
(
int
b
)
throws
IOException
{
byte
[]
data
=
{
(
byte
)
b
};
write
(
data
,
0
,
1
);
}
@Override
public
void
write
(
byte
[]
b
)
throws
IOException
{
write
(
b
,
0
,
b
.
length
);
}
@Override
public
void
write
(
byte
[]
b
,
int
off
,
int
len
)
throws
IOException
{
if
(
len
==
0
)
{
return
;
}
out
.
write
(
String
.
format
(
"%x\r\n"
,
len
).
getBytes
());
out
.
write
(
b
,
off
,
len
);
out
.
write
(
"\r\n"
.
getBytes
());
}
public
void
finish
()
throws
IOException
{
out
.
write
(
"0\r\n\r\n"
.
getBytes
());
}
}
/**
* HTTP status code after processing, e.g. "200 OK", Status.OK
*/
private
IStatus
status
;
/**
* MIME type of content, e.g. "text/html"
*/
private
String
mimeType
;
/**
* Data of the response, may be null.
*/
private
InputStream
data
;
private
long
contentLength
;
/**
* Headers for the HTTP response. Use addHeader() to add lines.
*/
private
final
Map
<
String
,
String
>
header
=
new
HashMap
<
String
,
String
>();
/**
* The request method that spawned this response.
*/
private
Method
requestMethod
;
/**
* Use chunkedTransfer
*/
private
boolean
chunkedTransfer
;
private
boolean
encodeAsGzip
;
private
boolean
keepAlive
;
/**
* Creates a fixed length response if totalBytes>=0, otherwise chunked.
*/
protected
Response
(
IStatus
status
,
String
mimeType
,
InputStream
data
,
long
totalBytes
)
{
this
.
status
=
status
;
this
.
mimeType
=
mimeType
;
if
(
data
==
null
)
{
this
.
data
=
new
ByteArrayInputStream
(
new
byte
[
0
]);
this
.
contentLength
=
0L
;
}
else
{
this
.
data
=
data
;
this
.
contentLength
=
totalBytes
;
}
this
.
chunkedTransfer
=
this
.
contentLength
<
0
;
keepAlive
=
true
;
}
@Override
public
void
close
()
throws
IOException
{
if
(
this
.
data
!=
null
)
{
this
.
data
.
close
();
}
}
/**
* Adds given line to the header.
*/
public
void
addHeader
(
String
name
,
String
value
)
{
this
.
header
.
put
(
name
,
value
);
}
public
InputStream
getData
()
{
return
this
.
data
;
}
public
String
getHeader
(
String
name
)
{
for
(
String
headerName
:
header
.
keySet
())
{
if
(
headerName
.
equalsIgnoreCase
(
name
))
{
return
header
.
get
(
headerName
);
}
}
return
null
;
}
public
String
getMimeType
()
{
return
this
.
mimeType
;
}
public
Method
getRequestMethod
()
{
return
this
.
requestMethod
;
}
public
IStatus
getStatus
()
{
return
this
.
status
;
}
public
void
setGzipEncoding
(
boolean
encodeAsGzip
)
{
this
.
encodeAsGzip
=
encodeAsGzip
;
}
public
void
setKeepAlive
(
boolean
useKeepAlive
)
{
this
.
keepAlive
=
useKeepAlive
;
}
private
static
boolean
headerAlreadySent
(
Map
<
String
,
String
>
header
,
String
name
)
{
boolean
alreadySent
=
false
;
for
(
String
headerName
:
header
.
keySet
())
{
alreadySent
|=
headerName
.
equalsIgnoreCase
(
name
);
}
return
alreadySent
;
}
/**
* Sends given response to the socket.
*/
protected
void
send
(
OutputStream
outputStream
)
{
String
mime
=
this
.
mimeType
;
SimpleDateFormat
gmtFrmt
=
new
SimpleDateFormat
(
"E, d MMM yyyy HH:mm:ss 'GMT'"
,
Locale
.
US
);
gmtFrmt
.
setTimeZone
(
TimeZone
.
getTimeZone
(
"GMT"
));
try
{
if
(
this
.
status
==
null
)
{
throw
new
Error
(
"sendResponse(): Status can't be null."
);
}
PrintWriter
pw
=
new
PrintWriter
(
new
BufferedWriter
(
new
OutputStreamWriter
(
outputStream
,
"UTF-8"
)),
false
);
pw
.
print
(
"HTTP/1.1 "
+
this
.
status
.
getDescription
()
+
" \r\n"
);
if
(
mime
!=
null
)
{
pw
.
print
(
"Content-Type: "
+
mime
+
"\r\n"
);
}
if
(
this
.
header
==
null
||
this
.
header
.
get
(
"Date"
)
==
null
)
{
pw
.
print
(
"Date: "
+
gmtFrmt
.
format
(
new
Date
())
+
"\r\n"
);
}
if
(
this
.
header
!=
null
)
{
for
(
String
key
:
this
.
header
.
keySet
())
{
String
value
=
this
.
header
.
get
(
key
);
pw
.
print
(
key
+
": "
+
value
+
"\r\n"
);
}
}
if
(!
headerAlreadySent
(
header
,
"connection"
))
{
pw
.
print
(
"Connection: "
+
(
this
.
keepAlive
?
"keep-alive"
:
"close"
)
+
"\r\n"
);
}
if
(
headerAlreadySent
(
this
.
header
,
"content-length"
))
{
encodeAsGzip
=
false
;
}
if
(
encodeAsGzip
)
{
pw
.
print
(
"Content-Encoding: gzip\r\n"
);
setChunkedTransfer
(
true
);
}
long
pending
=
this
.
data
!=
null
?
this
.
contentLength
:
0
;
if
(
this
.
requestMethod
!=
Method
.
HEAD
&&
this
.
chunkedTransfer
)
{
pw
.
print
(
"Transfer-Encoding: chunked\r\n"
);
}
else
if
(!
encodeAsGzip
)
{
pending
=
sendContentLengthHeaderIfNotAlreadyPresent
(
pw
,
this
.
header
,
pending
);
}
pw
.
print
(
"\r\n"
);
pw
.
flush
();
sendBodyWithCorrectTransferAndEncoding
(
outputStream
,
pending
);
outputStream
.
flush
();
safeClose
(
this
.
data
);
}
catch
(
SocketException
se
)
{
NanoHTTPD
.
LOG
.
log
(
Level
.
WARNING
,
"SocketException"
,
se
.
getLocalizedMessage
());
}
catch
(
IOException
ioe
)
{
NanoHTTPD
.
LOG
.
log
(
Level
.
SEVERE
,
"Could not send response to the client"
,
ioe
);
}
}
private
void
sendBodyWithCorrectTransferAndEncoding
(
OutputStream
outputStream
,
long
pending
)
throws
IOException
{
if
(
this
.
requestMethod
!=
Method
.
HEAD
&&
this
.
chunkedTransfer
)
{
ChunkedOutputStream
chunkedOutputStream
=
new
ChunkedOutputStream
(
outputStream
);
sendBodyWithCorrectEncoding
(
chunkedOutputStream
,
-
1
);
chunkedOutputStream
.
finish
();
}
else
{
sendBodyWithCorrectEncoding
(
outputStream
,
pending
);
}
}
private
void
sendBodyWithCorrectEncoding
(
OutputStream
outputStream
,
long
pending
)
throws
IOException
{
if
(
encodeAsGzip
)
{
GZIPOutputStream
gzipOutputStream
=
new
GZIPOutputStream
(
outputStream
);
sendBody
(
gzipOutputStream
,
-
1
);
gzipOutputStream
.
finish
();
}
else
{
sendBody
(
outputStream
,
pending
);
}
}
/**
* Sends the body to the specified OutputStream. The pending parameter
* limits the maximum amounts of bytes sent unless it is -1, in which
* case everything is sent.
*
* @param outputStream
* the OutputStream to send data to
* @param pending
* -1 to send everything, otherwise sets a max limit to the
* number of bytes sent
* @throws IOException
* if something goes wrong while sending the data.
*/
private
void
sendBody
(
OutputStream
outputStream
,
long
pending
)
throws
IOException
{
long
BUFFER_SIZE
=
16
*
1024
;
byte
[]
buff
=
new
byte
[(
int
)
BUFFER_SIZE
];
boolean
sendEverything
=
pending
==
-
1
;
while
(
pending
>
0
||
sendEverything
)
{
long
bytesToRead
=
sendEverything
?
BUFFER_SIZE
:
Math
.
min
(
pending
,
BUFFER_SIZE
);
int
read
=
this
.
data
.
read
(
buff
,
0
,
(
int
)
bytesToRead
);
if
(
read
<=
0
)
{
break
;
}
outputStream
.
write
(
buff
,
0
,
read
);
if
(!
sendEverything
)
{
pending
-=
read
;
}
}
}
protected
static
long
sendContentLengthHeaderIfNotAlreadyPresent
(
PrintWriter
pw
,
Map
<
String
,
String
>
header
,
long
size
)
{
for
(
String
headerName
:
header
.
keySet
())
{
if
(
"content-length"
.
equalsIgnoreCase
(
headerName
))
{
try
{
return
Long
.
parseLong
(
header
.
get
(
headerName
));
}
catch
(
NumberFormatException
ex
)
{
return
size
;
}
}
}
pw
.
print
(
"Content-Length: "
+
size
+
"\r\n"
);
return
size
;
}
public
void
setChunkedTransfer
(
boolean
chunkedTransfer
)
{
this
.
chunkedTransfer
=
chunkedTransfer
;
}
public
void
setData
(
InputStream
data
)
{
this
.
data
=
data
;
}
public
void
setMimeType
(
String
mimeType
)
{
this
.
mimeType
=
mimeType
;
}
public
void
setRequestMethod
(
Method
requestMethod
)
{
this
.
requestMethod
=
requestMethod
;
}
public
void
setStatus
(
IStatus
status
)
{
this
.
status
=
status
;
}
}
public
static
final
class
ResponseException
extends
Exception
{
private
static
final
long
serialVersionUID
=
6569838532917408380L
;
private
final
Response
.
Status
status
;
public
ResponseException
(
Response
.
Status
status
,
String
message
)
{
super
(
message
);
this
.
status
=
status
;
}
public
ResponseException
(
Response
.
Status
status
,
String
message
,
Exception
e
)
{
super
(
message
,
e
);
this
.
status
=
status
;
}
public
Response
.
Status
getStatus
()
{
return
this
.
status
;
}
}
/**
* The runnable that will be used for the main listening thread.
*/
public
class
ServerRunnable
implements
Runnable
{
private
final
int
timeout
;
private
IOException
bindException
;
private
boolean
hasBinded
=
false
;
private
ServerRunnable
(
int
timeout
)
{
this
.
timeout
=
timeout
;
}
@Override
public
void
run
()
{
try
{
myServerSocket
.
bind
(
hostname
!=
null
?
new
InetSocketAddress
(
hostname
,
myPort
)
:
new
InetSocketAddress
(
myPort
));
hasBinded
=
true
;
}
catch
(
IOException
e
)
{
this
.
bindException
=
e
;
return
;
}
do
{
try
{
final
Socket
finalAccept
=
NanoHTTPD
.
this
.
myServerSocket
.
accept
();
if
(
this
.
timeout
>
0
)
{
finalAccept
.
setSoTimeout
(
this
.
timeout
);
}
final
InputStream
inputStream
=
finalAccept
.
getInputStream
();
lastAccess
=
System
.
currentTimeMillis
();
NanoHTTPD
.
this
.
asyncRunner
.
exec
(
createClientHandler
(
finalAccept
,
inputStream
));
}
catch
(
IOException
e
)
{
NanoHTTPD
.
LOG
.
log
(
Level
.
FINE
,
"Communication with the client broken"
,
e
);
}
}
while
(!
NanoHTTPD
.
this
.
myServerSocket
.
isClosed
());
}
}
public
long
getLastAccess
()
{
return
lastAccess
;
}
/**
* A temp file.
* <p/>
* <p>
* Temp files are responsible for managing the actual temporary storage and
* cleaning themselves up when no longer needed.
* </p>
*/
public
interface
TempFile
{
public
void
delete
()
throws
Exception
;
public
String
getName
();
public
OutputStream
open
()
throws
Exception
;
}
/**
* Temp file manager.
* <p/>
* <p>
* Temp file managers are created 1-to-1 with incoming requests, to create
* and cleanup temporary files created as a result of handling the request.
* </p>
*/
public
interface
TempFileManager
{
void
clear
();
public
TempFile
createTempFile
(
String
filename_hint
)
throws
Exception
;
}
/**
* Factory to create temp file managers.
*/
public
interface
TempFileManagerFactory
{
public
TempFileManager
create
();
}
/**
* Factory to create ServerSocketFactories.
*/
public
interface
ServerSocketFactory
{
public
ServerSocket
create
()
throws
IOException
;
}
/**
* Maximum time to wait on Socket.getInputStream().read() (in milliseconds)
* This is required as the Keep-Alive HTTP connections would otherwise block
* the socket reading thread forever (or as long the browser is open).
*/
public
static
final
int
SOCKET_READ_TIMEOUT
=
5000
;
/**
* Common MIME type for dynamic content: plain text
*/
public
static
final
String
MIME_PLAINTEXT
=
"text/plain"
;
/**
* Common MIME type for dynamic content: html
*/
public
static
final
String
MIME_HTML
=
"text/html"
;
/**
* Pseudo-Parameter to use to store the actual query string in the
* parameters map for later re-processing.
*/
private
static
final
String
QUERY_STRING_PARAMETER
=
"NanoHttpd.QUERY_STRING"
;
/**
* logger to log to.
*/
private
static
final
Logger
LOG
=
Logger
.
getLogger
(
NanoHTTPD
.
class
.
getName
());
/**
* Hashtable mapping (String)FILENAME_EXTENSION -> (String)MIME_TYPE
*/
protected
static
Map
<
String
,
String
>
MIME_TYPES
;
private
static
void
loadMimeTypes
()
{
if
(
MIME_TYPES
==
null
)
{
MIME_TYPES
=
new
HashMap
<
String
,
String
>();
MIME_TYPES
.
put
(
"css"
,
"text/css"
);
MIME_TYPES
.
put
(
"htm"
,
"text/html"
);
MIME_TYPES
.
put
(
"html"
,
"text/html"
);
MIME_TYPES
.
put
(
"xml"
,
"text/xml"
);
MIME_TYPES
.
put
(
"java"
,
"text/x-java-source, text/java"
);
MIME_TYPES
.
put
(
"md"
,
"text/plain"
);
MIME_TYPES
.
put
(
"txt"
,
"text/plain"
);
MIME_TYPES
.
put
(
"asc"
,
"text/plain"
);
MIME_TYPES
.
put
(
"gif"
,
"image/gif"
);
MIME_TYPES
.
put
(
"jpg"
,
"image/jpeg"
);
MIME_TYPES
.
put
(
"jpeg"
,
"image/jpeg"
);
MIME_TYPES
.
put
(
"png"
,
"image/png"
);
MIME_TYPES
.
put
(
"svg"
,
"image/svg+xml"
);
MIME_TYPES
.
put
(
"mp3"
,
"audio/mpeg"
);
MIME_TYPES
.
put
(
"m3u"
,
"audio/mpeg-url"
);
MIME_TYPES
.
put
(
"mp4"
,
"video/mp4"
);
MIME_TYPES
.
put
(
"ogv"
,
"video/ogg"
);
MIME_TYPES
.
put
(
"flv"
,
"video/x-flv"
);
MIME_TYPES
.
put
(
"mov"
,
"video/quicktime"
);
MIME_TYPES
.
put
(
"swf"
,
"application/x-shockwave-flash"
);
MIME_TYPES
.
put
(
"js"
,
"application/javascript"
);
MIME_TYPES
.
put
(
"pdf"
,
"application/pdf"
);
MIME_TYPES
.
put
(
"doc"
,
"application/msword"
);
MIME_TYPES
.
put
(
"ogg"
,
"application/x-ogg"
);
MIME_TYPES
.
put
(
"zip"
,
"application/octet-stream"
);
MIME_TYPES
.
put
(
"exe"
,
"application/octet-stream"
);
MIME_TYPES
.
put
(
"class"
,
"application/octet-stream"
);
MIME_TYPES
.
put
(
"m3u8"
,
"application/vnd.apple.mpegurl"
);
MIME_TYPES
.
put
(
"ts"
,
"video/mp2t"
);
if
(
MIME_TYPES
.
isEmpty
())
{
LOG
.
log
(
Level
.
WARNING
,
"no mime types found in the classpath! please provide mimetypes.properties"
);
}
}
}
/**
* Creates an SSLSocketFactory for HTTPS. Pass a loaded KeyStore and an
* array of loaded KeyManagers. These objects must properly
* loaded/initialized by the caller.
*/
public
static
SSLServerSocketFactory
makeSSLSocketFactory
(
KeyStore
loadedKeyStore
,
KeyManager
[]
keyManagers
)
throws
IOException
{
SSLServerSocketFactory
res
;
try
{
TrustManagerFactory
trustManagerFactory
=
TrustManagerFactory
.
getInstance
(
TrustManagerFactory
.
getDefaultAlgorithm
());
trustManagerFactory
.
init
(
loadedKeyStore
);
SSLContext
ctx
=
SSLContext
.
getInstance
(
"TLS"
);
ctx
.
init
(
keyManagers
,
trustManagerFactory
.
getTrustManagers
(),
null
);
res
=
ctx
.
getServerSocketFactory
();
}
catch
(
Exception
e
)
{
throw
new
IOException
(
e
.
getMessage
());
}
return
res
;
}
/**
* Creates an SSLSocketFactory for HTTPS. Pass a loaded KeyStore and a
* loaded KeyManagerFactory. These objects must properly loaded/initialized
* by the caller.
*/
public
static
SSLServerSocketFactory
makeSSLSocketFactory
(
KeyStore
loadedKeyStore
,
KeyManagerFactory
loadedKeyFactory
)
throws
IOException
{
try
{
return
makeSSLSocketFactory
(
loadedKeyStore
,
loadedKeyFactory
.
getKeyManagers
());
}
catch
(
Exception
e
)
{
throw
new
IOException
(
e
.
getMessage
());
}
}
/**
* Creates an SSLSocketFactory for HTTPS. Pass a KeyStore resource with your
* certificate and passphrase
*/
public
static
SSLServerSocketFactory
makeSSLSocketFactory
(
String
keyAndTrustStoreClasspathPath
,
char
[]
passphrase
)
throws
IOException
{
try
{
KeyStore
keystore
=
KeyStore
.
getInstance
(
KeyStore
.
getDefaultType
());
InputStream
keystoreStream
=
NanoHTTPD
.
class
.
getResourceAsStream
(
keyAndTrustStoreClasspathPath
);
keystore
.
load
(
keystoreStream
,
passphrase
);
KeyManagerFactory
keyManagerFactory
=
KeyManagerFactory
.
getInstance
(
KeyManagerFactory
.
getDefaultAlgorithm
());
keyManagerFactory
.
init
(
keystore
,
passphrase
);
return
makeSSLSocketFactory
(
keystore
,
keyManagerFactory
);
}
catch
(
Exception
e
)
{
throw
new
IOException
(
e
.
getMessage
());
}
}
/**
* Get MIME type from file name extension, if possible
*
* @param uri
* the string representing a file
* @return the connected mime/type
*/
public
static
String
getMimeTypeForFile
(
String
uri
)
{
int
dot
=
uri
.
lastIndexOf
(
'.'
);
String
mime
=
null
;
if
(
dot
>=
0
)
{
mime
=
MIME_TYPES
.
get
(
uri
.
substring
(
dot
+
1
).
toLowerCase
());
}
return
mime
==
null
?
"application/octet-stream"
:
mime
;
}
private
static
final
void
safeClose
(
Object
closeable
)
{
try
{
if
(
closeable
!=
null
)
{
if
(
closeable
instanceof
Closeable
)
{
((
Closeable
)
closeable
).
close
();
}
else
if
(
closeable
instanceof
Socket
)
{
((
Socket
)
closeable
).
close
();
}
else
if
(
closeable
instanceof
ServerSocket
)
{
((
ServerSocket
)
closeable
).
close
();
}
else
{
throw
new
IllegalArgumentException
(
"Unknown object to close"
);
}
}
}
catch
(
IOException
e
)
{
NanoHTTPD
.
LOG
.
log
(
Level
.
SEVERE
,
"Could not close"
,
e
);
}
}
private
final
String
hostname
;
private
final
int
myPort
;
private
volatile
ServerSocket
myServerSocket
;
private
ServerSocketFactory
serverSocketFactory
=
new
DefaultServerSocketFactory
();
private
Thread
myThread
;
/**
* Pluggable strategy for asynchronously executing requests.
*/
protected
AsyncRunner
asyncRunner
;
/**
* Pluggable strategy for creating and cleaning up temporary files.
*/
private
TempFileManagerFactory
tempFileManagerFactory
;
/**
* Constructs an HTTP server on given port.
*/
public
NanoHTTPD
(
int
port
)
{
this
(
null
,
port
);
}
// -------------------------------------------------------------------------------
// //
//
// Threading Strategy.
//
// -------------------------------------------------------------------------------
// //
/**
* Constructs an HTTP server on given hostname and port.
*/
public
NanoHTTPD
(
String
hostname
,
int
port
)
{
this
.
hostname
=
hostname
;
this
.
myPort
=
port
;
setTempFileManagerFactory
(
new
DefaultTempFileManagerFactory
());
setAsyncRunner
(
new
DefaultAsyncRunner
());
}
/**
* Forcibly closes all connections that are open.
*/
public
synchronized
void
closeAllConnections
()
{
stop
();
}
/**
* create a instance of the client handler, subclasses can return a subclass
* of the ClientHandler.
*
* @param finalAccept
* the socket the cleint is connected to
* @param inputStream
* the input stream
* @return the client handler
*/
protected
ClientHandler
createClientHandler
(
final
Socket
finalAccept
,
final
InputStream
inputStream
)
{
return
new
ClientHandler
(
inputStream
,
finalAccept
);
}
/**
* Instantiate the server runnable, can be overwritten by subclasses to
* provide a subclass of the ServerRunnable.
*
* @param timeout
* the socet timeout to use.
* @return the server runnable.
*/
protected
ServerRunnable
createServerRunnable
(
final
int
timeout
)
{
return
new
ServerRunnable
(
timeout
);
}
/**
* Decode parameters from a URL, handing the case where a single parameter
* name might have been supplied several times, by return lists of values.
* In general these lists will contain a single element.
*
* @param parms
* original <b>NanoHTTPD</b> parameters values, as passed to the
* <code>serve()</code> method.
* @return a map of <code>String</code> (parameter name) to
* <code>List<String></code> (a list of the values supplied).
*/
protected
static
Map
<
String
,
List
<
String
>>
decodeParameters
(
Map
<
String
,
String
>
parms
)
{
return
decodeParameters
(
parms
.
get
(
NanoHTTPD
.
QUERY_STRING_PARAMETER
));
}
// -------------------------------------------------------------------------------
// //
/**
* Decode parameters from a URL, handing the case where a single parameter
* name might have been supplied several times, by return lists of values.
* In general these lists will contain a single element.
*
* @param queryString
* a query string pulled from the URL.
* @return a map of <code>String</code> (parameter name) to
* <code>List<String></code> (a list of the values supplied).
*/
protected
static
Map
<
String
,
List
<
String
>>
decodeParameters
(
String
queryString
)
{
Map
<
String
,
List
<
String
>>
parms
=
new
HashMap
<
String
,
List
<
String
>>();
if
(
queryString
!=
null
)
{
StringTokenizer
st
=
new
StringTokenizer
(
queryString
,
"&"
);
while
(
st
.
hasMoreTokens
())
{
String
e
=
st
.
nextToken
();
int
sep
=
e
.
indexOf
(
'='
);
String
propertyName
=
sep
>=
0
?
decodePercent
(
e
.
substring
(
0
,
sep
)).
trim
()
:
decodePercent
(
e
).
trim
();
if
(!
parms
.
containsKey
(
propertyName
))
{
parms
.
put
(
propertyName
,
new
ArrayList
<
String
>());
}
String
propertyValue
=
sep
>=
0
?
decodePercent
(
e
.
substring
(
sep
+
1
))
:
null
;
if
(
propertyValue
!=
null
)
{
parms
.
get
(
propertyName
).
add
(
propertyValue
);
}
}
}
return
parms
;
}
/**
* Decode percent encoded <code>String</code> values.
*
* @param str
* the percent encoded <code>String</code>
* @return expanded form of the input, for example "foo%20bar" becomes
* "foo bar"
*/
protected
static
String
decodePercent
(
String
str
)
{
String
decoded
=
null
;
try
{
decoded
=
URLDecoder
.
decode
(
str
,
"UTF8"
);
}
catch
(
UnsupportedEncodingException
ignored
)
{
NanoHTTPD
.
LOG
.
log
(
Level
.
WARNING
,
"Encoding not supported, ignored"
,
ignored
);
}
return
decoded
;
}
/**
* @return true if the gzip compression should be used if the client
* accespts it. Default this option is on for text content and off
* for everything. Override this for custom semantics.
*/
protected
boolean
useGzipWhenAccepted
(
Response
r
)
{
return
r
.
getMimeType
()
!=
null
&&
r
.
getMimeType
().
toLowerCase
().
contains
(
"text/"
);
}
public
final
int
getListeningPort
()
{
return
this
.
myServerSocket
==
null
?
-
1
:
this
.
myServerSocket
.
getLocalPort
();
}
public
final
boolean
isAlive
()
{
return
wasStarted
()
&&
!
this
.
myServerSocket
.
isClosed
()
&&
this
.
myThread
.
isAlive
();
}
public
ServerSocketFactory
getServerSocketFactory
()
{
return
serverSocketFactory
;
}
public
void
setServerSocketFactory
(
ServerSocketFactory
serverSocketFactory
)
{
this
.
serverSocketFactory
=
serverSocketFactory
;
}
public
String
getHostname
()
{
return
hostname
;
}
public
TempFileManagerFactory
getTempFileManagerFactory
()
{
return
tempFileManagerFactory
;
}
/**
* Call before start() to serve over HTTPS instead of HTTP
*/
public
void
makeSecure
(
SSLServerSocketFactory
sslServerSocketFactory
,
String
[]
sslProtocols
)
{
this
.
serverSocketFactory
=
new
SecureServerSocketFactory
(
sslServerSocketFactory
,
sslProtocols
);
}
/**
* Create a response with unknown length (using HTTP 1.1 chunking).
*/
public
static
Response
newChunkedResponse
(
IStatus
status
,
String
mimeType
,
InputStream
data
)
{
return
new
Response
(
status
,
mimeType
,
data
,
-
1
);
}
/**
* Create a response with known length.
*/
public
static
Response
newFixedLengthResponse
(
IStatus
status
,
String
mimeType
,
InputStream
data
,
long
totalBytes
)
{
return
new
Response
(
status
,
mimeType
,
data
,
totalBytes
);
}
/**
* Create a text response with known length.
*/
public
static
Response
newFixedLengthResponse
(
IStatus
status
,
String
mimeType
,
String
txt
)
{
if
(
txt
==
null
)
{
return
newFixedLengthResponse
(
status
,
mimeType
,
new
ByteArrayInputStream
(
new
byte
[
0
]),
0
);
}
else
{
byte
[]
bytes
;
try
{
bytes
=
txt
.
getBytes
(
"UTF-8"
);
}
catch
(
UnsupportedEncodingException
e
)
{
NanoHTTPD
.
LOG
.
log
(
Level
.
SEVERE
,
"encoding problem, responding nothing"
,
e
);
bytes
=
new
byte
[
0
];
}
return
newFixedLengthResponse
(
status
,
mimeType
,
new
ByteArrayInputStream
(
bytes
),
bytes
.
length
);
}
}
/**
* Create a text response with known length.
*/
public
static
Response
newFixedLengthResponse
(
String
msg
)
{
return
newFixedLengthResponse
(
Status
.
OK
,
NanoHTTPD
.
MIME_HTML
,
msg
);
}
/**
* Override this to customize the server.
* <p/>
* <p/>
* (By default, this returns a 404 "Not Found" plain text error response.)
*
* @param session
* The HTTP session
* @return HTTP response, see class Response for details
*/
public
Response
serve
(
IHTTPSession
session
)
{
Map
<
String
,
String
>
files
=
new
HashMap
<
String
,
String
>();
Method
method
=
session
.
getMethod
();
if
(
Method
.
PUT
.
equals
(
method
)
||
Method
.
POST
.
equals
(
method
))
{
try
{
session
.
parseBody
(
files
);
}
catch
(
IOException
ioe
)
{
return
newFixedLengthResponse
(
Response
.
Status
.
INTERNAL_ERROR
,
NanoHTTPD
.
MIME_PLAINTEXT
,
"SERVER INTERNAL ERROR: IOException: "
+
ioe
.
getMessage
());
}
catch
(
ResponseException
re
)
{
return
newFixedLengthResponse
(
re
.
getStatus
(),
NanoHTTPD
.
MIME_PLAINTEXT
,
re
.
getMessage
());
}
}
Map
<
String
,
String
>
parms
=
session
.
getParms
();
parms
.
put
(
NanoHTTPD
.
QUERY_STRING_PARAMETER
,
session
.
getQueryParameterString
());
return
serve
(
session
.
getUri
(),
method
,
session
.
getHeaders
(),
parms
,
files
);
}
/**
* Override this to customize the server.
* <p/>
* <p/>
* (By default, this returns a 404 "Not Found" plain text error response.)
*
* @param uri
* Percent-decoded URI without parameters, for example
* "/index.cgi"
* @param method
* "GET", "POST" etc.
* @param parms
* Parsed, percent decoded parameters from URI and, in case of
* POST, data.
* @param headers
* Header entries, percent decoded
* @return HTTP response, see class Response for details
*/
@Deprecated
public
Response
serve
(
String
uri
,
Method
method
,
Map
<
String
,
String
>
headers
,
Map
<
String
,
String
>
parms
,
Map
<
String
,
String
>
files
)
{
return
newFixedLengthResponse
(
Response
.
Status
.
NOT_FOUND
,
NanoHTTPD
.
MIME_PLAINTEXT
,
"Not Found"
);
}
/**
* Pluggable strategy for asynchronously executing requests.
*
* @param asyncRunner
* new strategy for handling threads.
*/
public
void
setAsyncRunner
(
AsyncRunner
asyncRunner
)
{
this
.
asyncRunner
=
asyncRunner
;
}
/**
* Pluggable strategy for creating and cleaning up temporary files.
*
* @param tempFileManagerFactory
* new strategy for handling temp files.
*/
public
void
setTempFileManagerFactory
(
TempFileManagerFactory
tempFileManagerFactory
)
{
this
.
tempFileManagerFactory
=
tempFileManagerFactory
;
}
/**
* Start the server.
*
* @throws IOException
* if the socket is in use.
*/
public
void
start
()
throws
IOException
{
start
(
NanoHTTPD
.
SOCKET_READ_TIMEOUT
);
}
/**
* Starts the server (in setDaemon(true) mode).
*/
public
void
start
(
final
int
timeout
)
throws
IOException
{
start
(
timeout
,
true
);
}
/**
* Start the server.
*
* @param timeout
* timeout to use for socket connections.
* @param daemon
* start the thread daemon or not.
* @throws IOException
* if the socket is in use.
*/
public
void
start
(
final
int
timeout
,
boolean
daemon
)
throws
IOException
{
this
.
myServerSocket
=
this
.
getServerSocketFactory
().
create
();
this
.
myServerSocket
.
setReuseAddress
(
true
);
ServerRunnable
serverRunnable
=
createServerRunnable
(
timeout
);
this
.
myThread
=
new
Thread
(
serverRunnable
);
this
.
myThread
.
setDaemon
(
daemon
);
this
.
myThread
.
setName
(
"NanoHttpd Main Listener"
);
this
.
myThread
.
start
();
while
(!
serverRunnable
.
hasBinded
&&
serverRunnable
.
bindException
==
null
)
{
try
{
Thread
.
sleep
(
10L
);
}
catch
(
Throwable
e
)
{
// on android this may not be allowed, that's why we
// catch throwable the wait should be very short because we are
// just waiting for the bind of the socket
}
}
if
(
serverRunnable
.
bindException
!=
null
)
{
throw
serverRunnable
.
bindException
;
}
}
/**
* Stop the server.
*/
public
void
stop
()
{
try
{
safeClose
(
this
.
myServerSocket
);
this
.
asyncRunner
.
closeAll
();
if
(
this
.
myThread
!=
null
)
{
this
.
myThread
.
join
();
}
}
catch
(
Exception
e
)
{
NanoHTTPD
.
LOG
.
log
(
Level
.
SEVERE
,
"Could not stop all connections"
,
e
);
}
}
public
final
boolean
wasStarted
()
{
return
this
.
myServerSocket
!=
null
&&
this
.
myThread
!=
null
;
}
}
\ No newline at end of file
ABVJE_BL/src/jp/agentec/abook/abv/bl/common/Constant.java
View file @
3e307bda
...
...
@@ -146,10 +146,6 @@ public class Constant {
}
public
interface
editionType
{
int
BIZ
=
1
;
int
SIGNAGE
=
2
;
int
AD
=
3
;
int
READER
=
4
;
int
CHECK
=
5
;
}
}
ABVJE_BL/src/jp/agentec/abook/abv/bl/common/constant/ABookKeys.java
View file @
3e307bda
...
...
@@ -96,4 +96,25 @@ public class ABookKeys {
public
static
final
int
HTTP_STATUS_SUCCESS
=
200
;
public
static
final
String
HELP_VIEW_TYPE
=
"helpViewType"
;
public
static
final
String
ABOOK
=
"abook"
;
public
static
final
String
MOVEPAGE
=
"/abookmovepage"
;
public
static
final
String
DETAILLOG
=
"/abookdetaillog"
;
public
static
final
String
CONTENTLINK
=
"/abookcontentlink"
;
public
static
final
String
NEXTCONTENT
=
"/abooknextcontent"
;
public
static
final
String
SEND_CUSTOM_LOG
=
"/abooksendcustomlog"
;
public
static
final
String
GETITS_OPEN_SHARE
=
"/abookopengetitsshare"
;
public
static
final
String
PING
=
"/ping"
;
public
static
final
String
CMD_GETITS_OPEN_SHARE
=
"opengetitsshare"
;
public
static
final
String
CMD_GETITS_CLOSE_SHARE
=
"closegetitsshare"
;
public
static
final
String
PARAM_LAST_PAGE_NUMBER
=
"lastPageNo"
;
public
static
final
String
PARAM_LAST_PAGE_START_DATE
=
"lastPageStartDate"
;
public
static
final
String
PARAM_READING_LOG_ID
=
"readingLogId"
;
public
static
final
String
PARAM_SHARE_URL
=
"shareUrl"
;
public
static
final
String
URI
=
"uri"
;
public
static
final
String
CLOSE
=
"CLOSE"
;
public
static
final
String
OK
=
"OK"
;
}
ABVJE_BL/src/jp/agentec/abook/abv/bl/data/DatabaseVersions.java
View file @
3e307bda
...
...
@@ -15,7 +15,7 @@ public class DatabaseVersions {
public
static
final
int
Plus_1_3_0
=
11
;
// 2014/01/27 ABook+1.3
public
static
final
int
Plus_1_4_0_OLD
=
12
;
// 2014/04/1 ABook+1.4旧
public
static
final
int
Plus_1_4_0
=
20
;
// 2014/05/21 ABook+1.4
public
static
final
int
Plus_1_4_3
=
30
;
// 2014/05/21 ABook+1.4.3
public
static
final
int
Plus_1_4_3
=
30
;
// 2014/05/21 ABook+1.4.3
public
static
final
int
Plus_1_5_0
=
40
;
// 2014/07/25 ABook+1.5
public
static
final
int
Plus_1_5_2
=
50
;
// 2014/07/25 ABook+1.5.2
public
static
final
int
Plus_1_6_0
=
60
;
// 2014/12/01 ABook+1.6.0
...
...
ABVJE_BL/src/jp/agentec/abook/abv/bl/data/dao/ContentDao.java
View file @
3e307bda
...
...
@@ -1082,7 +1082,7 @@ public class ContentDao extends AbstractDao {
sql
.
append
(
" ON tc.content_id = rcc.content_id "
);
sql
.
append
(
" INNER JOIN m_category AS mc "
);
sql
.
append
(
" ON rcc.category_relation_id = mc.category_relation_id "
);
sql
.
append
(
" WHERE tc.common_content_flg = 1"
);
sql
.
append
(
" WHERE tc.common_content_flg = 1"
);
sql
.
append
(
" ORDER BY mc.category_id, tc.content_id DESC "
);
return
rawQueryGetDtoList
(
sql
.
toString
(),
null
,
ContentDto
.
class
);
...
...
ABVJE_BL/src/jp/agentec/abook/abv/bl/data/dao/ProjectContentDao.java
View file @
3e307bda
...
...
@@ -95,10 +95,6 @@ public class ProjectContentDao extends AbstractDao {
}
}
public
void
deleteAll
()
{
delete
(
"r_project_content"
,
null
,
null
);
}
/**
* リストを削除
* @param projectId
...
...
ABVJE_BL/src/jp/agentec/abook/abv/bl/download/ReaderContentDownloader.java
deleted
100644 → 0
View file @
32ec4e3a
package
jp
.
agentec
.
abook
.
abv
.
bl
.
download
;
import
java.io.File
;
import
java.net.MalformedURLException
;
import
java.util.Locale
;
import
jp.agentec.abook.abv.bl.acms.client.AcmsClient
;
import
jp.agentec.abook.abv.bl.acms.client.json.reader.ReaderContentJSON
;
import
jp.agentec.abook.abv.bl.acms.client.json.reader.ReaderContentVersionJSON
;
import
jp.agentec.abook.abv.bl.acms.client.parameters.ContentDownloadLogParameters
;
import
jp.agentec.abook.abv.bl.acms.type.ContentZipType
;
import
jp.agentec.abook.abv.bl.acms.type.DownloadStatusType
;
import
jp.agentec.abook.abv.bl.common.ABVEnvironment
;
import
jp.agentec.abook.abv.bl.common.Constant.ReaderConstant
;
import
jp.agentec.abook.abv.bl.common.exception.ABVException
;
import
jp.agentec.abook.abv.bl.common.exception.ABVExceptionCode
;
import
jp.agentec.abook.abv.bl.common.exception.AcmsException
;
import
jp.agentec.abook.abv.bl.common.exception.NetworkDisconnectedException
;
import
jp.agentec.abook.abv.bl.common.log.Logger
;
import
jp.agentec.abook.abv.bl.common.util.SecurityUtil
;
import
jp.agentec.abook.abv.bl.data.ABVDataCache
;
import
jp.agentec.abook.abv.bl.data.dao.AbstractDao
;
import
jp.agentec.abook.abv.bl.data.dao.ContentDao
;
import
jp.agentec.abook.abv.bl.data.dao.ContentIdConvDao
;
import
jp.agentec.abook.abv.bl.dto.ContentDto
;
import
jp.agentec.abook.abv.bl.dto.ContentIdConvDto
;
import
jp.agentec.abook.abv.bl.logic.AbstractLogic
;
import
jp.agentec.abook.abv.bl.logic.ContentLogic
;
import
jp.agentec.adf.net.http.HttpDownloadState
;
import
jp.agentec.adf.net.http.HttpFileDownloader
;
import
jp.agentec.adf.net.http.HttpResponse
;
import
jp.agentec.adf.util.DateTimeUtil
;
import
jp.agentec.adf.util.FileUtil
;
import
jp.agentec.adf.util.StringUtil
;
public
class
ReaderContentDownloader
{
private
static
final
String
TAG
=
"ReaderContentDownloader"
;
private
static
ReaderContentDownloader
instance
;
private
ContentDownloader
contentDownloader
=
ContentDownloader
.
getInstance
();
private
ContentLogic
contentLogic
=
AbstractLogic
.
getLogic
(
ContentLogic
.
class
);
private
ContentDao
contentDao
=
AbstractDao
.
getDao
(
ContentDao
.
class
);
private
ContentFileExtractor
contentFileExtractor
=
ContentFileExtractor
.
getInstance
();
private
ABVDataCache
cache
=
ABVDataCache
.
getInstance
();
private
ReaderContentDownloader
()
{
}
/**
* {@link ContentDownloader} クラスのインスタンスを取得します。
*
* @return {@link ContentDownloader} クラスのインスタンスを返します。
* @since 1.0.0
*/
public
static
ReaderContentDownloader
getInstance
()
{
if
(
instance
==
null
)
{
synchronized
(
ContentDownloader
.
class
)
{
if
(
instance
==
null
)
{
instance
=
new
ReaderContentDownloader
();
}
}
}
return
instance
;
}
/**
* ReaderコンテンツのDLを実行する
*
* @param contentDto
* @return
* @throws AcmsException
*/
HttpFileDownloader
executeDownload
(
ContentDto
contentDto
)
throws
AcmsException
{
ContentIdConvDto
contentIdConvDto
=
AbstractDao
.
getDao
(
ContentIdConvDao
.
class
).
getDto
(
contentDto
.
contentId
);
String
keyForCms
=
SecurityUtil
.
getEncryptString
(
ReaderConstant
.
SHARED_SECRET_CMS
,
""
+
System
.
currentTimeMillis
(),
true
);
String
downloadUrl
=
contentIdConvDto
.
downloadUrl
+
"?contentId="
+
contentIdConvDto
.
cmsContentId
+
"&filePattern=2&key="
+
keyForCms
;
HttpFileDownloader
downloader
=
contentDownloader
.
executeDownload
(
contentDto
,
downloadUrl
);
// ログ送信
ContentDownloadLogParameters
downloadParam
=
new
ContentDownloadLogParameters
(
null
,
contentDto
.
contentId
,
DateTimeUtil
.
getCurrentTimestamp
()
,
contentDto
.
resourceVersion
,
ABVEnvironment
.
DeviceTypeId
,
DownloadStatusType
.
Downloading
);
try
{
AcmsClient
acmsClient
=
AcmsClient
.
getInstance
(
cache
.
getUrlPath
(),
ABVEnvironment
.
getInstance
().
networkAdapter
);
acmsClient
.
contentDownloadLog
(
downloadParam
);
}
catch
(
NetworkDisconnectedException
e
)
{
// サーバ側のエラーはここでは無視
Logger
.
e
(
TAG
,
"contentDownloadLog "
+
downloadParam
,
e
);
}
return
downloader
;
}
/**
* コンテンツバージョン情報を取得する
*
* @param contentVersionUrl
* @param cmsContentId
* @return
* @throws NetworkDisconnectedException
* @throws AcmsException
*/
public
ReaderContentVersionJSON
getContentVersion
(
String
contentVersionUrl
,
long
cmsContentId
)
throws
AcmsException
,
NetworkDisconnectedException
{
String
keyForCms
=
SecurityUtil
.
getEncryptString
(
ReaderConstant
.
SHARED_SECRET_CMS
,
""
+
System
.
currentTimeMillis
(),
true
);
String
url
=
contentVersionUrl
+
"?contentId="
+
cmsContentId
+
"&key="
+
keyForCms
+
"&language="
+
Locale
.
getDefault
().
getLanguage
();
HttpResponse
response
=
AcmsClient
.
getInstance
(
ABVEnvironment
.
getInstance
().
networkAdapter
).
send
(
url
,
""
,
null
);
return
new
ReaderContentVersionJSON
(
response
.
httpResponseBody
);
}
/**
* Reader用のコンテンツダウンロード(一連)
*
* @param contentJson
* @throws Exception
*/
public
void
downloadContent
(
ReaderContentJSON
contentJson
)
throws
Exception
{
downloadContent
(
contentJson
.
siteId
,
contentJson
.
cmsContentId
,
contentJson
.
downloadUrl
,
contentJson
.
contractId
,
contentJson
.
contractContentId
,
contentJson
.
shortUrl
);
}
public
void
registrationDownloadContent
(
ReaderContentJSON
contentJson
)
throws
Exception
{
long
contentId
=
downloadContentInforAndContentDetail
(
contentJson
.
siteId
,
contentJson
.
cmsContentId
,
contentJson
.
downloadUrl
,
contentJson
.
contractId
,
contentJson
.
contractContentId
,
contentJson
.
shortUrl
);
contentDownloader
.
reserveDownload
(
contentId
,
false
);
}
//コンテンツ情報とコンテンツ詳細をダウンロードして該当するコンテンツIDに返す
private
long
downloadContentInforAndContentDetail
(
int
siteId
,
long
cmsContentId
,
String
downloadUrl
,
int
contractId
,
int
contractContentId
,
String
shortUrl
)
throws
Exception
{
long
contentId
=
ContentLogic
.
getReaderContentId
(
siteId
,
cmsContentId
);
String
keyForCms
=
SecurityUtil
.
getEncryptString
(
ReaderConstant
.
SHARED_SECRET_CMS
,
""
+
System
.
currentTimeMillis
(),
true
);
// info (Sync)
String
url
=
downloadUrl
+
"?contentId="
+
cmsContentId
+
"&filePattern=1&key="
+
keyForCms
;
downloadContentInfo
(
contentId
,
url
);
if
(
contractContentId
==
-
1
){
// ダウンロード開始時点でContractContentIdが分からない場合、ダウンロードした情報で上書き
contractContentId
=
contentDao
.
getContent
(
contentId
).
contractContentId
;
}
// contentIdConv登録
ContentIdConvDto
contentIdConvDto
=
new
ContentIdConvDto
(
contentId
,
siteId
,
contractId
,
cmsContentId
,
contractContentId
,
downloadUrl
,
shortUrl
);
AbstractDao
.
getDao
(
ContentIdConvDao
.
class
).
insertOrUpdateupdate
(
contentIdConvDto
);
// detail (Sync) コンテンツ詳細はPDFコンテンツのみダウンロードする
ContentDto
contentDto
=
contentDao
.
getContent
(
contentId
);
if
(
contentDto
!=
null
&&
contentDto
.
isPdf
())
{
url
=
downloadUrl
+
"?contentId="
+
cmsContentId
+
"&filePattern=3&key="
+
keyForCms
;
downloadContentDetail
(
contentId
,
url
);
}
return
contentId
;
}
public
void
downloadContent
(
int
siteId
,
long
cmsContentId
,
String
downloadUrl
,
int
contractId
,
int
contractContentId
,
String
shortUrl
)
throws
Exception
{
long
contentId
=
downloadContentInforAndContentDetail
(
siteId
,
cmsContentId
,
downloadUrl
,
contractId
,
contractContentId
,
shortUrl
);
// downloadキューへ登録 (ASync)
contentDownloader
.
download
(
contentId
);
}
/**
* Reader用ContentInfoダウンロード
*
* @param contentId
* @param downloadUrl
* @throws NetworkDisconnectedException
* @throws ABVException
* @throws Exception
*/
public
void
downloadContentInfo
(
long
contentId
,
String
downloadUrl
)
throws
Exception
{
String
outputFilePath
=
String
.
format
(
"%s/%s_%s.zip"
,
ABVEnvironment
.
getInstance
().
getContentDownloadsDirectoryPath
(),
ContentZipType
.
ContentInfo
.
name
(),
contentId
);
ContentRefresher
.
getInstance
().
addRefreshingContentId
(
contentId
);
Logger
.
d
(
TAG
,
"[url : %s], [contentId : %s]"
,
downloadUrl
,
contentId
);
HttpFileDownloader
downloader
=
new
HttpFileDownloader
(
downloadUrl
,
null
,
outputFilePath
);
downloader
.
downloadSync
();
if
(
downloader
.
getState
()
==
HttpDownloadState
.
failed
)
{
throw
downloader
.
getError
();
}
else
if
(
downloader
.
getState
()
!=
HttpDownloadState
.
finished
)
{
// ほぼ原因はNW切断
Logger
.
e
(
TAG
,
"download failed. [url : %s], [contentId : %s] state=%s"
,
downloadUrl
,
contentId
,
downloader
.
getState
());
throw
new
NetworkDisconnectedException
();
}
try
{
String
contentPath
=
ABVEnvironment
.
getInstance
().
getContentDirectoryPath
(
contentId
,
false
)
+
File
.
separator
;
FileUtil
.
deleteFileOnly
(
contentPath
);
contentFileExtractor
.
removeContentCash
(
contentId
);
contentFileExtractor
.
extractZipFile
(
contentId
,
outputFilePath
,
contentPath
);
contentLogic
.
saveContentInfo
(
contentPath
,
contentId
,
false
,
false
);
}
catch
(
Exception
e
)
{
Logger
.
e
(
"Can't extract zip file. detail : "
,
e
);
}
finally
{
// ダウンロードしていたファイルの削除
FileUtil
.
delete
(
outputFilePath
);
}
}
/**
* Reader用ContentDetailダウンロード
*
* @param contentId
* @param downloadUrl
* @throws MalformedURLException
* @throws InterruptedException
* @throws ABVException
*/
public
void
downloadContentDetail
(
long
contentId
,
String
downloadUrl
)
throws
MalformedURLException
,
InterruptedException
,
ABVException
{
String
outputFilePath
=
String
.
format
(
"%s/%s_%s.zip"
,
ABVEnvironment
.
getInstance
().
getContentDownloadsDirectoryPath
(),
ContentZipType
.
ContentDetail
,
contentId
);
Logger
.
d
(
TAG
,
"call api : getContentForAndroid [getContentInfoReader] "
+
downloadUrl
+
" outputFilePath="
+
outputFilePath
);
String
fileName
=
null
;
String
outputFileName
=
null
;
try
{
HttpFileDownloader
downloader
=
new
HttpFileDownloader
(
downloadUrl
,
null
,
outputFilePath
);
downloader
.
downloadSync
();
if
(
downloader
.
getState
()
!=
HttpDownloadState
.
finished
)
{
// finished以外は失敗とみなす(pausedの場合はgetErrorはnull)
throw
new
ABVException
(
ABVExceptionCode
.
C_E_CONTENT_1002
,
downloader
.
getError
());
}
String
contentPath
=
ABVEnvironment
.
getInstance
().
getContentDetailDirectoryPath
(
contentId
,
false
);
FileUtil
.
delete
(
contentPath
);
contentFileExtractor
.
extractZipFile
(
contentId
,
downloader
.
getOutputFileName
(),
contentPath
);
fileName
=
contentPath
;
outputFileName
=
downloader
.
getOutputFileName
();
contentLogic
.
saveContentDetail
(
contentId
,
contentPath
);
}
catch
(
Exception
e
)
{
Logger
.
e
(
TAG
,
"downloadContentDetailForReader failed"
,
e
);
if
(!
StringUtil
.
isNullOrWhiteSpace
(
fileName
))
{
FileUtil
.
delete
(
fileName
);
}
if
(!
StringUtil
.
isNullOrWhiteSpace
(
outputFileName
))
{
FileUtil
.
delete
(
outputFileName
);
}
}
}
}
ABVJE_BL/src/jp/agentec/abook/abv/bl/logic/ContractLogic.java
View file @
3e307bda
...
...
@@ -36,7 +36,6 @@ public class ContractLogic extends AbstractLogic {
private
static
final
String
True
=
"Y"
;
private
ServiceOptionDao
serviceOptionDao
=
AbstractDao
.
getDao
(
ServiceOptionDao
.
class
);
private
AcmsDao
acmsDao
=
AbstractDao
.
getDao
(
AcmsDao
.
class
);
private
ContractDao
contractDao
=
AbstractDao
.
getDao
(
ContractDao
.
class
);
/**
* {@link ContractLogic} クラスのインスタンスを初期化します。
...
...
@@ -77,31 +76,6 @@ public class ContractLogic extends AbstractLogic {
}
/**
* ABookMaker専用 。
* @throws Exception
* @since 1.0.0
*/
public
void
insertServiceOption
(
List
<
ServiceOptionDto
>
list
)
{
if
(
list
!=
null
&&
list
.
size
()
>
0
)
{
try
{
serviceOptionDao
.
beginTransaction
();
serviceOptionDao
.
deleteServiceOptions
();
serviceOptionDao
.
insertServiceOptions
(
list
);
serviceOptionDao
.
commit
();
cache
.
addServiceOptions
(
list
);
}
catch
(
Exception
e
)
{
serviceOptionDao
.
rollback
();
throw
new
RuntimeException
(
e
);
}
finally
{
}
}
}
/**
* 権限喪失,非公開,削除時のDL済コンテンツ強制削除するかどうかを示します。
* @return 権限喪失,非公開,削除時のDL済コンテンツ強制削除する場合、trueを返します。
* @since 1.0.0
...
...
@@ -448,80 +422,4 @@ public class ContractLogic extends AbstractLogic {
public
static
boolean
getBooleanValue
(
String
value
)
{
return
True
.
equals
(
value
);
}
public
ContractDto
getContractByContentId
(
long
contentId
)
{
ContentIdConvDto
contentIdConvDto
=
AbstractDao
.
getDao
(
ContentIdConvDao
.
class
).
getDto
(
contentId
);
if
(
contentIdConvDto
==
null
)
{
Logger
.
e
(
TAG
,
"contentId not found in ContentIdConv"
+
contentId
);
return
null
;
}
return
contractDao
.
getDto
(
contentIdConvDto
.
siteId
,
contentIdConvDto
.
contractId
);
}
/**
* 事業者のプッシュメッセージ設定を更新します<br>
* Repository Serverに更新情報を送信します
*
* @param repositoryFqdn
* @param registractionId
* @param contractDto
* @throws AcmsException
* @throws NetworkDisconnectedException
*/
public
void
updateReceivePushMessage
(
String
repositoryFqdn
,
String
registractionId
,
ContractDto
contractDto
)
throws
AcmsException
,
NetworkDisconnectedException
{
try
{
contractDao
.
beginTransaction
();
contractDto
.
userUpdateDate
=
DateTimeUtil
.
getCurrentDate
();
contractDao
.
update
(
contractDto
);
// プッシュメッセージを受信する事業者の情報を送信する
List
<
ContractDto
>
permitContractList
=
contractDao
.
findByReceivePushMessage
(
ReceivePushMessage
.
PERMIT
);
RepoClient
.
getInstance
().
sendReaderUserAccount
(
repositoryFqdn
,
registractionId
,
permitContractList
);
contractDao
.
commit
();
}
catch
(
AcmsException
e
)
{
contractDao
.
rollback
();
throw
e
;
}
catch
(
NetworkDisconnectedException
e
)
{
contractDao
.
rollback
();
throw
e
;
}
}
/**
* 事業者のプッシュメッセージ設定を更新します<br>
* Repository Serverに更新情報を送信します
*
* @param repositoryFqdn
* @param registractionId
* @param contractDtoList
* @throws AcmsException
* @throws NetworkDisconnectedException
*/
public
void
updateReceivePushMessage
(
String
repositoryFqdn
,
String
registractionId
,
List
<
ContractDto
>
contractDtoList
)
throws
AcmsException
,
NetworkDisconnectedException
{
try
{
ArrayList
<
ContractDto
>
permitContractList
=
new
ArrayList
<
ContractDto
>();
for
(
ContractDto
contractDto
:
contractDtoList
)
{
if
(
contractDto
.
receivePushMessage
==
ReceivePushMessage
.
PERMIT
)
{
permitContractList
.
add
(
contractDto
);
}
}
// プッシュメッセージを受信する事業者の情報を送信する
RepoClient
.
getInstance
().
sendReaderUserAccount
(
repositoryFqdn
,
registractionId
,
permitContractList
);
contractDao
.
beginTransaction
();
for
(
ContractDto
contractDto
:
contractDtoList
)
{
contractDto
.
userUpdateDate
=
DateTimeUtil
.
getCurrentDate
();
contractDao
.
update
(
contractDto
);
}
contractDao
.
commit
();
}
catch
(
AcmsException
e
)
{
contractDao
.
rollback
();
throw
e
;
}
catch
(
NetworkDisconnectedException
e
)
{
contractDao
.
rollback
();
throw
e
;
}
}
}
ABVJE_BL/src/jp/agentec/abook/abv/bl/logic/ProjectLogic.java
View file @
3e307bda
...
...
@@ -192,64 +192,10 @@ public class ProjectLogic extends AbstractLogic {
}
mPushMessageDao
.
delete
(
deleteProjectDto
.
projectId
);
mProjectDao
.
delete
(
deleteProjectDto
);
if
(
deleteProjectDto
.
contentId
!=
null
)
{
ContentDto
contentDto
=
mContentDao
.
getContent
(
deleteProjectDto
.
contentId
);
if
(
contentDto
!=
null
)
{
AbstractLogic
.
getLogic
(
ContentLogic
.
class
).
deleteContent
(
contentDto
,
true
);
}
}
String
projectTaskDirPath
=
ABVEnvironment
.
getInstance
().
getProjectDirFile
(
deleteProjectDto
.
projectId
);
FileUtil
.
delete
(
projectTaskDirPath
);
}
// for (ProjectDto serverProjectDto : serverProjects) {
//
//
// int localProjectIndex = localProjects.indexOf(serverProjectDto);
// if (localProjectIndex >= 0) {
// ProjectDto localDto = localProjects.get(localProjectIndex);
// if (!serverProjectDto.equalsLastEdit(localDto)) {
// serverProjectDto.needSyncFlg = true;
// mProjectContentDao.deleteProjectContent(serverProjectDto.projectId);
// for (ProjectContentDto projectContentDto : serverProjectDto.projectContentDtoList) {
// mProjectContentDao.insertProjectContent(projectContentDto);
// }
// mProjectDao.update(serverProjectDto);
// }
// localProjects.remove(localDto);
// } else {
// // プロジェクトの登録
// serverProjectDto.needSyncFlg = true;
// mProjectDao.insert(serverProjectDto);
// // 関連資料の登録
// for (ProjectContentDto projectContentDto : serverProjectDto.projectContentDtoList) {
// mProjectContentDao.insertProjectContent(projectContentDto);
// }
// }
//
// for (PushMessageDto dto : serverProjectDto.pushMessageList) {
// mPushMessageDao.insert(dto);
// }
// }
//
// // サーバーから取得したプロジェクト情報がローカルに存在しないので削除する
// for (ProjectDto localProjectDto : localProjects) {
// List<TaskDto> taskDtoList = mTaskDao.selectAllTaskByProjectId(localProjectDto.projectId);
// for(TaskDto taskDto : taskDtoList) {
// mTaskDao.delete(taskDto);
// }
// mPushMessageDao.delete(localProjectDto.projectId);
// mProjectDao.delete(localProjectDto);
// if (localProjectDto.contentId != null) {
// ContentDto contentDto = mContentDao.getContent(localProjectDto.contentId);
// if (contentDto != null) {
// AbstractLogic.getLogic(ContentLogic.class).deleteContent(contentDto, true);
// }
// }
// String projectTaskDirPath = ABVEnvironment.getInstance().getProjectDirFile(localProjectDto.projectId);
// FileUtil.delete(projectTaskDirPath);
// }
}
/**
...
...
ABVJE_BL/src/jp/agentec/abook/abv/bl/net/PanoServer.java
deleted
100644 → 0
View file @
32ec4e3a
package
jp
.
agentec
.
abook
.
abv
.
bl
.
net
;
import
java.io.IOException
;
import
java.util.List
;
import
java.util.Map
;
import
java.util.Timer
;
import
java.util.TimerTask
;
import
jp.agentec.abook.abv.bl.common.Callback
;
import
jp.agentec.abook.abv.bl.common.log.Logger
;
import
jp.agentec.adf.net.http.SimpleWebServer
;
/**
* 360°コンテンツ表示用WebServer
*
* Created by tsukada on 2016/02/12.
*/
public
class
PanoServer
extends
SimpleWebServer
{
private
static
final
java
.
lang
.
String
TAG
=
"PanoServer"
;
public
static
final
String
ABOOK
=
"abook"
;
public
static
final
String
MOVEPAGE
=
"/abookmovepage"
;
public
static
final
String
DETAILLOG
=
"/abookdetaillog"
;
public
static
final
String
CONTENTLINK
=
"/abookcontentlink"
;
public
static
final
String
NEXTCONTENT
=
"/abooknextcontent"
;
public
static
final
String
SEND_CUSTOM_LOG
=
"/abooksendcustomlog"
;
public
static
final
String
GETITS_OPEN_SHARE
=
"/abookopengetitsshare"
;
public
static
final
String
PING
=
"/ping"
;
public
static
final
String
CMD_GETITS_OPEN_SHARE
=
"opengetitsshare"
;
public
static
final
String
CMD_GETITS_CLOSE_SHARE
=
"closegetitsshare"
;
public
static
final
String
PARAM_LAST_PAGE_NUMBER
=
"lastPageNo"
;
public
static
final
String
PARAM_LAST_PAGE_START_DATE
=
"lastPageStartDate"
;
public
static
final
String
PARAM_READING_LOG_ID
=
"readingLogId"
;
public
static
final
String
PARAM_SHARE_URL
=
"shareUrl"
;
public
static
final
String
URI
=
"uri"
;
public
static
final
String
CLOSE
=
"CLOSE"
;
public
static
final
String
OK
=
"OK"
;
public
static
final
int
MAX_NO_ACCESS_TIME
=
60000
;
// pingがこれ以上の間来ない場合にコンテンツ閲覧終了とみなす(ミリ秒)
private
Callback
callback
;
private
Long
contentId
;
private
Thread
panoCheckThread
;
private
boolean
isCloseWaiting
=
false
;
public
PanoServer
(
String
host
,
int
port
,
Long
contentId
,
String
wwwroot
,
boolean
quiet
,
boolean
extAccess
,
List
<
String
>
userAgentList
,
Callback
callback
)
{
super
(
host
,
port
,
wwwroot
,
quiet
,
extAccess
,
userAgentList
);
this
.
contentId
=
contentId
;
this
.
callback
=
callback
;
panoCheckThread
=
new
Thread
()
{
// チェックスレッド(リクエストが一定時間以上ない場合に終了させる)
@Override
public
void
run
()
{
while
(
true
)
{
try
{
Thread
.
sleep
(
1000
);
}
catch
(
InterruptedException
e
)
{
break
;
}
if
(
System
.
currentTimeMillis
()
-
getLastAccess
()
>
PanoServer
.
MAX_NO_ACCESS_TIME
)
{
callStop
();
break
;
}
}
}
};
}
@Override
public
void
start
(
final
int
timeout
,
boolean
daemon
)
throws
IOException
{
super
.
start
(
timeout
,
daemon
);
panoCheckThread
.
start
();
}
@Override
protected
String
modifyUri
(
String
uri
)
throws
Exception
{
if
(!
uri
.
startsWith
(
"/"
+
contentId
+
"/"
))
{
Logger
.
e
(
TAG
,
"invalid uri. server="
+
getHostname
());
throw
new
Exception
(
"You are not allowed to access."
);
}
uri
=
uri
.
substring
((
"/"
+
contentId
).
length
());
return
super
.
modifyUri
(
uri
);
}
@Override
protected
Response
getResponse
(
String
uri
,
Map
<
String
,
String
>
params
,
Map
<
String
,
String
>
headers
,
IHTTPSession
session
)
{
if
(
isCloseWaiting
())
{
return
newFixedLengthResponse
(
CLOSE
);
}
else
if
(
uri
.
startsWith
(
PING
))
{
return
newFixedLengthResponse
(
OK
);
}
else
if
(
uri
.
startsWith
(
MOVEPAGE
)
||
uri
.
startsWith
(
DETAILLOG
)
||
uri
.
startsWith
(
CONTENTLINK
))
{
params
.
put
(
URI
,
uri
);
Object
ret
=
callback
.
callback
(
params
);
if
(
ret
!=
null
)
{
return
newFixedLengthResponse
(
ret
.
toString
());
}
return
newFixedLengthResponse
(
OK
);
}
else
{
return
super
.
getResponse
(
uri
,
params
,
headers
,
session
);
}
}
public
void
callStop
()
{
if
(!
isCloseWaiting
())
{
isCloseWaiting
=
true
;
callback
.
callback
(
contentId
);
new
Timer
().
schedule
(
new
TimerTask
()
{
@Override
public
void
run
()
{
PanoServer
.
this
.
stop
();
}
},
30000L
);
}
if
(
panoCheckThread
!=
null
)
{
panoCheckThread
.
interrupt
();
panoCheckThread
=
null
;
}
}
public
boolean
isCloseWaiting
()
{
return
isCloseWaiting
;
}
}
\ No newline at end of file
ABVJE_BL/src/jp/agentec/abook/abv/bl/repo/RepoClient.java
View file @
3e307bda
...
...
@@ -137,33 +137,6 @@ public class RepoClient {
AbstractDao
.
getDao
(
EnqueteDao
.
class
).
deleteUnsendEnquete
(
contentListStr
);
}
/**
* ShareKeyを解決し、コンテンツ情報・ダウンロード先を取得する
*
* @param repositoryFqdn
* @param shareKey
* @return
* @throws NetworkDisconnectedException
* @throws AcmsException
*/
public
ReaderContentJSON
resolveShareKey
(
String
repositoryFqdn
,
String
shareKey
,
String
password
)
throws
NetworkDisconnectedException
,
AcmsException
{
String
keyForReader
=
SecurityUtil
.
getEncryptString
(
ReaderConstant
.
SHARED_SECRET_REPO
,
""
+
System
.
currentTimeMillis
(),
true
);
String
url
=
"https://"
+
repositoryFqdn
+
"/repo/getDlUrl?key="
+
keyForReader
+
"&shareKey="
+
shareKey
+
(
StringUtil
.
isNullOrEmpty
(
password
)?
""
:
"&password="
+
password
)
+
"&language="
+
Locale
.
getDefault
().
getLanguage
()
+
"&checkOnly=n"
;
HttpResponse
response
=
AcmsClient
.
getInstance
(
ABVEnvironment
.
getInstance
().
networkAdapter
).
send
(
url
,
""
,
null
);
Logger
.
d
(
TAG
,
"resolveShareKey response=%s"
,
response
.
httpResponseBody
);
return
new
ReaderContentJSON
(
response
.
httpResponseBody
,
"http://"
+
repositoryFqdn
+
"/"
+
shareKey
);
}
public
ReaderContentJSON
resolveShareKeyCheckOnly
(
String
repositoryFqdn
,
String
shareKey
,
String
password
)
throws
NetworkDisconnectedException
,
AcmsException
{
String
keyForReader
=
SecurityUtil
.
getEncryptString
(
ReaderConstant
.
SHARED_SECRET_REPO
,
""
+
System
.
currentTimeMillis
(),
true
);
String
url
=
"https://"
+
repositoryFqdn
+
"/repo/getDlUrl?key="
+
keyForReader
+
"&shareKey="
+
shareKey
+
(
StringUtil
.
isNullOrEmpty
(
password
)?
""
:
"&password="
+
password
)
+
"&language="
+
Locale
.
getDefault
().
getLanguage
()
+
"&checkOnly=y"
;
HttpResponse
response
=
AcmsClient
.
getInstance
(
ABVEnvironment
.
getInstance
().
networkAdapter
).
send
(
url
,
""
,
null
);
Logger
.
d
(
TAG
,
"resolveShareKey response=%s"
,
response
.
httpResponseBody
);
return
new
ReaderContentJSON
(
response
.
httpResponseBody
,
"http://"
+
repositoryFqdn
+
"/"
+
shareKey
);
}
public
AcmsCommonJSON
sendReaderUserAccount
(
String
repositoryFqdn
,
String
registractionId
,
List
<
ContractDto
>
permitContractList
)
throws
AcmsException
,
NetworkDisconnectedException
{
// 送信
StringBuilder
sb
=
new
StringBuilder
();
...
...
ABVJE_BL/src/jp/agentec/adf/net/http/SimpleWebServer.java
deleted
100644 → 0
View file @
32ec4e3a
package
jp
.
agentec
.
adf
.
net
.
http
;
import
java.io.File
;
import
java.io.FileInputStream
;
import
java.io.FileNotFoundException
;
import
java.io.IOException
;
import
java.util.Collections
;
import
java.util.List
;
import
java.util.Map
;
import
java.util.Map.Entry
;
import
jp.agentec.abook.abv.bl.common.log.Logger
;
import
fi.iki.elonen.NanoHTTPD
;
import
fi.iki.elonen.NanoHTTPD.Response.IStatus
;
public
class
SimpleWebServer
extends
NanoHTTPD
{
private
static
final
String
TAG
=
"SimpleWebServer"
;
private
final
boolean
quiet
;
private
boolean
extAccess
;
private
List
<
String
>
userAgentList
;
protected
File
rootDir
;
private
String
firstUserAgent
;
public
SimpleWebServer
(
String
host
,
int
port
,
String
wwwroot
,
boolean
quiet
,
boolean
extAccess
,
List
<
String
>
userAgentList
)
{
super
(
host
,
port
);
this
.
quiet
=
quiet
;
this
.
extAccess
=
extAccess
;
this
.
userAgentList
=
userAgentList
;
this
.
rootDir
=
new
File
(
wwwroot
);
}
protected
Response
getForbiddenResponse
(
String
s
)
{
return
newFixedLengthResponse
(
Response
.
Status
.
FORBIDDEN
,
NanoHTTPD
.
MIME_PLAINTEXT
,
"FORBIDDEN: "
+
s
);
}
protected
Response
getInternalErrorResponse
(
String
s
)
{
return
newFixedLengthResponse
(
Response
.
Status
.
INTERNAL_ERROR
,
NanoHTTPD
.
MIME_PLAINTEXT
,
"INTERNAL ERROR: "
+
s
);
}
protected
Response
getNotFoundResponse
()
{
return
newFixedLengthResponse
(
Response
.
Status
.
NOT_FOUND
,
NanoHTTPD
.
MIME_PLAINTEXT
,
"Error 404, file not found."
);
}
public
static
Response
newFixedLengthResponse
(
IStatus
status
,
String
mimeType
,
String
message
)
{
Response
response
=
NanoHTTPD
.
newFixedLengthResponse
(
status
,
mimeType
,
message
);
response
.
addHeader
(
"Accept-Ranges"
,
"bytes"
);
return
response
;
}
@Override
public
void
stop
()
{
Logger
.
d
(
"Simple WebServer stop. port=%s rootdir=%s"
,
""
+
getListeningPort
(),
rootDir
);
onStop
();
super
.
stop
();
}
protected
void
onStop
()
{
}
@Override
public
Response
serve
(
IHTTPSession
session
)
{
Map
<
String
,
String
>
headers
=
session
.
getHeaders
();
String
uri
=
session
.
getUri
();
Method
method
=
session
.
getMethod
();
Map
<
String
,
String
>
params
=
session
.
getParms
();
logRequest
(
uri
,
method
,
params
,
headers
);
if
(!
checkClient
(
uri
,
headers
))
{
return
getForbiddenResponse
(
"You are not authorized to access."
);
}
try
{
uri
=
modifyUri
(
uri
);
}
catch
(
Exception
e
)
{
return
getForbiddenResponse
(
e
.
getMessage
());
}
Response
response
=
getResponse
(
uri
,
params
,
headers
,
session
);
Logger
.
d
(
TAG
,
"response status=%s"
,
response
.
getStatus
());
return
response
;
}
protected
void
logRequest
(
String
uri
,
Method
method
,
Map
<
String
,
String
>
params
,
Map
<
String
,
String
>
headers
)
{
if
(
uri
.
contains
(
"/ping/"
))
{
Logger
.
v
(
TAG
,
"Method:"
+
method
.
name
()
+
" Uri: "
+
uri
);
}
else
{
Logger
.
i
(
TAG
,
"Method:"
+
method
.
name
()
+
" Uri: "
+
uri
);
}
if
(!
quiet
)
{
for
(
Entry
<
String
,
String
>
e
:
headers
.
entrySet
())
{
Logger
.
d
(
TAG
,
"[Header] %s: %s"
,
e
.
getKey
(),
e
.
getValue
());
}
for
(
Entry
<
String
,
String
>
e
:
params
.
entrySet
())
{
Logger
.
d
(
TAG
,
"[Param] %s: %s"
,
e
.
getKey
(),
e
.
getValue
());
}
}
}
protected
Response
getResponse
(
String
uri
,
Map
<
String
,
String
>
param
,
Map
<
String
,
String
>
headers
,
IHTTPSession
session
)
{
if
(
uri
.
endsWith
(
".mp4"
))
{
return
respond
(
Collections
.
unmodifiableMap
(
headers
),
session
,
uri
);
}
else
{
return
respond
(
session
,
uri
);
}
}
protected
boolean
checkClient
(
String
uri
,
Map
<
String
,
String
>
headers
)
{
if
(!
extAccess
)
{
String
httpClientIp
=
headers
.
get
(
"http-client-ip"
);
if
(!
getHostname
().
equals
(
httpClientIp
))
{
Logger
.
e
(
TAG
,
"invalid http-client-ip. server="
+
getHostname
()
+
" client="
+
httpClientIp
);
return
false
;
}
String
remoteAddr
=
headers
.
get
(
"remote-addr"
);
if
(!
getHostname
().
equals
(
remoteAddr
))
{
Logger
.
e
(
TAG
,
"invalid remote-addr. server="
+
getHostname
()
+
" client="
+
remoteAddr
);
return
false
;
}
}
if
(
userAgentList
!=
null
)
{
String
checkedUserAgent
=
headers
.
get
(
"user-agent"
);
if
(
firstUserAgent
==
null
)
{
firstUserAgent
=
checkedUserAgent
;
}
for
(
String
userAgent
:
userAgentList
)
{
// 動画の場合Chromeが来ないのでチェック無効: ex. Sony401SO Build/23.1.F.0.351 stagefright/1.2 (Linux;Android 5.0.2)
if
(
checkedUserAgent
==
null
||
!
isMovie
(
uri
)
&&
(!
checkedUserAgent
.
contains
(
userAgent
)
||
!
firstUserAgent
.
equals
(
checkedUserAgent
)))
{
Logger
.
e
(
TAG
,
"invalid user-agent. required="
+
userAgent
+
" client="
+
checkedUserAgent
);
return
false
;
}
}
}
return
true
;
}
private
boolean
isMovie
(
String
uri
)
{
String
s
=
uri
.
toLowerCase
();
return
s
.
endsWith
(
".mp4"
)
||
s
.
endsWith
(
".mov"
)
||
s
.
endsWith
(
".m4v"
);
}
protected
String
modifyUri
(
String
uri
)
throws
Exception
{
if
(
uri
.
endsWith
(
"/"
))
{
uri
=
uri
+
"index.html"
;
}
return
uri
;
}
private
Response
respond
(
IHTTPSession
session
,
String
uri
)
{
try
{
String
path
=
rootDir
+
uri
;
Logger
.
d
(
TAG
,
"Path: %s"
,
path
);
String
suf
=
path
.
contains
(
"."
)?
path
.
substring
(
path
.
lastIndexOf
(
"."
)
+
1
):
""
;
String
mime
=
NanoHTTPD
.
MIME_TYPES
.
get
(
suf
);
Logger
.
d
(
TAG
,
"mime: %s"
,
mime
);
FileInputStream
fis
=
new
FileInputStream
(
path
);
return
newFixedLengthResponse
(
Response
.
Status
.
OK
,
mime
,
fis
,
fis
.
available
());
}
catch
(
IOException
e
)
{
Logger
.
e
(
TAG
,
"serve failed. "
+
uri
,
e
);
return
newFixedLengthResponse
(
Response
.
Status
.
NOT_FOUND
,
NanoHTTPD
.
MIME_PLAINTEXT
,
"Not Found"
);
}
catch
(
Exception
e
)
{
Logger
.
e
(
TAG
,
"serve failed. "
+
uri
,
e
);
return
newFixedLengthResponse
(
Response
.
Status
.
INTERNAL_ERROR
,
NanoHTTPD
.
MIME_PLAINTEXT
,
"Internal Server Error"
);
}
}
private
Response
respond
(
Map
<
String
,
String
>
headers
,
IHTTPSession
session
,
String
uri
)
{
// Remove URL arguments
uri
=
uri
.
trim
().
replace
(
File
.
separatorChar
,
'/'
);
if
(
uri
.
indexOf
(
'?'
)
>=
0
)
{
uri
=
uri
.
substring
(
0
,
uri
.
indexOf
(
'?'
));
}
// Prohibit getting out of current directory
if
(
uri
.
contains
(
"../"
))
{
return
getForbiddenResponse
(
"Won't serve ../ for security reasons."
);
}
// Browsers get confused without '/' after the directory, send a
// redirect.
if
(
uri
.
endsWith
(
"/"
))
{
uri
=
uri
+
"index.html"
;
}
File
f
=
new
File
(
rootDir
,
uri
);
if
(!
f
.
exists
())
{
return
getNotFoundResponse
();
}
String
mimeTypeForFile
=
getMimeTypeForFile
(
uri
);
Response
response
=
serveFile
(
uri
,
headers
,
f
,
mimeTypeForFile
);
return
response
!=
null
?
response
:
getNotFoundResponse
();
}
/**
* Serves file from homeDir and its' subdirectories (only). Uses only URI,
* ignores all headers and HTTP parameters.
*/
Response
serveFile
(
String
uri
,
Map
<
String
,
String
>
header
,
File
file
,
String
mime
)
{
Response
res
;
try
{
// Calculate etag
String
etag
=
Integer
.
toHexString
((
file
.
getAbsolutePath
()
+
file
.
lastModified
()
+
""
+
file
.
length
()).
hashCode
());
// Support (simple) skipping:
long
startFrom
=
0
;
long
endAt
=
-
1
;
String
range
=
header
.
get
(
"range"
);
if
(
range
!=
null
)
{
if
(
range
.
startsWith
(
"bytes="
))
{
range
=
range
.
substring
(
"bytes="
.
length
());
int
minus
=
range
.
indexOf
(
'-'
);
try
{
if
(
minus
>
0
)
{
startFrom
=
Long
.
parseLong
(
range
.
substring
(
0
,
minus
));
endAt
=
Long
.
parseLong
(
range
.
substring
(
minus
+
1
));
}
}
catch
(
NumberFormatException
ignored
)
{
}
}
}
// get if-range header. If present, it must match etag or else we
// should ignore the range request
String
ifRange
=
header
.
get
(
"if-range"
);
boolean
headerIfRangeMissingOrMatching
=
(
ifRange
==
null
||
etag
.
equals
(
ifRange
));
String
ifNoneMatch
=
header
.
get
(
"if-none-match"
);
boolean
headerIfNoneMatchPresentAndMatching
=
ifNoneMatch
!=
null
&&
(
"*"
.
equals
(
ifNoneMatch
)
||
ifNoneMatch
.
equals
(
etag
));
// Change return code and add Content-Range header when skipping is
// requested
long
fileLen
=
file
.
length
();
if
(
headerIfRangeMissingOrMatching
&&
range
!=
null
&&
startFrom
>=
0
&&
startFrom
<
fileLen
)
{
// range request that matches current etag
// and the startFrom of the range is satisfiable
if
(
headerIfNoneMatchPresentAndMatching
)
{
// range request that matches current etag
// and the startFrom of the range is satisfiable
// would return range from file
// respond with not-modified
res
=
newFixedLengthResponse
(
Response
.
Status
.
NOT_MODIFIED
,
mime
,
""
);
res
.
addHeader
(
"ETag"
,
etag
);
}
else
{
if
(
endAt
<
0
)
{
endAt
=
fileLen
-
1
;
}
long
newLen
=
endAt
-
startFrom
+
1
;
if
(
newLen
<
0
)
{
newLen
=
0
;
}
FileInputStream
fis
=
new
FileInputStream
(
file
);
fis
.
skip
(
startFrom
);
res
=
newFixedLengthResponse
(
Response
.
Status
.
PARTIAL_CONTENT
,
mime
,
fis
,
newLen
);
res
.
addHeader
(
"Accept-Ranges"
,
"bytes"
);
res
.
addHeader
(
"Content-Length"
,
""
+
newLen
);
res
.
addHeader
(
"Content-Range"
,
"bytes "
+
startFrom
+
"-"
+
endAt
+
"/"
+
fileLen
);
res
.
addHeader
(
"ETag"
,
etag
);
}
}
else
{
if
(
headerIfRangeMissingOrMatching
&&
range
!=
null
&&
startFrom
>=
fileLen
)
{
// return the size of the file
// 4xx responses are not trumped by if-none-match
res
=
newFixedLengthResponse
(
Response
.
Status
.
RANGE_NOT_SATISFIABLE
,
NanoHTTPD
.
MIME_PLAINTEXT
,
""
);
res
.
addHeader
(
"Content-Range"
,
"bytes */"
+
fileLen
);
res
.
addHeader
(
"ETag"
,
etag
);
}
else
if
(
range
==
null
&&
headerIfNoneMatchPresentAndMatching
)
{
// full-file-fetch request
// would return entire file
// respond with not-modified
res
=
newFixedLengthResponse
(
Response
.
Status
.
NOT_MODIFIED
,
mime
,
""
);
res
.
addHeader
(
"ETag"
,
etag
);
}
else
if
(!
headerIfRangeMissingOrMatching
&&
headerIfNoneMatchPresentAndMatching
)
{
// range request that doesn't match current etag
// would return entire (different) file
// respond with not-modified
res
=
newFixedLengthResponse
(
Response
.
Status
.
NOT_MODIFIED
,
mime
,
""
);
res
.
addHeader
(
"ETag"
,
etag
);
}
else
{
// supply the file
res
=
newFixedFileResponse
(
file
,
mime
);
res
.
addHeader
(
"Content-Length"
,
""
+
fileLen
);
res
.
addHeader
(
"ETag"
,
etag
);
}
}
}
catch
(
IOException
ioe
)
{
res
=
getForbiddenResponse
(
"Reading file failed."
);
}
return
res
;
}
private
Response
newFixedFileResponse
(
File
file
,
String
mime
)
throws
FileNotFoundException
{
Response
res
;
res
=
newFixedLengthResponse
(
Response
.
Status
.
OK
,
mime
,
new
FileInputStream
(
file
),
(
int
)
file
.
length
());
res
.
addHeader
(
"Accept-Ranges"
,
"bytes"
);
return
res
;
}
}
ABVJE_Launcher_Android/AndroidManifest.xml
View file @
3e307bda
...
...
@@ -56,9 +56,6 @@
</intent-filter>
</receiver>
<service
android:name=
"jp.agentec.abook.abv.cl.beacon.BeaconIntentService"
/>
<service
android:name=
"jp.agentec.abook.abv.cl.beacon.BeaconPeriodicService"
/>
<service
android:name=
"jp.agentec.abook.abv.cl.push.ABVFcmListenerService"
>
<intent-filter>
<action
android:name=
"com.google.firebase.MESSAGING_EVENT"
></action>
...
...
@@ -166,11 +163,6 @@
android:label=
"LoginActivity"
android:theme=
"@android:style/Theme.NoTitleBar.Fullscreen"
/>
<activity
android:name=
"jp.agentec.abook.abv.ui.home.activity.ContentDetailViewActivity"
android:configChanges=
"keyboardHidden|orientation|screenSize"
android:label=
"ContentDetailViewActivity"
android:theme=
"@style/Theme_Contentdetailview"
/>
<activity
android:name=
"jp.agentec.abook.abv.ui.viewer.activity.ContentViewActivity"
android:configChanges=
"keyboardHidden|orientation|screenSize"
android:hardwareAccelerated=
"false"
...
...
@@ -206,11 +198,6 @@
android:label=
"LoginPasswordChangeActivity"
android:theme=
"@android:style/Theme.NoTitleBar.Fullscreen"
>
</activity>
<activity
android:name=
"jp.agentec.abook.abv.ui.viewer.activity.PanoViewActivity"
android:configChanges=
"keyboardHidden|orientation|screenSize"
android:theme=
"@android:style/Theme.NoTitleBar.Fullscreen"
>
</activity>
<activity
android:name=
"jp.agentec.abook.abv.ui.home.activity.ABookSettingActivity"
android:theme=
"@android:style/Theme.NoTitleBar"
/>
<activity
android:name=
"jp.agentec.abook.abv.ui.home.activity.ChangePasswordActivity"
android:theme=
"@android:style/Theme.NoTitleBar.Fullscreen"
/>
<activity
android:name=
"jp.agentec.abook.abv.ui.home.activity.ChangePasswordActivityDialog"
android:theme=
"@style/Theme.MyTheme.ModalDialog"
/>
...
...
ABVJE_Res_Default_Android/build.gradle
View file @
3e307bda
...
...
@@ -40,7 +40,6 @@ android {
resValue
(
"bool"
,
"follow_service_option"
,
"${follow_service_option}"
)
resValue
(
"bool"
,
"is_check_invalid_passward_limit"
,
"${is_check_invalid_passward_limit}"
)
resValue
(
"bool"
,
"repeat_default"
,
"${repeat_default}"
)
resValue
(
"integer"
,
"pano_web_server_port"
,
"${pano_web_server_port}"
)
resValue
(
"string"
,
"version_name"
,
"${version_name}"
)
resValue
(
"string"
,
"release_date"
,
"${release_date}"
)
resValue
(
"string"
,
"copy_right"
,
"${copy_right}"
)
...
...
@@ -53,9 +52,6 @@ android {
resValue
(
"integer"
,
"app_log_retention"
,
"${app_log_retention}"
)
resValue
(
"bool"
,
"hprof"
,
"${hprof}"
)
resValue
(
"string"
,
"repository_fqdn"
,
"${repository_fqdn}"
)
resValue
(
"string"
,
"default_content_key"
,
"${default_content_key}"
)
resValue
(
"array"
,
"Beacon_UUID"
,
"${Beacon_UUID}"
)
resValue
(
"integer"
,
"beacon_scan_interval"
,
"${beacon_scan_interval}"
)
//abvFunctionOptions
resValue
(
"integer"
,
"login_mode"
,
"${login_mode}"
)
...
...
ABVJE_UI_Android/build.gradle
View file @
3e307bda
...
...
@@ -15,7 +15,6 @@ dependencies {
api
'com.google.firebase:firebase-messaging:11.4.0'
implementation
'commons-codec:commons-codec:1.10'
implementation
'org.xerial:sqlite-jdbc:3.7.2'
implementation
'net.lingala.zip4j:zip4j:1.3.2'
implementation
'com.google.guava:guava:18.0'
implementation
'com.journeyapps:zxing-android-embedded:3.0.1@aar'
...
...
ABVJE_UI_Android/src/jp/agentec/abook/abv/cl/beacon/Beacon.java
deleted
100644 → 0
View file @
32ec4e3a
package
jp
.
agentec
.
abook
.
abv
.
cl
.
beacon
;
public
class
Beacon
{
public
String
uuid
;
public
String
major
;
public
String
minor
;
public
int
rssi
;
public
long
receiveTime
;
public
boolean
isSameBeacon
(
Beacon
beacon
)
{
return
beacon
.
uuid
.
equals
(
uuid
)
&&
beacon
.
major
.
equals
(
major
)
&&
beacon
.
minor
.
equals
(
minor
);
}
public
boolean
isNear
(){
// 0~5m
return
rssi
>
-
70
;
}
}
\ No newline at end of file
ABVJE_UI_Android/src/jp/agentec/abook/abv/cl/beacon/BeaconBroadcastReceiver.java
deleted
100644 → 0
View file @
32ec4e3a
package
jp
.
agentec
.
abook
.
abv
.
cl
.
beacon
;
import
jp.agentec.abook.abv.cl.util.AppUtil
;
import
jp.agentec.abook.abv.ui.common.appinfo.AppDefType
;
import
jp.agentec.abook.abv.ui.common.appinfo.AppDefType.BeaconKey
;
import
android.content.ComponentName
;
import
android.content.Context
;
import
android.content.Intent
;
import
android.support.v4.content.WakefulBroadcastReceiver
;
public
class
BeaconBroadcastReceiver
extends
WakefulBroadcastReceiver
{
@Override
public
void
onReceive
(
Context
context
,
Intent
intent
)
{
if
(
AppUtil
.
isAppForground
(
context
))
{
Intent
i
=
new
Intent
(
AppDefType
.
Intent
.
Action_Receive_Message
);
i
.
putExtra
(
BeaconKey
.
major
,
intent
.
getStringExtra
(
BeaconKey
.
major
));
i
.
putExtra
(
BeaconKey
.
minor
,
intent
.
getStringExtra
(
BeaconKey
.
minor
));
context
.
sendBroadcast
(
i
);
}
else
{
ComponentName
comp
=
new
ComponentName
(
context
.
getPackageName
(),
BeaconIntentService
.
class
.
getName
());
startWakefulService
(
context
,
(
intent
.
setComponent
(
comp
)));
}
}
}
ABVJE_UI_Android/src/jp/agentec/abook/abv/cl/beacon/BeaconIntentService.java
deleted
100644 → 0
View file @
32ec4e3a
package
jp
.
agentec
.
abook
.
abv
.
cl
.
beacon
;
import
jp.agentec.abook.abv.launcher.android.R
;
import
jp.agentec.abook.abv.ui.common.activity.ABVActivity
;
import
jp.agentec.abook.abv.ui.common.appinfo.AppDefType.BeaconKey
;
import
android.annotation.TargetApi
;
import
android.app.IntentService
;
import
android.app.Notification
;
import
android.app.NotificationManager
;
import
android.app.PendingIntent
;
import
android.content.Context
;
import
android.content.Intent
;
import
android.net.Uri
;
import
android.os.Build
;
import
android.os.Build.VERSION_CODES
;
import
android.os.Bundle
;
import
android.support.v4.app.NotificationCompat
;
import
android.support.v4.content.WakefulBroadcastReceiver
;
public
class
BeaconIntentService
extends
IntentService
{
private
NotificationManager
mNotificationManager
;
NotificationCompat
.
Builder
builder
;
private
static
int
mNotificationConnect
=
0
;
public
BeaconIntentService
()
{
super
(
"BeaconIntentService"
);
}
@Override
protected
void
onHandleIntent
(
Intent
intent
)
{
Bundle
extras
=
intent
.
getExtras
();
if
(!
extras
.
isEmpty
())
{
sendNotification
(
extras
.
getString
(
BeaconKey
.
major
),
extras
.
getString
(
BeaconKey
.
minor
));
}
WakefulBroadcastReceiver
.
completeWakefulIntent
(
intent
);
}
@TargetApi
(
Build
.
VERSION_CODES
.
JELLY_BEAN
)
private
void
sendNotification
(
String
major
,
String
minor
)
{
mNotificationManager
=
(
NotificationManager
)
this
.
getSystemService
(
Context
.
NOTIFICATION_SERVICE
);
Notification
.
Builder
nb
=
new
Notification
.
Builder
(
this
);
nb
.
setDefaults
(
Notification
.
DEFAULT_ALL
);
nb
.
setSmallIcon
(
R
.
drawable
.
icon
);
nb
.
setWhen
(
System
.
currentTimeMillis
());
nb
.
setAutoCancel
(
true
);
Intent
intent
=
new
Intent
(
Intent
.
ACTION_VIEW
);
String
downloadUrl
=
getDownloadUrl
(
major
,
minor
);
Uri
.
Builder
uriBuilder
=
new
Uri
.
Builder
();
uriBuilder
.
scheme
(
getString
(
R
.
string
.
scheme_url
));
uriBuilder
.
authority
(
"abook"
);
uriBuilder
.
appendQueryParameter
(
ABVActivity
.
URL
,
downloadUrl
);
uriBuilder
.
appendQueryParameter
(
ABVActivity
.
PASSWORD
,
""
+
0
);
intent
.
setData
(
uriBuilder
.
build
());
PendingIntent
pi
=
PendingIntent
.
getActivity
(
this
,
0
,
intent
,
0
);
nb
.
setContentTitle
(
getString
(
R
.
string
.
app_name
));
nb
.
setContentText
(
getString
(
R
.
string
.
receive_message
)+
"("
+
major
+
minor
+
")"
);
nb
.
setContentIntent
(
pi
);
Notification
n
;
if
(
android
.
os
.
Build
.
VERSION
.
SDK_INT
<
VERSION_CODES
.
JELLY_BEAN_MR1
)
{
//noinspection deprecation(API16から非推奨になった無視)
n
=
nb
.
getNotification
();
}
else
{
n
=
nb
.
build
();
}
n
.
flags
|=
Notification
.
FLAG_SHOW_LIGHTS
;
n
.
flags
|=
Notification
.
FLAG_AUTO_CANCEL
;
// Notification ID 증가 0~999 까지 순환
mNotificationConnect
=
(
mNotificationConnect
+
1
)
%
1000
;
mNotificationManager
.
notify
(
mNotificationConnect
,
n
);
}
// テキスト内からダウンロードURLを検索して返します
private
String
getDownloadUrl
(
String
major
,
String
minor
)
{
return
"http://"
+
getString
(
R
.
string
.
repository_fqdn
)
+
"/"
+
major
+
minor
;
}
}
ABVJE_UI_Android/src/jp/agentec/abook/abv/cl/beacon/BeaconPeriodicService.java
deleted
100644 → 0
View file @
32ec4e3a
package
jp
.
agentec
.
abook
.
abv
.
cl
.
beacon
;
import
java.util.ArrayList
;
import
java.util.List
;
import
jp.agentec.abook.abv.bl.common.CommonExecutor
;
import
jp.agentec.abook.abv.bl.common.log.Logger
;
import
jp.agentec.abook.abv.bl.data.dao.AbstractDao
;
import
jp.agentec.abook.abv.bl.data.dao.BeaconHistoryDao
;
import
jp.agentec.abook.abv.bl.dto.BeaconHistoryDto
;
import
jp.agentec.abook.abv.launcher.android.R
;
import
jp.agentec.abook.abv.ui.common.appinfo.AppDefType
;
import
jp.agentec.abook.abv.ui.home.activity.SplashScreenActivity
;
import
android.annotation.TargetApi
;
import
android.app.ActivityManager
;
import
android.app.ActivityManager.RunningTaskInfo
;
import
android.app.AlarmManager
;
import
android.app.PendingIntent
;
import
android.app.Service
;
import
android.bluetooth.BluetoothAdapter
;
import
android.bluetooth.BluetoothDevice
;
import
android.bluetooth.BluetoothManager
;
import
android.content.ComponentName
;
import
android.content.Context
;
import
android.content.Intent
;
import
android.os.Binder
;
import
android.os.Build
;
import
android.os.IBinder
;
import
android.os.Parcel
;
import
android.os.RemoteException
;
public
class
BeaconPeriodicService
extends
Service
{
private
final
String
TAG
=
"BeaconPeriodicService"
;
private
List
<
Beacon
>
beaconList
;
private
List
<
Beacon
>
sentBeaconList
=
new
ArrayList
<>();
private
BluetoothAdapter
mBluetoothAdapter
;
private
BluetoothAdapter
.
LeScanCallback
mLeScanCallback
;
public
static
BeaconPeriodicService
activeService
;
private
int
containInterval
=
1000
*
20
;
protected
void
execTask
()
{
activeService
=
this
;
iBeaconScan
();
}
/**
* 次回の実行計画を立てる。
*/
protected
void
makeNextPlan
()
{
this
.
scheduleNextTime
();
}
protected
final
IBinder
binder
=
new
Binder
()
{
@Override
protected
boolean
onTransact
(
int
code
,
Parcel
data
,
Parcel
reply
,
int
flags
)
throws
RemoteException
{
return
super
.
onTransact
(
code
,
data
,
reply
,
flags
);
}
};
@Override
public
IBinder
onBind
(
Intent
intent
)
{
return
binder
;
}
@Override
public
int
onStartCommand
(
Intent
intent
,
int
flags
,
int
startId
)
{
init
();
execTask
();
return
START_STICKY
;
}
/**
* サービスの次回の起動を予約
*/
public
void
scheduleNextTime
()
{
long
now
=
System
.
currentTimeMillis
();
PendingIntent
alarmSender
=
PendingIntent
.
getService
(
this
,
0
,
new
Intent
(
this
,
this
.
getClass
()),
0
);
AlarmManager
am
=
(
AlarmManager
)
this
.
getSystemService
(
Context
.
ALARM_SERVICE
);
am
.
set
(
AlarmManager
.
RTC
,
now
+
getResources
().
getInteger
(
R
.
integer
.
beacon_scan_interval
),
alarmSender
);
}
/**
* サービスの定期実行を解除し,サービスを停止
*/
public
void
stopResident
(
Context
context
)
{
Intent
intent
=
new
Intent
(
context
,
this
.
getClass
());
PendingIntent
pendingIntent
=
PendingIntent
.
getService
(
context
,
0
,
intent
,
PendingIntent
.
FLAG_UPDATE_CURRENT
);
AlarmManager
alarmManager
=
(
AlarmManager
)
context
.
getSystemService
(
Context
.
ALARM_SERVICE
);
alarmManager
.
cancel
(
pendingIntent
);
stopSelf
();
}
@Override
public
void
onDestroy
()
{
super
.
onDestroy
();
}
@TargetApi
(
Build
.
VERSION_CODES
.
JELLY_BEAN_MR2
)
private
synchronized
void
iBeaconScan
()
{
final
BluetoothManager
bluetoothManager
=
(
BluetoothManager
)
getApplicationContext
().
getSystemService
(
Context
.
BLUETOOTH_SERVICE
);
mBluetoothAdapter
=
bluetoothManager
.
getAdapter
();
if
(
mBluetoothAdapter
!=
null
&&
mBluetoothAdapter
.
isEnabled
())
{
CommonExecutor
.
execute
(
new
Runnable
()
{
@Override
public
void
run
()
{
leScan
();
}
});
}
else
{
makeNextPlan
();
}
}
private
String
IntToHex
(
int
Value
)
{
char
HEX2
[]
=
{
Character
.
forDigit
((
Value
>>
4
)
&
0x0F
,
16
),
Character
.
forDigit
(
Value
&
0x0F
,
16
)
};
return
new
String
(
HEX2
);
}
@TargetApi
(
Build
.
VERSION_CODES
.
JELLY_BEAN_MR2
)
private
void
init
(){
mLeScanCallback
=
new
BluetoothAdapter
.
LeScanCallback
()
{
@Override
public
void
onLeScan
(
BluetoothDevice
device
,
int
rssi
,
byte
[]
scanRecord
)
{
if
(
scanRecord
.
length
>
30
)
{
if
((
scanRecord
[
5
]
==
(
byte
)
0x4c
)
&&
(
scanRecord
[
6
]
==
(
byte
)
0x00
)
&&
(
scanRecord
[
7
]
==
(
byte
)
0x02
)
&&
(
scanRecord
[
8
]
==
(
byte
)
0x15
))
{
String
uuid
=
IntToHex
(
scanRecord
[
9
]
&
0xff
)
+
IntToHex
(
scanRecord
[
10
]
&
0xff
)
+
IntToHex
(
scanRecord
[
11
]
&
0xff
)
+
IntToHex
(
scanRecord
[
12
]
&
0xff
)
+
"-"
+
IntToHex
(
scanRecord
[
13
]
&
0xff
)
+
IntToHex
(
scanRecord
[
14
]
&
0xff
)
+
"-"
+
IntToHex
(
scanRecord
[
15
]
&
0xff
)
+
IntToHex
(
scanRecord
[
16
]
&
0xff
)
+
"-"
+
IntToHex
(
scanRecord
[
17
]
&
0xff
)
+
IntToHex
(
scanRecord
[
18
]
&
0xff
)
+
"-"
+
IntToHex
(
scanRecord
[
19
]
&
0xff
)
+
IntToHex
(
scanRecord
[
20
]
&
0xff
)
+
IntToHex
(
scanRecord
[
21
]
&
0xff
)
+
IntToHex
(
scanRecord
[
22
]
&
0xff
)
+
IntToHex
(
scanRecord
[
23
]
&
0xff
)
+
IntToHex
(
scanRecord
[
24
]
&
0xff
);
if
(!
isAvailableServiceUUID
(
uuid
)){
return
;
}
String
major
=
IntToHex
(
scanRecord
[
25
]
&
0xff
)
+
IntToHex
(
scanRecord
[
26
]
&
0xff
);
String
minor
=
IntToHex
(
scanRecord
[
27
]
&
0xff
)
+
IntToHex
(
scanRecord
[
28
]
&
0xff
);
Beacon
beacon
=
new
Beacon
();
beacon
.
uuid
=
uuid
;
beacon
.
major
=
major
;
beacon
.
minor
=
minor
;
beacon
.
rssi
=
rssi
;
beacon
.
receiveTime
=
System
.
currentTimeMillis
();
Logger
.
d
(
TAG
,
"Beacon received UUID:"
+
beacon
.
uuid
+
", Major:"
+
beacon
.
major
+
", Minor: "
+
beacon
.
minor
+
", Rssi: "
+
beacon
.
rssi
);
if
(!
isBeaconListContains
(
beaconList
,
beacon
)
&&
beacon
.
isNear
()){
beaconList
.
add
(
beacon
);
}
}
}
}
};
}
private
boolean
isBeaconListContains
(
List
<
Beacon
>
beaconList
,
Beacon
beacon
){
for
(
Beacon
b
:
beaconList
)
{
if
(
beacon
.
isSameBeacon
(
b
))
{
return
true
;
}
}
return
false
;
}
@TargetApi
(
Build
.
VERSION_CODES
.
JELLY_BEAN_MR2
)
private
synchronized
void
leScan
()
{
beaconList
=
new
ArrayList
<>();
// TODO later UUIDのフィルタリングがうまく動作しない。
Logger
.
d
(
TAG
,
"startLeScan"
);
//noinspection deprecation(API21から非推奨になった、無視)
mBluetoothAdapter
.
startLeScan
(
mLeScanCallback
);
try
{
Thread
.
sleep
(
500
);
}
catch
(
InterruptedException
e
)
{
//ignore
}
Logger
.
d
(
TAG
,
"stoptLeScan"
);
//noinspection deprecation(API21から非推奨になった、無視)
mBluetoothAdapter
.
stopLeScan
(
mLeScanCallback
);
sendBeaconBroadcast
();
makeNextPlan
();
}
private
void
sendBeaconBroadcast
()
{
if
(
isSplashScreenForground
(
this
)){
return
;
}
Beacon
targetBeacon
=
getNearestBeacon
();
if
(
targetBeacon
!=
null
)
{
if
(
isUnSentBeacon
(
targetBeacon
))
{
sendBroadcastBeaconMessage
(
targetBeacon
);
saveBeaconHistory
(
targetBeacon
);
}
}
resetSentBeaconList
();
}
private
Beacon
getNearestBeacon
()
{
Beacon
targetBeacon
=
null
;
for
(
Beacon
beacon
:
beaconList
)
{
if
(
targetBeacon
==
null
)
{
targetBeacon
=
beacon
;
}
else
{
if
(
targetBeacon
.
rssi
<
beacon
.
rssi
)
{
targetBeacon
=
beacon
;
}
}
}
return
targetBeacon
;
}
private
boolean
isUnSentBeacon
(
Beacon
beacon
){
return
!
isBeaconListContains
(
sentBeaconList
,
beacon
);
}
private
void
sendBroadcastBeaconMessage
(
Beacon
beacon
)
{
Logger
.
d
(
TAG
,
"SendBroadcastBeaconMessage UUID:"
+
beacon
.
uuid
+
", Major:"
+
beacon
.
major
+
", Minor: "
+
beacon
.
minor
+
", Rssi: "
+
beacon
.
rssi
);
Intent
it
=
new
Intent
(
BeaconPeriodicService
.
this
,
BeaconBroadcastReceiver
.
class
);
it
.
setAction
(
AppDefType
.
Intent
.
Action_Receive_iBeacon_Message
);
it
.
putExtra
(
"major"
,
beacon
.
major
.
toUpperCase
());
it
.
putExtra
(
"minor"
,
beacon
.
minor
.
toUpperCase
());
sendBroadcast
(
it
);
// 送信済みリストに保存
sentBeaconList
.
add
(
beacon
);
}
private
void
saveBeaconHistory
(
Beacon
beacon
)
{
BeaconHistoryDto
dto
=
new
BeaconHistoryDto
();
dto
.
major
=
Integer
.
parseInt
(
beacon
.
major
,
16
);
dto
.
minor
=
Integer
.
parseInt
(
beacon
.
minor
,
16
);
AbstractDao
.
getDao
(
BeaconHistoryDao
.
class
).
insertOrUpdate
(
dto
);
}
private
void
resetSentBeaconList
(){
for
(
int
i
=
sentBeaconList
.
size
()
-
1
;
i
>=
0
;
i
--)
{
Beacon
sentBeacon
=
sentBeaconList
.
get
(
i
);
boolean
isRemoveTarget
=
true
;
for
(
Beacon
beacon
:
beaconList
)
{
if
(
sentBeacon
.
isSameBeacon
(
beacon
))
{
sentBeacon
.
receiveTime
=
beacon
.
receiveTime
;
isRemoveTarget
=
false
;
break
;
}
}
if
(
isRemoveTarget
)
{
if
(
sentBeacon
.
receiveTime
+
containInterval
<
System
.
currentTimeMillis
())
{
Logger
.
d
(
TAG
,
"Remove UUID:"
+
sentBeacon
.
uuid
+
", Major:"
+
sentBeacon
.
major
+
", Minor: "
+
sentBeacon
.
minor
+
", Rssi: "
+
sentBeacon
.
rssi
);
sentBeaconList
.
remove
(
i
);
}
}
}
}
private
boolean
isAvailableServiceUUID
(
String
serviceUUID
)
{
String
[]
uuids
=
getResources
().
getStringArray
(
R
.
array
.
Beacon_UUID
);
for
(
String
uuid
:
uuids
)
{
if
(
serviceUUID
.
toUpperCase
().
equals
(
uuid
.
toUpperCase
()))
{
return
true
;
}
}
return
false
;
}
private
boolean
isSplashScreenForground
(
Context
context
)
{
ActivityManager
am
=
(
ActivityManager
)
context
.
getSystemService
(
Context
.
ACTIVITY_SERVICE
);
//noinspection deprecation(API21から非推奨になった。無視)
List
<
RunningTaskInfo
>
taskInfoList
=
am
.
getRunningTasks
(
1
);
if
(
taskInfoList
.
size
()
>
0
)
{
RunningTaskInfo
runningTaskInfo
=
taskInfoList
.
get
(
0
);
ComponentName
topActivity
=
runningTaskInfo
.
topActivity
;
if
(
topActivity
.
getPackageName
().
equals
(
context
.
getPackageName
())
&&
topActivity
.
getClassName
().
equals
(
SplashScreenActivity
.
class
.
getName
()))
{
return
true
;
}
}
return
false
;
}
}
\ No newline at end of file
ABVJE_UI_Android/src/jp/agentec/abook/abv/launcher/android/ABVUIDataCache.java
View file @
3e307bda
...
...
@@ -61,8 +61,6 @@ public class ABVUIDataCache {
private
int
homeContractId
;
private
int
homeSiteId
;
public
int
contentShareType
=
0
;
// 0:なし,1:ABook+,2:Reader
public
boolean
preIsCatalogEdition
;
public
int
preScale
;
public
int
preDeviceLocationMode
;
...
...
@@ -106,7 +104,6 @@ public class ABVUIDataCache {
loadHomeContractId
();
loadHomeSiteId
();
loadContentLocationTypeEnable
();
contentShareType
=
AbstractLogic
.
getLogic
(
ContractLogic
.
class
).
getContentShareType
();
}
public
boolean
getFavoriteFlag
()
{
...
...
ABVJE_UI_Android/src/jp/agentec/abook/abv/launcher/android/OnBootReceiver.java
View file @
3e307bda
package
jp
.
agentec
.
abook
.
abv
.
launcher
.
android
;
import
java.util.Calendar
;
import
jp.agentec.abook.abv.bl.common.ABVEnvironment
;
import
jp.agentec.abook.abv.bl.common.log.Logger
;
import
jp.agentec.abook.abv.cl.beacon.BeaconPeriodicService
;
import
android.app.AlarmManager
;
import
android.app.PendingIntent
;
import
android.content.BroadcastReceiver
;
...
...
ABVJE_UI_Android/src/jp/agentec/abook/abv/ui/common/activity/ABVAuthenticatedActivity.java
View file @
3e307bda
...
...
@@ -85,8 +85,6 @@ import jp.agentec.abook.abv.bl.logic.ContractLogic;
import
jp.agentec.abook.abv.bl.logic.GroupLogic
;
import
jp.agentec.abook.abv.bl.logic.MemoLogic
;
import
jp.agentec.abook.abv.bl.logic.UserAuthenticateLogic
;
import
jp.agentec.abook.abv.bl.net.PanoServer
;
import
jp.agentec.abook.abv.bl.repo.RepoClient
;
import
jp.agentec.abook.abv.cl.billing.Purchase
;
import
jp.agentec.abook.abv.cl.helper.ABVUncaughtExceptionHandler
;
import
jp.agentec.abook.abv.cl.util.AndroidStringUtil
;
...
...
@@ -279,27 +277,6 @@ public abstract class ABVAuthenticatedActivity extends ABVActivity implements Co
}
}
public
void
contentDetailActivityMove
(
long
contentId
,
String
className
)
{
contentDetailActivityMove
(
contentId
,
className
,
-
1
,
false
);
}
// 2012 12 17 Contents link by jeonghun
// ActivityView에서 사용할수 있기 위하여 contentDetailActivityMove 추가
// 상세화면에서 이전화면 이동시 Bug수정
protected
void
contentDetailActivityMove
(
final
long
contentId
,
final
String
className
,
final
int
pre_page
,
final
boolean
contentLinkFlag
)
{
showProgressPopup
();
ActivityHandlingHelper
.
getInstance
().
contentDetailActivityMove
(
this
,
contentId
,
className
,
pre_page
,
contentLinkFlag
,
new
Callback
()
{
@Override
public
Object
callback
(
Object
ret
)
{
closeProgressPopup
();
if
(
ret
!=
null
)
{
handleErrorMessageToast
(
ret
);
}
return
null
;
}
});
}
/**
* Viewを開始します。
*/
...
...
@@ -1065,7 +1042,7 @@ public abstract class ABVAuthenticatedActivity extends ABVActivity implements Co
}
if
(
xWalkView
!=
null
)
{
// xWalkViewがnullではない場合、javaScriptでopengetitsshareコマンド実行
javaScriptSignageCmd
(
PanoServer
.
CMD_GETITS_OPEN_SHARE
,
xWalkView
);
javaScriptSignageCmd
(
ABookKeys
.
CMD_GETITS_OPEN_SHARE
,
xWalkView
);
}
}
});
...
...
ABVJE_UI_Android/src/jp/agentec/abook/abv/ui/common/activity/ABVUIActivity.java
View file @
3e307bda
package
jp
.
agentec
.
abook
.
abv
.
ui
.
common
.
activity
;
import
java.util.ArrayList
;
import
java.util.List
;
import
java.util.Locale
;
import
jp.agentec.abook.abv.bl.acms.client.json.content.ContentJSON
;
import
jp.agentec.abook.abv.bl.acms.type.DownloadStatusType
;
import
jp.agentec.abook.abv.bl.common.ABVEnvironment
;
import
jp.agentec.abook.abv.bl.common.Callback
;
import
jp.agentec.abook.abv.bl.common.CommonExecutor
;
import
jp.agentec.abook.abv.bl.common.Constant.ReaderConstant
;
import
jp.agentec.abook.abv.bl.common.Constant.ReaderConstant.ReceivePushMessage
;
import
jp.agentec.abook.abv.bl.common.exception.ABVException
;
import
jp.agentec.abook.abv.bl.common.exception.ABVExceptionCode
;
import
jp.agentec.abook.abv.bl.common.exception.AcmsException
;
import
jp.agentec.abook.abv.bl.common.exception.NetworkDisconnectedException
;
import
jp.agentec.abook.abv.bl.common.log.Logger
;
import
jp.agentec.abook.abv.bl.common.util.SecurityUtil
;
import
jp.agentec.abook.abv.bl.data.ABVDataCache
;
import
jp.agentec.abook.abv.bl.data.dao.AbstractDao
;
import
jp.agentec.abook.abv.bl.data.dao.ContentIdConvDao
;
import
jp.agentec.abook.abv.bl.data.dao.ContractDao
;
import
jp.agentec.abook.abv.bl.data.dao.LockDao
;
import
jp.agentec.abook.abv.bl.data.dao.SiteDao
;
import
jp.agentec.abook.abv.bl.download.ContentDownloader
;
import
jp.agentec.abook.abv.bl.download.ContentFileExtractor
;
import
jp.agentec.abook.abv.bl.download.ContentZipDownloadNotification
;
import
jp.agentec.abook.abv.bl.download.ReaderContentDownloader
;
import
jp.agentec.abook.abv.bl.dto.ContentDto
;
import
jp.agentec.abook.abv.bl.dto.ContractDto
;
import
jp.agentec.abook.abv.bl.dto.SiteDto
;
import
jp.agentec.abook.abv.bl.logic.AbstractLogic
;
import
jp.agentec.abook.abv.bl.logic.ContentLogic
;
import
jp.agentec.abook.abv.bl.logic.ContractLogic
;
import
jp.agentec.abook.abv.bl.repo.RepoClient
;
import
jp.agentec.abook.abv.cl.helper.ContentMarkingFileHelper
;
import
jp.agentec.abook.abv.cl.push.FcmManager
;
import
jp.agentec.abook.abv.cl.util.AndroidStringUtil
;
import
jp.agentec.abook.abv.cl.util.PreferenceUtil
;
import
jp.agentec.abook.abv.cl.util.StorageUtil
;
import
jp.agentec.abook.abv.launcher.android.ABVApplication
;
import
jp.agentec.abook.abv.launcher.android.R
;
import
jp.agentec.abook.abv.ui.common.appinfo.AppDefType.SubMenuType
;
import
jp.agentec.abook.abv.ui.common.appinfo.AppDefType.UserPrefKey
;
import
jp.agentec.abook.abv.ui.common.appinfo.options.Options
;
import
jp.agentec.abook.abv.ui.common.constant.ErrorCode
;
import
jp.agentec.abook.abv.ui.common.constant.ErrorMessage
;
import
jp.agentec.abook.abv.ui.common.constant.NaviConsts
;
import
jp.agentec.abook.abv.ui.common.dialog.ABookAlertDialog
;
import
jp.agentec.abook.abv.ui.common.helper.NavigationContentDownloadForReader
;
import
jp.agentec.abook.abv.ui.common.helper.NavigationContentDownloadForReader.NavigationForReaderInterface
;
import
jp.agentec.abook.abv.ui.common.helper.NavigationDownloadForReader
;
import
jp.agentec.abook.abv.ui.common.helper.NavigationExceptionForReader
;
import
jp.agentec.abook.abv.ui.common.helper.NavigationOpenForReader
;
import
jp.agentec.abook.abv.ui.common.helper.NavigationRequestPassForReader
;
import
jp.agentec.abook.abv.ui.common.helper.NavigationUpdateForReader
;
import
jp.agentec.abook.abv.ui.common.helper.ProgressDialogHelper
;
import
jp.agentec.abook.abv.ui.common.util.ABVToastUtil
;
import
jp.agentec.abook.abv.ui.common.util.AlertDialogUtil
;
import
jp.agentec.abook.abv.ui.common.util.LogUtil
;
import
jp.agentec.abook.abv.ui.common.vo.ContentMyList
;
import
jp.agentec.abook.abv.ui.home.activity.ABookSettingActivity
;
import
jp.agentec.abook.abv.ui.home.adapter.ContentCheckListTypeItem
;
import
jp.agentec.abook.abv.ui.home.helper.ActivityHandlingHelper
;
import
jp.agentec.adf.util.StringUtil
;
import
android.content.DialogInterface
;
import
android.content.Intent
;
...
...
@@ -514,275 +490,6 @@ public abstract class ABVUIActivity extends ABVAuthenticatedActivity {
}
}
@Deprecated
// Widgetは廃止
protected
void
sendBroadcastWidget
(
String
action
)
{
Intent
intent
=
new
Intent
();
intent
.
setAction
(
action
);
getApplicationContext
().
sendBroadcast
(
intent
);
}
/**
* サブメニューで表示するアイテムリストを作成します。
*
* @param contentDto 対象コンテンツ
* @param isMain true:メイン画面用、false:詳細画面用
* @return
*/
public
List
<
ContentCheckListTypeItem
>
createSubMenuItems
(
ContentDto
contentDto
,
boolean
isMain
)
{
String
[]
names
=
getRStringArray
(
R
.
array
.
content_submenu_names
);
List
<
ContentCheckListTypeItem
>
items
=
new
ArrayList
<>();
if
(
isMain
)
{
// コンテンツ詳細 ※詳細画面ではなし
items
.
add
(
new
ContentCheckListTypeItem
(
SubMenuType
.
CONTENT_DETAIL_OPEN
,
names
[
SubMenuType
.
CONTENT_DETAIL_OPEN
]));
}
if
(
contentDto
.
downloadingFlg
)
{
// ダウンロード中コンテンツ
// ダウンロードキャンセル
items
.
add
(
new
ContentCheckListTypeItem
(
SubMenuType
.
CONTENT_DOWNLOAD_CANCEL
,
names
[
SubMenuType
.
CONTENT_DOWNLOAD_CANCEL
]));
}
else
{
if
(
isMain
&&
isStreamingEnable
(
contentDto
))
{
items
.
add
(
new
ContentCheckListTypeItem
(
SubMenuType
.
CONTENT_STREAMING
,
names
[
SubMenuType
.
CONTENT_STREAMING
]));
}
if
(
contentDto
.
downloadedFlg
)
{
// ダウンロード済みコンテンツ
if
(
isMain
)
{
// コンテンツ閲覧 ※詳細画面ではなし
items
.
add
(
new
ContentCheckListTypeItem
(
SubMenuType
.
CONTENT_OPEN
,
names
[
SubMenuType
.
CONTENT_OPEN
]));
if
(
ActivityHandlingHelper
.
getInstance
().
isUpdateEnable
(
contentDto
)
&&
!
ABVDataCache
.
getInstance
().
serviceOption
.
isPayment
())
{
// アップデート ※詳細画面ではなし
items
.
add
(
new
ContentCheckListTypeItem
(
SubMenuType
.
CONTENT_UPDATE
,
names
[
SubMenuType
.
CONTENT_UPDATE
]));
}
}
// コンテンツ削除
//チェックビルドオプション
if
(
getRInteger
(
R
.
integer
.
hide_delete_content
)
==
0
)
{
items
.
add
(
new
ContentCheckListTypeItem
(
SubMenuType
.
CONTENT_DELETE
,
names
[
SubMenuType
.
CONTENT_DELETE
]));
}
if
(
contentDto
.
contentType
==
null
||
ContentJSON
.
KEY_PDF_TYPE
.
equals
(
contentDto
.
contentType
.
toLowerCase
(
Locale
.
US
))
||
ContentJSON
.
KEY_NONE_TYPE
.
equals
(
contentDto
.
contentType
))
{
// メモ、マーキング、しおりがすべてオフの場合非表示
if
(
Options
.
getInstance
(
this
).
getViewerMenuMemo
()
==
1
||
Options
.
getInstance
(
this
).
getViewerMenuMarking
()
==
1
||
Options
.
getInstance
(
this
).
getViewerMenuBookmark
()
==
1
)
{
// ユーザ情報コピー
items
.
add
(
new
ContentCheckListTypeItem
(
SubMenuType
.
USER_INFO_COPY
,
names
[
SubMenuType
.
USER_INFO_COPY
]));
}
if
(
getABVUIDataCache
().
srcContentId
!=
-
1
)
{
// ユーザ情報貼り付け
items
.
add
(
new
ContentCheckListTypeItem
(
SubMenuType
.
USER_INFO_PASTE
,
names
[
SubMenuType
.
USER_INFO_PASTE
]));
}
}
if
(
Options
.
getInstance
(
this
).
getHomeMenuMyfolder
()
==
1
&&
isMain
)
{
// マイフォルダに追加 ※詳細画面ではなし
items
.
add
(
new
ContentCheckListTypeItem
(
SubMenuType
.
MYFOLDER_ADD
,
names
[
SubMenuType
.
MYFOLDER_ADD
]));
}
}
else
{
// 未ダウンロードコンテンツ
if
(
ActivityHandlingHelper
.
getInstance
().
isDownloadEnable
(
contentDto
)
&&
!
ABVDataCache
.
getInstance
().
serviceOption
.
isPayment
())
{
// ダウンロード
items
.
add
(
new
ContentCheckListTypeItem
(
SubMenuType
.
CONTENT_DOWNLOAD
,
names
[
SubMenuType
.
CONTENT_DOWNLOAD
]));
}
}
}
if
(
isMain
&&
Options
.
getInstance
(
this
).
getFilerFavorite
()
==
1
)
{
if
(
contentDto
.
favoriteFlg
)
{
// お気に入り追加 ※詳細画面ではなし
items
.
add
(
new
ContentCheckListTypeItem
(
SubMenuType
.
FAVORITE_DELETE
,
names
[
SubMenuType
.
FAVORITE_DELETE
]));
}
else
{
// お気に入り削除 ※詳細画面ではなし
items
.
add
(
new
ContentCheckListTypeItem
(
SubMenuType
.
FAVORITE_ADD
,
names
[
SubMenuType
.
FAVORITE_ADD
]));
}
}
// サービスオプションチェック
if
(
Options
.
getInstance
(
this
).
getViewerMenuShare
(
contentDto
.
contentId
)
==
1
&&
(
ABVDataCache
.
getInstance
().
serviceOption
.
isBizEdition
()
||
hasShareUrl
(
contentDto
)))
{
items
.
add
(
new
ContentCheckListTypeItem
(
SubMenuType
.
SHARE_CONTENT
,
names
[
SubMenuType
.
SHARE_CONTENT
]));
}
return
items
;
}
/**
* URL解決を伴わないReaderコンテンツダウンロード
*
* @param contentId
* @return
*/
protected
boolean
readerContentDownload
(
final
ContractDto
contractDto
,
final
long
contentId
){
final
StringBuffer
result
=
new
StringBuffer
();
try
{
showWifiDisconnectAlert
(
R
.
string
.
C_E_SYSTEM_0005
,
new
DialogInterface
.
OnClickListener
()
{
@Override
public
void
onClick
(
DialogInterface
dialog
,
int
which
)
{
String
msg
=
null
;
SiteDto
siteDto
=
AbstractDao
.
getDao
(
SiteDao
.
class
).
getDto
(
contractDto
.
siteId
);
try
{
// マスタ転送
if
(
transferMaster
(
getRString
(
R
.
string
.
repository_fqdn
))
!=
null
)
{
//????? !=null
throw
new
Exception
();
}
ReaderContentDownloader
.
getInstance
().
downloadContent
(
contractDto
.
siteId
,
ContentLogic
.
getCmsContentId
(
contentId
),
siteDto
.
downloadUrl
.
replace
(
"{URLPATH}"
,
contractDto
.
urlPath
),
contractDto
.
contractId
,
-
1
,
null
);
}
catch
(
AcmsException
e
)
{
// TODO: LoginErrorMessageにメッセージが入っているがこれで良いか。CMS側と合わせて修正必要。
Logger
.
e
(
TAG
,
"downloadContent failed. "
+
e
.
getMessage
()
+
" : "
+
e
.
getLoginErrorMessage
());
msg
=
handleException
(
e
);
}
catch
(
NetworkDisconnectedException
e
)
{
Logger
.
e
(
TAG
,
"downloadContent failed. "
+
e
.
toString
());
msg
=
ErrorMessage
.
getErrorMessage
(
ABVUIActivity
.
this
,
ErrorCode
.
NETWORK
);
}
catch
(
Exception
e
)
{
Logger
.
e
(
TAG
,
"downloadContent failed. "
,
e
);
msg
=
ErrorMessage
.
getErrorMessage
(
ABVUIActivity
.
this
,
ErrorCode
.
C_E_SYSTEM_0001
);
}
finally
{
if
(!
StringUtil
.
isNullOrEmpty
(
msg
))
{
result
.
append
(
msg
);
final
String
errorMsg
=
msg
;
handler
.
post
(
new
Runnable
()
{
@Override
public
void
run
()
{
showSimpleAlertDialog
(
getRString
(
R
.
string
.
error
),
errorMsg
);
}
});
}
}
}
},
new
DialogInterface
.
OnClickListener
()
{
@Override
public
void
onClick
(
DialogInterface
dialog
,
int
which
)
{
ContentZipDownloadNotification
notification
=
new
ContentZipDownloadNotification
();
notification
.
contentId
=
contentId
;
notification
.
downloadStatus
=
DownloadStatusType
.
Canceled
;
onDownloadingContentZip
(
notification
);
}
});
}
catch
(
NetworkDisconnectedException
e
)
{
result
.
append
(
e
.
toString
());
handleErrorMessageToast
(
ErrorCode
.
NETWORK
);
}
return
result
.
length
()
==
0
;
}
protected
ArrayList
<
Long
>
readerContentDownload
(
ContractDto
contractDto
,
long
[]
contentIds
)
{
String
msg
;
ArrayList
<
Long
>
successIds
=
new
ArrayList
<>();
SiteDto
siteDto
=
AbstractDao
.
getDao
(
SiteDao
.
class
).
getDto
(
contractDto
.
siteId
);
// マスタ転送
try
{
msg
=
transferMaster
(
getRString
(
R
.
string
.
repository_fqdn
));
}
catch
(
AcmsException
e
)
{
Logger
.
e
(
TAG
,
"downloadContent failed. "
+
e
.
getMessage
()
+
" : "
+
e
.
getLoginErrorMessage
());
msg
=
handleException
(
e
);
}
catch
(
NetworkDisconnectedException
e
)
{
Logger
.
e
(
TAG
,
"downloadContent failed. "
+
e
.
toString
());
msg
=
ErrorMessage
.
getErrorMessage
(
this
,
ErrorCode
.
NETWORK
);
}
if
(
msg
==
null
)
{
for
(
long
contentId
:
contentIds
)
{
try
{
ReaderContentDownloader
.
getInstance
().
downloadContent
(
contractDto
.
siteId
,
ContentLogic
.
getCmsContentId
(
contentId
),
siteDto
.
downloadUrl
.
replace
(
"{URLPATH}"
,
contractDto
.
urlPath
),
contractDto
.
contractId
,
-
1
,
null
);
successIds
.
add
(
contentId
);
}
catch
(
Exception
e
)
{
msg
=
ErrorMessage
.
getErrorMessage
(
this
,
ErrorCode
.
M003
);
Logger
.
e
(
TAG
,
"downloadContent failed. "
+
e
.
toString
());
}
}
}
if
(!
StringUtil
.
isNullOrEmpty
(
msg
))
{
final
String
errorMsg
=
msg
;
handler
.
post
(
new
Runnable
()
{
@Override
public
void
run
()
{
ABVToastUtil
.
showMakeText
(
ABVUIActivity
.
this
,
errorMsg
,
Toast
.
LENGTH_LONG
);
}
});
}
return
successIds
;
}
/**
* マスタ転送を行い、prefに実行日時を保存する
*
* @return
* @throws AcmsException
* @throws NetworkDisconnectedException
*/
protected
String
transferMaster
(
final
String
repositoryFqdn
)
throws
AcmsException
,
NetworkDisconnectedException
{
if
(
isCheckTransferMaster
)
{
return
null
;
}
try
{
isCheckTransferMaster
=
true
;
return
RepoClient
.
getInstance
().
transferMaster
(
repositoryFqdn
);
}
finally
{
PreferenceUtil
.
putUserPref
(
this
,
UserPrefKey
.
LAST_MASTER_TRANSFER_TIME
,
System
.
currentTimeMillis
());
isCheckTransferMaster
=
false
;
}
}
private
void
pushMessageActivityFinish
()
{
if
(
this
instanceof
ShowPushMessageDailogActivity
)
{
finish
();
}
}
private
String
createMessageWhenPushMessageExist
(
String
msg
)
{
if
(!
StringUtil
.
isNullOrEmpty
(
mPushMessage
))
{
msg
=
mPushMessage
+
"\n"
+
msg
;
mPushMessage
=
""
;
}
return
msg
;
}
private
void
showPushMessageDialog
(
final
ContractDto
contractDto
,
final
Callback
callback
)
{
ABookAlertDialog
pushDialog
=
AlertDialogUtil
.
createAlertDialog
(
this
,
getRString
(
R
.
string
.
push_message_setting
),
getRString
(
R
.
string
.
push_message_setting_dialog_summary
));
pushDialog
.
setPositiveButton
(
R
.
string
.
agree
,
new
DialogInterface
.
OnClickListener
()
{
@Override
public
void
onClick
(
DialogInterface
dialog
,
int
which
)
{
contractDto
.
receivePushMessage
=
ReceivePushMessage
.
PERMIT
;
callback
.
callback
(
contractDto
);
}
});
pushDialog
.
setNegativeButton
(
R
.
string
.
disagree
,
new
DialogInterface
.
OnClickListener
()
{
@Override
public
void
onClick
(
DialogInterface
dialog
,
int
which
)
{
contractDto
.
receivePushMessage
=
ReceivePushMessage
.
REFUSE
;
callback
.
callback
(
contractDto
);
}
});
showAlertDialog
(
pushDialog
);
}
private
void
updateReceivePushMessage
(
final
ContractDto
contractDto
)
{
ProgressDialogHelper
.
showProgressPopup
(
this
,
true
);
final
String
fcmToken
=
FcmManager
.
getFcmToken
(
this
);
if
(
fcmToken
==
null
||
fcmToken
.
equals
(
"noneId"
))
{
ABVToastUtil
.
showMakeText
(
ABVUIActivity
.
this
,
getString
(
R
.
string
.
fcm_not_supported
),
Toast
.
LENGTH_SHORT
);
}
else
{
CommonExecutor
.
execute
(
new
Runnable
()
{
@Override
public
void
run
()
{
try
{
AbstractLogic
.
getLogic
(
ContractLogic
.
class
).
updateReceivePushMessage
(
ABVUIActivity
.
this
.
getString
(
R
.
string
.
repository_fqdn
),
fcmToken
,
contractDto
);
}
catch
(
AcmsException
e
)
{
ErrorMessage
.
showErrorMessageToast
(
ABVUIActivity
.
this
,
e
);
Logger
.
e
(
"PushMessageSettingDialog"
,
e
);
}
catch
(
NetworkDisconnectedException
e
)
{
ABVToastUtil
.
showMakeText
(
ABVUIActivity
.
this
,
R
.
string
.
NETWORK
,
Toast
.
LENGTH_SHORT
);
}
finally
{
ProgressDialogHelper
.
closeProgressPopup
();
}
}
});
}
}
@Override
public
void
onDownloadingContentZip
(
final
ContentZipDownloadNotification
notification
)
{
super
.
onDownloadingContentZip
(
notification
);
...
...
ABVJE_UI_Android/src/jp/agentec/abook/abv/ui/home/activity/ABookSettingFragment.java
View file @
3e307bda
...
...
@@ -78,7 +78,6 @@ import jp.agentec.abook.abv.ui.common.util.ABVToastUtil;
import
jp.agentec.abook.abv.ui.common.util.AlertDialogUtil
;
import
jp.agentec.abook.abv.ui.common.util.ClipboardUtil
;
import
jp.agentec.abook.abv.ui.home.dialog.BackupDialog
;
import
jp.agentec.abook.abv.ui.home.dialog.PushMessageSettingDialog
;
import
jp.agentec.abook.abv.ui.home.dialog.RestoreDialog
;
import
jp.agentec.abook.abv.ui.home.helper.ABookPermissionHelper
;
import
jp.agentec.abook.abv.ui.home.helper.ActivityHandlingHelper
;
...
...
@@ -295,12 +294,6 @@ public class ABookSettingFragment extends PreferenceFragment {
getPreferenceScreen
().
removePreference
(
prefGroup
);
}
private
void
showPushMessageSettingDialog
()
{
PushMessageSettingDialog
dialog
=
new
PushMessageSettingDialog
(
getActivity
());
dialog
.
setNormalSizeFlag
(
isNormalSize
());
dialog
.
show
();
}
private
void
setViewerSetting
()
{
PreferenceGroup
viewerSettings
=
(
PreferenceGroup
)
findPreference
(
VIEWER_SETTING
);
...
...
ABVJE_UI_Android/src/jp/agentec/abook/abv/ui/home/activity/ContentDetailViewActivity.java
deleted
100644 → 0
View file @
32ec4e3a
package
jp
.
agentec
.
abook
.
abv
.
ui
.
home
.
activity
;
import
java.io.File
;
import
java.io.IOException
;
import
java.util.ArrayList
;
import
java.util.List
;
import
jp.agentec.abook.abv.bl.acms.client.json.DownloadedContentInfoJSON
;
import
jp.agentec.abook.abv.bl.acms.client.json.content.ContentJSON
;
import
jp.agentec.abook.abv.bl.acms.client.json.content.ContentLinkJSON
;
import
jp.agentec.abook.abv.bl.acms.type.DeliveryType
;
import
jp.agentec.abook.abv.bl.acms.type.ServiceOption.ContentShareType
;
import
jp.agentec.abook.abv.bl.common.ABVEnvironment
;
import
jp.agentec.abook.abv.bl.common.exception.AcmsException
;
import
jp.agentec.abook.abv.bl.common.exception.NetworkDisconnectedException
;
import
jp.agentec.abook.abv.bl.common.log.Logger
;
import
jp.agentec.abook.abv.bl.common.util.ContentFileUtil
;
import
jp.agentec.abook.abv.bl.data.ABVDataCache
;
import
jp.agentec.abook.abv.bl.data.dao.AbstractDao
;
import
jp.agentec.abook.abv.bl.data.dao.ContentDao
;
import
jp.agentec.abook.abv.bl.data.dao.ContentIdConvDao
;
import
jp.agentec.abook.abv.bl.download.ContentZipDownloadNotification
;
import
jp.agentec.abook.abv.bl.dto.ContentDto
;
import
jp.agentec.abook.abv.bl.dto.ContentIdConvDto
;
import
jp.agentec.abook.abv.bl.dto.ContractDto
;
import
jp.agentec.abook.abv.bl.logic.AbstractLogic
;
import
jp.agentec.abook.abv.bl.logic.ContentLogic
;
import
jp.agentec.abook.abv.bl.logic.ContractLogic
;
import
jp.agentec.abook.abv.bl.logic.ProjectLogic
;
import
jp.agentec.abook.abv.cl.util.AndroidStringUtil
;
import
jp.agentec.abook.abv.cl.util.BitmapUtil
;
import
jp.agentec.abook.abv.cl.util.PreferenceUtil
;
import
jp.agentec.abook.abv.launcher.android.R
;
import
jp.agentec.abook.abv.launcher.android.R.id
;
import
jp.agentec.abook.abv.ui.common.activity.ABVUIActivity
;
import
jp.agentec.abook.abv.ui.common.appinfo.AppDefType.DefPrefKey
;
import
jp.agentec.abook.abv.ui.common.appinfo.AppDefType.SubMenuType
;
import
jp.agentec.abook.abv.ui.common.appinfo.options.Options
;
import
jp.agentec.abook.abv.ui.common.constant.ErrorCode
;
import
jp.agentec.abook.abv.ui.common.constant.ErrorMessage
;
import
jp.agentec.abook.abv.ui.common.dialog.ABookAlertDialog
;
import
jp.agentec.abook.abv.ui.common.dto.ContentPageSerializableDto
;
import
jp.agentec.abook.abv.ui.common.helper.BillingHelper
;
import
jp.agentec.abook.abv.ui.common.util.ABVToastUtil
;
import
jp.agentec.abook.abv.ui.common.util.AlertDialogUtil
;
import
jp.agentec.abook.abv.ui.common.view.ABVPopupListWindow
;
import
jp.agentec.abook.abv.ui.home.adapter.ContentCheckListTypeItem
;
import
jp.agentec.abook.abv.ui.home.adapter.ContentDetailLinkAdapter
;
import
jp.agentec.abook.abv.ui.home.adapter.ContentDetailListAdapter
;
import
jp.agentec.abook.abv.ui.home.dto.ContentLinkAdapterDto
;
import
jp.agentec.abook.abv.ui.home.dto.ContentLinkAdapterDto.ContentStatus
;
import
jp.agentec.abook.abv.ui.home.helper.ActivityHandlingHelper
;
import
jp.agentec.adf.util.DateTimeUtil
;
import
jp.agentec.adf.util.StringUtil
;
import
org.json.adf.JSONArray
;
import
android.content.Context
;
import
android.content.DialogInterface
;
import
android.content.Intent
;
import
android.content.res.Configuration
;
import
android.content.res.Resources
;
import
android.graphics.Bitmap
;
import
android.graphics.Bitmap.Config
;
import
android.graphics.Color
;
import
android.os.Bundle
;
import
android.util.Log
;
import
android.view.KeyEvent
;
import
android.view.LayoutInflater
;
import
android.view.View
;
import
android.view.View.OnClickListener
;
import
android.view.WindowManager
;
import
android.widget.AdapterView
;
import
android.widget.AdapterView.OnItemClickListener
;
import
android.widget.Button
;
import
android.widget.GridView
;
import
android.widget.ImageButton
;
import
android.widget.ImageView
;
import
android.widget.LinearLayout
;
import
android.widget.ListView
;
import
android.widget.TabHost
;
import
android.widget.TabHost.OnTabChangeListener
;
import
android.widget.TabHost.TabSpec
;
import
android.widget.TextView
;
import
android.widget.Toast
;
/**
* コンテンツ詳細画面
* @author Chae
* @version 1.0.0
*/
public
class
ContentDetailViewActivity
extends
ABVUIActivity
{
private
static
final
String
TAG
=
"ContentDetailActivity"
;
private
ContractLogic
contractLogic
=
AbstractLogic
.
getLogic
(
ContractLogic
.
class
);
private
TextView
mTxtContentDetail
;
private
TextView
mTxtDeliveryDateStart
;
private
TextView
mTxtDeliveryDateEnd
;
private
TextView
mTxtPublisherInfo
;
private
TextView
mTxtPublisherId
;
private
TextView
mTxtLastDeliveryDateValue
;
private
TextView
mTxtContentSizeValue
;
private
TextView
mTxtContractContentId
;
private
TextView
mTxtAllPageNum
;
private
TextView
mTxtGroupInfo
;
private
TextView
mTxtCategoryInfo
;
private
TabHost
mTabHost
;
private
Button
mBtnDelete
;
private
Button
mBtnDownloadStatus
;
private
Button
mBtnOpenStatus
;
private
Button
mBtnStreaming
;
private
Button
mBtnInappPurchase
;
private
Button
mBtnSubscribe
;
private
LinearLayout
mRelSelectAll
;
private
ImageView
mIconSelectAll
;
private
TextView
mTxtSelectAll
;
private
LinearLayout
mRelRelatedDown
;
private
Button
mBtnExit
;
private
ImageButton
mBtnSubmenu
;
private
TextView
mTxtMenutitle
;
private
ImageView
mImgDetail
;
private
ImageView
mImgFavorite
;
private
ListView
mListView
;
private
GridView
mGridView
;
private
ContentDetailListAdapter
mListAdapter
;
private
long
mContentId
=
0
;
private
String
mThumbnailNormalPath
;
private
String
mContentName
;
private
String
mContentDetail
;
private
String
mDeliveryStartDate
;
private
String
mDeliveryEndDate
;
private
String
mLastDeliveryDate
;
private
boolean
mDownloadedFlg
;
private
boolean
mDownloadingFlg
;
private
boolean
mUpdatedFlg
;
private
boolean
mPausedFlg
;
private
boolean
mPdfSendMailFlg
;
private
boolean
mPrintFlg
;
private
boolean
mReaderShareFlg
;
private
String
mContentType
;
private
int
mContractContentId
;
private
int
mContentAlertLevel
;
private
int
mAllPageNum
;
private
int
mContentSize
;
private
ImageView
mImgMail
;
private
ImageView
mImgPrint
;
private
ImageView
mImgAlert
;
private
ImageView
mImgShare
;
private
ArrayList
<
String
>
mGroupInfo
;
private
ArrayList
<
String
>
mCategoryInfo
;
private
ArrayList
<
ContentPageSerializableDto
>
mPages
;
private
JSONArray
mContentLinks
;
private
ContentDetailLinkAdapter
mLinkAdapter
;
private
List
<
ContentLinkAdapterDto
>
mLinkListItem
;
private
boolean
contentLinkFlag
;
private
ContractDto
mContractDto
;
private
ContentDto
mContentDto
;
private
String
mFromClassName
;
private
int
mSubMenuItemCount
=
-
1
;
//サブメニューの項目の数
@Override
@SuppressWarnings
(
"unchecked"
)
public
void
onCreate
(
Bundle
savedInstanceState
)
{
Logger
.
i
(
TAG
,
"onCreate"
);
super
.
onCreate
(
savedInstanceState
);
setContentView
(
R
.
layout
.
ac_content_detail_view
);
Intent
intent
=
getIntent
();
mContentId
=
intent
.
getLongExtra
(
"contentId"
,
0
);
mContentDto
=
AbstractDao
.
getDao
(
ContentDao
.
class
).
getContent
(
mContentId
);
// TODO: この下のフィールドも全部これを使ってIntent渡しをやめる
mThumbnailNormalPath
=
intent
.
getStringExtra
(
"ThumbnailNormalPath"
);
mContentName
=
intent
.
getStringExtra
(
"ContentName"
);
mContentDetail
=
intent
.
getStringExtra
(
"ContentDetail"
);
mDeliveryStartDate
=
intent
.
getStringExtra
(
"DeliveryStartDate"
);
mDeliveryEndDate
=
intent
.
getStringExtra
(
"DeliveryEndDate"
);
mDownloadedFlg
=
intent
.
getBooleanExtra
(
"DownloadedFlg"
,
false
);
mDownloadingFlg
=
intent
.
getBooleanExtra
(
"DownloadingFlg"
,
false
);
mUpdatedFlg
=
intent
.
getBooleanExtra
(
"UpdatedFlg"
,
false
);
//2012 12 17 Contents Link 수정
mPages
=
(
ArrayList
<
ContentPageSerializableDto
>)
intent
.
getSerializableExtra
(
"Pages"
);
mAllPageNum
=
intent
.
getIntExtra
(
"AllPageNum"
,
0
);
mContentSize
=
intent
.
getIntExtra
(
"ContentSize"
,
0
);
mGroupInfo
=
intent
.
getStringArrayListExtra
(
"GroupInfo"
);
mCategoryInfo
=
intent
.
getStringArrayListExtra
(
"CategoryInfo"
);
mPausedFlg
=
getIntent
().
getBooleanExtra
(
"PausedFlg"
,
false
);
mPdfSendMailFlg
=
getIntent
().
getBooleanExtra
(
"PdfSendMailFlg"
,
false
);
mPrintFlg
=
getIntent
().
getBooleanExtra
(
"PrintFlg"
,
false
);
mReaderShareFlg
=
getIntent
().
getBooleanExtra
(
"ReaderShareFlg"
,
false
);
// 콘텐츠 링크에서 넘어왔는지 값을 체크
// コンテンツリンクからの遷移か否か
contentLinkFlag
=
getIntent
().
getBooleanExtra
(
"ContentLinkFlag"
,
false
);
mLastDeliveryDate
=
getIntent
().
getStringExtra
(
"LastDeliveryDate"
);
mContentType
=
getIntent
().
getStringExtra
(
"ContentType"
);
mContractContentId
=
getIntent
().
getIntExtra
(
"ContractContentId"
,
0
);
mContentAlertLevel
=
getIntent
().
getIntExtra
(
"ContentAlertLevel"
,
0
);
mFromClassName
=
getIntent
().
getStringExtra
(
"FromClassName"
);
mBtnExit
=
(
Button
)
findViewById
(
R
.
id
.
btn_exit
);
mBtnSubmenu
=
(
ImageButton
)
findViewById
(
R
.
id
.
btn_submenu
);
mTxtMenutitle
=
(
TextView
)
findViewById
(
R
.
id
.
txt_detail_menu_title
);
mImgDetail
=
(
ImageView
)
findViewById
(
R
.
id
.
img_detail_main
);
mImgFavorite
=
(
ImageView
)
findViewById
(
R
.
id
.
img_favorite
);
mBtnDownloadStatus
=
(
Button
)
findViewById
(
R
.
id
.
btn_download_status
);
mBtnOpenStatus
=
(
Button
)
findViewById
(
R
.
id
.
btn_content_open_status
);
mBtnStreaming
=
(
Button
)
findViewById
(
R
.
id
.
btn_content_streaming
);
mBtnInappPurchase
=
(
Button
)
findViewById
(
R
.
id
.
btn_inapp_purchase
);
mBtnSubscribe
=
(
Button
)
findViewById
(
R
.
id
.
btn_subscribe
);
mBtnDelete
=
(
Button
)
findViewById
(
R
.
id
.
btn_content_delete
);
mTxtDeliveryDateStart
=
(
TextView
)
findViewById
(
R
.
id
.
txt_delivery_date_start
);
mTxtDeliveryDateEnd
=
(
TextView
)
findViewById
(
R
.
id
.
txt_delivery_date_end
);
//サブメニューの項目が「コンテンツ削除う」以外にない場合サブメニュー非表示
if
(
getRInteger
(
R
.
integer
.
hide_delete_content
)
==
1
)
{
final
ContentDto
contentDto
=
contentDao
.
getContent
(
mContentId
);
final
List
<
ContentCheckListTypeItem
>
members
=
createSubMenuItems
(
contentDto
,
false
);
mSubMenuItemCount
=
members
.
size
();
if
(
mSubMenuItemCount
==
0
)
{
mBtnSubmenu
.
setVisibility
(
View
.
INVISIBLE
);
}
}
findViewById
(
R
.
id
.
linear_publisher_info
).
setVisibility
(
View
.
GONE
);
mTxtLastDeliveryDateValue
=
(
TextView
)
findViewById
(
R
.
id
.
txt_update_date_value
);
mTxtContentSizeValue
=
(
TextView
)
findViewById
(
R
.
id
.
txt_content_size_value
);
mTxtContractContentId
=
(
TextView
)
findViewById
(
R
.
id
.
txt_content_num
);
mTxtAllPageNum
=
(
TextView
)
findViewById
(
R
.
id
.
txt_all_page_num
);
mRelSelectAll
=
(
LinearLayout
)
findViewById
(
R
.
id
.
rel_select_all
);
mIconSelectAll
=
(
ImageView
)
findViewById
(
R
.
id
.
icon_select_all
);
mTxtSelectAll
=
(
TextView
)
findViewById
(
R
.
id
.
txt_select_all
);
mRelRelatedDown
=
(
LinearLayout
)
findViewById
(
R
.
id
.
rel_related_down
);
mRelSelectAll
.
setVisibility
(
View
.
GONE
);
mRelRelatedDown
.
setVisibility
(
View
.
GONE
);
mGridView
=
(
GridView
)
findViewById
(
R
.
id
.
grid_link_view
);
if
(
mDeliveryStartDate
!=
null
)
{
mDeliveryStartDate
=
mDeliveryStartDate
.
replaceAll
(
"\\s"
,
" "
);
mDeliveryStartDate
=
mDeliveryStartDate
+
"~"
;
}
if
(
mDeliveryEndDate
!=
null
){
mDeliveryEndDate
=
mDeliveryEndDate
.
replaceAll
(
"\\s"
,
" "
);
mTxtDeliveryDateEnd
.
setText
(
mDeliveryEndDate
);
mLastDeliveryDate
=
mLastDeliveryDate
.
replaceAll
(
"\\s"
,
" "
);
}
mTxtDeliveryDateStart
.
setText
(
mDeliveryStartDate
);
mTxtLastDeliveryDateValue
.
setText
(
mLastDeliveryDate
);
setTabHost
();
mListView
=
(
ListView
)
findViewById
(
id
.
list_detail
);
LayoutInflater
inflater
=
(
LayoutInflater
)
getApplication
().
getSystemService
(
Context
.
LAYOUT_INFLATER_SERVICE
);
LinearLayout
headLayout
=
(
LinearLayout
)
inflater
.
inflate
(
R
.
layout
.
content_detail_info
,
null
);
mImgAlert
=
(
ImageView
)
headLayout
.
findViewById
(
R
.
id
.
img_alert
);
mImgMail
=
(
ImageView
)
headLayout
.
findViewById
(
R
.
id
.
img_mail
);
mImgPrint
=
(
ImageView
)
headLayout
.
findViewById
(
R
.
id
.
img_print
);
mImgShare
=
(
ImageView
)
headLayout
.
findViewById
(
R
.
id
.
img_share
);
if
(
mContentAlertLevel
!=
0
){
mImgAlert
.
setVisibility
(
View
.
VISIBLE
);
}
if
(
mPdfSendMailFlg
){
mImgMail
.
setVisibility
(
View
.
VISIBLE
);
}
if
(
mPrintFlg
){
mImgPrint
.
setVisibility
(
View
.
VISIBLE
);
}
boolean
showImgShareFlg
=
false
;
if
(
Options
.
getInstance
(
this
).
getHomeMenuGroup
()
==
0
)
{
headLayout
.
findViewById
(
R
.
id
.
linear_group
).
setVisibility
(
View
.
GONE
);
}
if
(
Options
.
getInstance
(
this
).
getHomeMenuCategory
()
==
0
)
{
headLayout
.
findViewById
(
R
.
id
.
linear_category
).
setVisibility
(
View
.
GONE
);
}
if
(
mContentAlertLevel
==
0
&&
!
mPdfSendMailFlg
)
{
headLayout
.
findViewById
(
R
.
id
.
linear_detail_icons
).
setVisibility
(
View
.
GONE
);
if
(
Options
.
getInstance
(
this
).
getHomeMenuGroup
()
==
0
&&
Options
.
getInstance
(
this
).
getHomeMenuCategory
()
==
0
)
{
headLayout
.
findViewById
(
R
.
id
.
linear1
).
setVisibility
(
View
.
GONE
);
}
}
mListView
.
addHeaderView
(
headLayout
);
Logger
.
d
(
TAG
,
"content_link_status : "
+
contentLinkFlag
);
if
(
Options
.
getInstance
(
this
).
getFilerFavorite
()
==
1
&&
!
ABVDataCache
.
getInstance
().
serviceOption
.
isPayment
())
{
mImgFavorite
.
setVisibility
(
View
.
VISIBLE
);
if
(
contentLogic
.
isExsitContentFavorite
(
mContentId
))
{
mImgFavorite
.
setBackgroundResource
(
R
.
drawable
.
icon_favorite_add_on
);
}
else
{
mImgFavorite
.
setBackgroundResource
(
R
.
drawable
.
icon_favorite_add_off
);
}
}
else
{
mImgFavorite
.
setVisibility
(
View
.
GONE
);
}
// Newフラグ更新
if
(
mContentDto
.
newFlg
)
{
mContentDto
.
newFlg
=
false
;
contentDao
.
updateContent
(
mContentDto
,
false
);
}
if
(
ABVDataCache
.
getInstance
().
serviceOption
.
isPayment
())
{
BillingHelper
.
getInstance
().
init
(
this
);
}
Resources
r
=
Resources
.
getSystem
();
Configuration
config
=
r
.
getConfiguration
();
onConfigurationChanged
(
config
);
}
//サブメニューの項目が「コンテンツ削除」以外にない場合サブメニュー非表示
private
void
checkSubMenu
()
{
if
(
getRInteger
(
R
.
integer
.
hide_delete_content
)
==
1
&&
mSubMenuItemCount
==
0
)
{
mBtnSubmenu
.
setVisibility
(
View
.
INVISIBLE
);
}
else
{
mBtnSubmenu
.
setVisibility
(
View
.
VISIBLE
);
}
}
private
void
setTabHost
()
{
mTabHost
=
(
TabHost
)
findViewById
(
R
.
id
.
tab_content_detail
);
mTabHost
.
setup
();
mTabHost
.
setCurrentTab
(
0
);
View
tabView1
=
createTabView
(
this
,
getResources
().
getString
(
R
.
string
.
detail_info
),
"info"
,
true
);
View
tabView2
=
createTabView
(
this
,
getResources
().
getString
(
R
.
string
.
related_content
),
"link"
,
false
);
TabSpec
tInfo
=
mTabHost
.
newTabSpec
(
"info"
)
.
setIndicator
(
tabView1
)
.
setContent
(
R
.
id
.
tab_content_info
);
TabSpec
tLink
=
mTabHost
.
newTabSpec
(
"link"
)
.
setIndicator
(
tabView2
)
.
setContent
(
R
.
id
.
tab_link_content
);
mTabHost
.
addTab
(
tInfo
);
mTabHost
.
addTab
(
tLink
);
final
Button
tInfoBtn
=
(
Button
)
mTabHost
.
getTabWidget
().
getChildAt
(
0
).
findViewById
(
R
.
id
.
tabs_image
);
final
Button
tLinkBtn
=
(
Button
)
mTabHost
.
getTabWidget
().
getChildAt
(
1
).
findViewById
(
R
.
id
.
tabs_image
);
mTabHost
.
setOnTabChangedListener
(
new
OnTabChangeListener
()
{
@Override
public
void
onTabChanged
(
String
tabId
)
{
if
(
tabId
.
equals
(
"info"
)){
mRelRelatedDown
.
setVisibility
(
View
.
GONE
);
mRelSelectAll
.
setVisibility
(
View
.
GONE
);
tInfoBtn
.
setTextColor
(
Color
.
WHITE
);
tLinkBtn
.
setTextColor
(
Color
.
BLACK
);
}
else
if
(
tabId
.
equals
(
"link"
)){
if
(
mLinkAdapter
.
getCheckableCount
()
!=
0
){
mRelRelatedDown
.
setVisibility
(
View
.
VISIBLE
);
mRelSelectAll
.
setVisibility
(
View
.
VISIBLE
);
}
tInfoBtn
.
setTextColor
(
Color
.
BLACK
);
tLinkBtn
.
setTextColor
(
Color
.
WHITE
);
}
}
});
}
private
View
createTabView
(
Context
context
,
String
tabText
,
final
String
tag
,
boolean
pressed
)
{
View
view
=
LayoutInflater
.
from
(
context
).
inflate
(
R
.
layout
.
custom_tab
,
null
,
false
);
Button
imgButton
=
(
Button
)
view
.
findViewById
(
R
.
id
.
tabs_image
);
imgButton
.
setBackgroundResource
(
R
.
drawable
.
icon_contentdetail_tab
);
imgButton
.
setText
(
tabText
);
if
(!
pressed
)
{
imgButton
.
setTextColor
(
Color
.
BLACK
);
}
imgButton
.
setOnClickListener
(
new
OnClickListener
()
{
@Override
public
void
onClick
(
View
v
)
{
if
(
tag
.
equals
(
"info"
))
{
mTabHost
.
setCurrentTab
(
0
);
}
else
{
mTabHost
.
setCurrentTab
(
1
);
}
}
});
return
view
;
}
/**
* ボタンイベント設定
* @since 1.0.0
*/
private
void
setOnButtonEvent
()
{
mBtnExit
.
setOnClickListener
(
new
View
.
OnClickListener
()
{
@Override
public
void
onClick
(
View
v
)
{
if
(
contentLinkFlag
&&
contentDownloader
.
getActiveCountWithoutWaiting
()
>
0
)
{
showDownloadPauseDialog
();
}
else
{
finish
();
}
}
});
mBtnSubmenu
.
setOnClickListener
(
new
View
.
OnClickListener
()
{
@Override
public
void
onClick
(
View
v
)
{
if
(
mDownloadedFlg
)
{
showSubMenuDialog
(
v
);
}
}
});
mImgFavorite
.
setOnClickListener
(
new
View
.
OnClickListener
()
{
@Override
public
void
onClick
(
View
v
)
{
try
{
if
(
contentLogic
.
isExsitContentFavorite
(
mContentId
))
{
contentLogic
.
setFavoriteContent
(
mContentId
,
false
);
mImgFavorite
.
setBackgroundResource
(
R
.
drawable
.
icon_favorite_add_off
);
Logger
.
d
(
TAG
,
"icon_favorite_add_off click"
);
}
else
{
contentLogic
.
setFavoriteContent
(
mContentId
,
true
);
mImgFavorite
.
setBackgroundResource
(
R
.
drawable
.
icon_favorite_add_on
);
Logger
.
d
(
TAG
,
"icon_favorite_add_on click"
);
}
}
catch
(
Exception
e
)
{
Logger
.
e
(
TAG
,
"mImgFavorite onClick"
,
e
);
handleErrorMessageToast
(
ErrorCode
.
ERROR
);
}
}
});
}
/**
* 項目設定
* @since 1.0.0
*/
private
void
setDetal
()
{
int
resizeLength
;
if
((
getResources
().
getConfiguration
().
orientation
==
Configuration
.
ORIENTATION_PORTRAIT
))
{
// 縦の場合、画面の5分の2の80%を基準にリサイズ
resizeLength
=
(
int
)((
getResources
().
getDisplayMetrics
().
widthPixels
)
*
0.4
);
}
else
{
// 横の場合、画面の半分の80%を基準にリサイズ
resizeLength
=
(
int
)((
getResources
().
getDisplayMetrics
().
heightPixels
)
*
0.5
);
}
Bitmap
resized
=
BitmapUtil
.
getResizedBitmap
(
mContentDto
.
thumbnailBigPath
,
resizeLength
,
resizeLength
,
Config
.
RGB_565
);
if
(
resized
==
null
)
{
resized
=
BitmapUtil
.
getResizedBitmap
(
mThumbnailNormalPath
,
resizeLength
,
resizeLength
,
Config
.
RGB_565
);
}
mImgDetail
.
setImageBitmap
(
resized
);
mImgDetail
.
setAdjustViewBounds
(
true
);
mImgDetail
.
setScaleType
(
ImageView
.
ScaleType
.
CENTER_INSIDE
);
mImgDetail
.
setPadding
(
0
,
0
,
1
,
1
);
if
(
ABVDataCache
.
getInstance
().
serviceOption
.
isPayment
()){
mImgDetail
.
setOnClickListener
(
new
View
.
OnClickListener
()
{
@Override
public
void
onClick
(
View
v
)
{
mBtnExit
.
setVisibility
(
View
.
INVISIBLE
);
findViewById
(
R
.
id
.
big_thumbnail_layout
).
setVisibility
(
View
.
VISIBLE
);
}
});
findViewById
(
R
.
id
.
big_thumbnail_close
).
setOnClickListener
(
new
View
.
OnClickListener
()
{
@Override
public
void
onClick
(
View
v
)
{
mBtnExit
.
setVisibility
(
View
.
VISIBLE
);
findViewById
(
R
.
id
.
big_thumbnail_layout
).
setVisibility
(
View
.
GONE
);
}
});
try
{
String
contentInfoFilePath
=
ABVEnvironment
.
getInstance
().
getContentDirectoryPath
(
mContentId
,
false
)
+
File
.
separator
+
ABVEnvironment
.
ContentVersionInfoJsonName
;
DownloadedContentInfoJSON
json
=
ContentFileUtil
.
getDownloadedContentInfoJSON
(
contentInfoFilePath
);
String
largeTthumbnailPath
=
ABVEnvironment
.
getInstance
().
getContentDetailDirectoryPath
(
mContentId
,
false
)
+
File
.
separator
+
json
.
thumbnailLargeName
;
Bitmap
largeBitmap
=
BitmapUtil
.
getBitmap
(
largeTthumbnailPath
,
Config
.
RGB_565
);
if
(
largeBitmap
==
null
)
{
largeBitmap
=
BitmapUtil
.
getBitmap
(
mContentDto
.
thumbnailBigPath
,
Config
.
RGB_565
);
}
if
(
largeBitmap
==
null
)
{
largeBitmap
=
BitmapUtil
.
getBitmap
(
mContentDto
.
thumbnailNormalPath
,
Config
.
RGB_565
);
}
if
(
largeBitmap
!=
null
)
{
((
ImageView
)
findViewById
(
R
.
id
.
big_thumbnail
)).
setImageBitmap
(
largeBitmap
);
}
}
catch
(
Exception
e
)
{
Logger
.
e
(
TAG
,
e
.
toString
());
}
}
if
(
ABVDataCache
.
getInstance
().
serviceOption
.
isPayment
())
{
mTxtMenutitle
.
setCompoundDrawablesWithIntrinsicBounds
(
0
,
0
,
0
,
0
);
}
else
{
int
drawableId
;
if
(
mContentType
.
equals
(
ContentJSON
.
KEY_PDF_TYPE
))
{
drawableId
=
R
.
drawable
.
icon_pdf_file
;
}
else
if
(
mContentType
.
equals
(
ContentJSON
.
KEY_IMAGE_TYPE
))
{
drawableId
=
R
.
drawable
.
icon_image_file
;
}
else
if
(
mContentType
.
equals
(
ContentJSON
.
KEY_MOVIE_TYPE
))
{
drawableId
=
R
.
drawable
.
icon_movie_file
;
}
else
if
(
mContentType
.
equals
(
ContentJSON
.
KEY_PANO_MOVIE_TYPE
))
{
drawableId
=
R
.
drawable
.
icon_pano_movie_file
;
}
else
if
(
mContentType
.
equals
(
ContentJSON
.
KEY_PANO_IMAGE_TYPE
))
{
drawableId
=
R
.
drawable
.
icon_pano_image_file
;
}
else
if
(
mContentType
.
equals
(
ContentJSON
.
KEY_OBJECTVR_TYPE
))
{
drawableId
=
R
.
drawable
.
icon_objectvr_file
;
}
else
if
(
mContentType
.
equals
(
ContentJSON
.
KEY_MUSIC_TYPE
))
{
drawableId
=
R
.
drawable
.
icon_music_file
;
}
else
if
(
mContentType
.
equals
(
ContentJSON
.
KEY_HTML_TYPE
))
{
drawableId
=
R
.
drawable
.
icon_html_file
;
}
else
if
(
mContentType
.
equals
(
ContentJSON
.
KEY_OTHER_TYPE
))
{
drawableId
=
R
.
drawable
.
icon_other_file
;
}
else
if
(
mContentType
.
equals
(
ContentJSON
.
KEY_LINK_TYPE
))
{
drawableId
=
R
.
drawable
.
icon_weblink_file
;
}
else
if
(
mContentType
.
equals
(
ContentJSON
.
KEY_ENQUETE_TYPE
))
{
drawableId
=
R
.
drawable
.
icon_enquete_file
;
}
else
if
(
mContentType
.
equals
(
ContentJSON
.
KEY_EXAM_TYPE
))
{
drawableId
=
R
.
drawable
.
icon_exam_file
;
}
else
{
drawableId
=
R
.
drawable
.
icon_no_file
;
}
mTxtMenutitle
.
setCompoundDrawablesWithIntrinsicBounds
(
drawableId
,
0
,
0
,
0
);
}
findViewById
(
R
.
id
.
txt_content_num_info
).
setVisibility
(
View
.
VISIBLE
);
mTxtContractContentId
.
setText
(
""
+
mContractContentId
);
mTxtContentSizeValue
.
setText
(
makeContentSizeStr
(
mContentSize
));
if
(
isNormalSize
())
{
mGridView
.
setNumColumns
(
1
);
}
else
{
mGridView
.
setNumColumns
(
2
);
}
mTxtAllPageNum
.
setText
(
""
+
mAllPageNum
);
}
private
String
makeContentSizeStr
(
int
contentSize
)
{
StringBuffer
sb
=
new
StringBuffer
();
if
(
contentSize
==
0
)
{
// 0の場合1KB
sb
.
append
(
"1KB"
);
}
else
{
if
(
contentSize
>=
1024
)
{
int
contentSizeMB
=
contentSize
/
1024
;
sb
.
append
(
StringUtil
.
numberDispFormatComma
(
contentSizeMB
));
sb
.
append
(
"MB"
);
}
else
{
sb
.
append
(
StringUtil
.
numberDispFormatComma
(
contentSize
));
sb
.
append
(
"KB"
);
}
}
return
sb
.
toString
();
}
private
void
setDownloadStatus
()
{
mBtnInappPurchase
.
setVisibility
(
View
.
GONE
);
mBtnSubscribe
.
setVisibility
(
View
.
GONE
);
mBtnDelete
.
setVisibility
(
View
.
GONE
);
mBtnStreaming
.
setVisibility
(
View
.
GONE
);
mBtnDownloadStatus
.
setVisibility
(
View
.
GONE
);
mBtnOpenStatus
.
setVisibility
(
View
.
GONE
);
mBtnSubmenu
.
setVisibility
(
View
.
INVISIBLE
);
if
(
contentLinkFlag
)
{
return
;
}
if
(
mDownloadingFlg
&&
!
mPausedFlg
)
{
mBtnDownloadStatus
.
setVisibility
(
View
.
VISIBLE
);
mBtnDownloadStatus
.
setText
(
getResources
().
getString
(
R
.
string
.
downloading
));
mBtnDownloadStatus
.
setCompoundDrawablesWithIntrinsicBounds
(
getResources
().
getDrawable
(
R
.
drawable
.
ic_download_pause
),
null
,
null
,
null
);
mBtnDownloadStatus
.
setOnClickListener
(
new
View
.
OnClickListener
()
{
@Override
public
void
onClick
(
View
v
)
{
//일시정지 이벤트
Logger
.
d
(
TAG
,
"#####################pause"
);
contentDownloadPause
(
mContentId
);
mPausedFlg
=
true
;
mDownloadingFlg
=
false
;
setDownloadStatus
();
}
});
}
else
if
(!
mDownloadedFlg
&&
!
mPausedFlg
&&
!
isStreamingOnly
(
mContentDto
))
{
mBtnDownloadStatus
.
setVisibility
(
View
.
VISIBLE
);
mBtnDownloadStatus
.
setText
(
getResources
().
getString
(
R
.
string
.
download
));
mBtnDownloadStatus
.
setCompoundDrawablesWithIntrinsicBounds
(
getResources
().
getDrawable
(
R
.
drawable
.
ic_download
),
null
,
null
,
null
);
mBtnDownloadStatus
.
setOnClickListener
(
new
View
.
OnClickListener
()
{
@Override
public
void
onClick
(
View
v
)
{
//다운로드 시작
Logger
.
d
(
TAG
,
"#####################start"
);
contentValidCheckAndDownload
(
mContentId
);
mDownloadingFlg
=
true
;
setDownloadStatus
();
}
});
}
else
if
(
mDownloadedFlg
&&
mUpdatedFlg
&&
!
mPausedFlg
&&
!
isStreamingOnly
(
mContentDto
))
{
mBtnDownloadStatus
.
setVisibility
(
View
.
VISIBLE
);
mBtnDownloadStatus
.
setText
(
getResources
().
getString
(
R
.
string
.
update
));
mBtnDownloadStatus
.
setCompoundDrawablesWithIntrinsicBounds
(
getResources
().
getDrawable
(
R
.
drawable
.
ic_download_update
),
null
,
null
,
null
);
mBtnDownloadStatus
.
setOnClickListener
(
new
View
.
OnClickListener
()
{
@Override
public
void
onClick
(
View
v
)
{
//업데이트 시작
Logger
.
d
(
TAG
,
"#####################update"
);
contentValidCheckAndDownload
(
mContentId
);
mDownloadingFlg
=
true
;
setDownloadStatus
();
}
});
mBtnOpenStatus
.
setVisibility
(
View
.
VISIBLE
);
mBtnOpenStatus
.
setText
(
getResources
().
getString
(
R
.
string
.
open
));
mBtnOpenStatus
.
setOnClickListener
(
new
View
.
OnClickListener
()
{
@Override
public
void
onClick
(
View
v
)
{
//콘텐츠 재생
Logger
.
d
(
TAG
,
"#####################open"
);
startContentViewActivity
(
mContentId
);
}
});
checkSubMenu
();
}
else
if
(
mDownloadedFlg
&&
!
mUpdatedFlg
)
{
mBtnOpenStatus
.
setVisibility
(
View
.
VISIBLE
);
mBtnOpenStatus
.
setText
(
getResources
().
getString
(
R
.
string
.
open
));
mBtnOpenStatus
.
setOnClickListener
(
new
View
.
OnClickListener
()
{
@Override
public
void
onClick
(
View
v
)
{
//콘텐츠 재생
startContentViewActivity
(
mContentId
);
}
});
checkSubMenu
();
if
(
ABVDataCache
.
getInstance
().
serviceOption
.
isPayment
())
{
mBtnDelete
.
setVisibility
(
View
.
VISIBLE
);
mBtnDelete
.
setOnClickListener
(
new
View
.
OnClickListener
()
{
@Override
public
void
onClick
(
View
v
)
{
showContentDeleteDialog
(
mContentDto
);
}
});
}
}
else
if
(
mPausedFlg
)
{
mBtnDownloadStatus
.
setVisibility
(
View
.
VISIBLE
);
mBtnDownloadStatus
.
setText
(
R
.
string
.
restart
);
mBtnDownloadStatus
.
setCompoundDrawablesWithIntrinsicBounds
(
getResources
().
getDrawable
(
R
.
drawable
.
ic_download_resume
),
null
,
null
,
null
);
mBtnDownloadStatus
.
setOnClickListener
(
new
View
.
OnClickListener
()
{
@Override
public
void
onClick
(
View
v
)
{
resumeContentDownload
(
mContentId
);
mDownloadingFlg
=
true
;
mPausedFlg
=
false
;
setDownloadStatus
();
}
});
mBtnOpenStatus
.
setVisibility
(
View
.
VISIBLE
);
mBtnOpenStatus
.
setText
(
getResources
().
getString
(
R
.
string
.
cancel
));
mBtnOpenStatus
.
setOnClickListener
(
new
View
.
OnClickListener
()
{
@Override
public
void
onClick
(
View
v
)
{
ContentDto
contentDto
=
contentDao
.
getContent
(
mContentId
);
contentDownloadCancel
(
contentDto
);
mPausedFlg
=
false
;
mDownloadingFlg
=
false
;
setDownloadStatus
();
}
});
}
if
(
isStreamingEnable
(
mContentDto
))
{
mBtnStreaming
.
setVisibility
(
View
.
VISIBLE
);
mBtnStreaming
.
setOnClickListener
(
new
View
.
OnClickListener
()
{
@Override
public
void
onClick
(
View
v
)
{
startStreamingActivity
(
mContentId
);
}
});
}
if
(
isNormalSize
())
{
// 携帯画面の場合、ボタンに納まらないので数が多い場合、文字を短くもしくはアイコンのみにする。上にスペースがあるが修正するとLayoutの全面見直しが必要。
int
visibleCount
=
getVisibleCount
(
mBtnOpenStatus
,
mBtnDownloadStatus
,
mBtnStreaming
);
if
(
visibleCount
==
2
)
{
if
(
mDownloadedFlg
&&
mUpdatedFlg
&&
!
mPausedFlg
&&
!
isStreamingOnly
(
mContentDto
))
{
mBtnDownloadStatus
.
setText
(
"Update"
);
}
else
{
mBtnDownloadStatus
.
setText
(
"DL"
);
}
}
else
if
(
visibleCount
>
2
)
{
mBtnOpenStatus
.
setText
(
""
);
mBtnDownloadStatus
.
setText
(
""
);
mBtnStreaming
.
setText
(
""
);
}
}
if
(
ABVDataCache
.
getInstance
().
serviceOption
.
isPayment
())
{
mBtnSubmenu
.
setVisibility
(
View
.
GONE
);
if
(
mContentDto
.
downloadedFlg
)
{
// DL済みの場合
}
else
if
(
mContentDto
.
downloadingFlg
)
{
// DL中の場合
}
else
if
(!
mContentDto
.
payFlg
// 無料の場合
||
AbstractLogic
.
getLogic
(
ContentLogic
.
class
).
isAllSubscribed
(
mContentDto
)
// 定期購読済み
||
!
StringUtil
.
isNullOrEmpty
(
mContentDto
.
productId
)
&&
mContentDto
.
purchaseState
==
0
)
{
// 単品購入済み
}
else
{
mBtnOpenStatus
.
setVisibility
(
View
.
GONE
);
mBtnDownloadStatus
.
setVisibility
(
View
.
GONE
);
mBtnInappPurchase
.
setVisibility
(
View
.
VISIBLE
);
mBtnInappPurchase
.
setText
(
mContentDto
.
price
);
mBtnInappPurchase
.
setFocusable
(
false
);
mBtnInappPurchase
.
setOnClickListener
(
new
View
.
OnClickListener
()
{
@Override
public
void
onClick
(
View
v
)
{
try
{
BillingHelper
.
getInstance
().
buy
(
v
,
mContentDto
.
productId
);
}
catch
(
Exception
e
)
{
Logger
.
e
(
TAG
,
"inapp launchPurchaseFlow failed."
,
e
);
Toast
.
makeText
(
ContentDetailViewActivity
.
this
,
R
.
string
.
billing_error_purchase_failed
,
Toast
.
LENGTH_SHORT
).
show
();
}
}
});
}
}
}
private
int
getVisibleCount
(
Button
...
buttons
)
{
int
count
=
0
;
for
(
Button
button
:
buttons
)
{
if
(
button
.
getVisibility
()
==
View
.
VISIBLE
)
{
count
++;
}
}
return
count
;
}
/**
* リスト画面設定
* @since 1.0.0
*/
private
void
setDetailList
()
{
mTxtMenutitle
.
setText
(
mContentName
);
mTxtMenutitle
.
requestFocus
();
// コンテンツリンク情報読込
try
{
mContentLinks
=
loadContentLinksJSON
(
mContentId
);
}
catch
(
Exception
e
)
{
Logger
.
e
(
TAG
,
"loadContentLinksJSON"
,
e
);
ABVToastUtil
.
showMakeText
(
getApplicationContext
(),
R
.
string
.
ERROR
,
Toast
.
LENGTH_SHORT
);
}
mListAdapter
=
new
ContentDetailListAdapter
(
this
,
R
.
layout
.
item_content_detail_render
,
mPages
);
mListView
.
setAdapter
(
mListAdapter
);
mListView
.
setDivider
(
null
);
mTxtContentDetail
=
(
TextView
)
findViewById
(
R
.
id
.
txt_content_detail
);
mTxtGroupInfo
=
(
TextView
)
findViewById
(
R
.
id
.
txt_group_info
);
mTxtCategoryInfo
=
(
TextView
)
findViewById
(
R
.
id
.
txt_category_info
);
String
groupInfo
=
null
;
for
(
int
i
=
0
;
i
<
mGroupInfo
.
size
();
i
++)
{
if
(
i
==
0
)
{
groupInfo
=
mGroupInfo
.
get
(
i
);
}
else
{
groupInfo
+=
", "
+
mGroupInfo
.
get
(
i
);
}
}
String
categoryInfo
=
null
;
for
(
int
i
=
0
;
i
<
mCategoryInfo
.
size
();
i
++)
{
if
(
i
==
0
)
{
categoryInfo
=
mCategoryInfo
.
get
(
i
);
}
else
{
categoryInfo
+=
", "
+
mCategoryInfo
.
get
(
i
);
}
}
if
(
ABVDataCache
.
getInstance
().
serviceOption
.
isPayment
()){
((
TextView
)
findViewById
(
R
.
id
.
txt_content_explain
)).
setText
(
mContentDetail
);
findViewById
(
R
.
id
.
sc_content_explain
).
setVisibility
(
View
.
VISIBLE
);
findViewById
(
R
.
id
.
contentNumberLayout
).
setVisibility
(
View
.
INVISIBLE
);
findViewById
(
R
.
id
.
rightSideInfoLayout
).
setVisibility
(
View
.
GONE
);
mTxtContentDetail
.
setVisibility
(
View
.
GONE
);
}
else
{
mTxtContentDetail
.
setMinLines
(
1
);
mTxtContentDetail
.
setText
(
mContentDetail
);
findViewById
(
R
.
id
.
sc_content_explain
).
setVisibility
(
View
.
GONE
);
findViewById
(
R
.
id
.
contentNumberLayout
).
setVisibility
(
View
.
VISIBLE
);
findViewById
(
R
.
id
.
rightSideInfoLayout
).
setVisibility
(
View
.
VISIBLE
);
mTxtContentDetail
.
setVisibility
(
View
.
VISIBLE
);
}
mTxtGroupInfo
.
setText
(
groupInfo
);
mTxtCategoryInfo
.
setText
(
categoryInfo
);
if
(
mContentLinks
==
null
||
ABVDataCache
.
getInstance
().
serviceOption
.
isPayment
())
{
mTabHost
.
getTabWidget
().
getChildAt
(
1
).
setVisibility
(
View
.
GONE
);
}
else
{
ProjectLogic
mProjectLogic
=
AbstractLogic
.
getLogic
(
ProjectLogic
.
class
);
boolean
isCommonContentForSelf
=
mProjectLogic
.
isCommonContent
(
mContentId
);
mLinkListItem
=
new
ArrayList
<>();
for
(
int
i
=
0
;
i
<
mContentLinks
.
length
();
i
++)
{
ContentLinkJSON
contentLinkJSON
=
new
ContentLinkJSON
(
mContentLinks
.
getJSONObject
(
i
));
ContentLinkAdapterDto
contentLinkDto
=
new
ContentLinkAdapterDto
();
makeContentLinkDto
(
contentLinkDto
,
contentLinkJSON
.
getContentId
(),
contentLinkJSON
.
getContentName
());
// 上でjsonのValidationを行っているのでここではないはず
if
(
isCommonContentForSelf
&&
!
mProjectLogic
.
isCommonContent
(
contentLinkDto
.
contentId
))
{
continue
;
}
if
(
contentLinkDto
.
deliveryStartDate
==
null
||
DateTimeUtil
.
getCurrentDate
().
after
(
contentLinkDto
.
deliveryStartDate
))
{
mLinkListItem
.
add
(
contentLinkDto
);
}
}
if
(
mLinkListItem
.
size
()
==
0
){
mTabHost
.
getTabWidget
().
getChildAt
(
1
).
setVisibility
(
View
.
GONE
);
}
else
{
mLinkAdapter
=
new
ContentDetailLinkAdapter
(
this
,
mLinkListItem
,
new
ContentDetailLinkAdapter
.
ContentLinkAdapterListener
()
{
@Override
public
void
onAllCheckChanged
(
boolean
allChecked
)
{
if
(
mLinkAdapter
.
getCheckableCount
()
!=
0
){
if
(
allChecked
)
{
mIconSelectAll
.
setBackgroundResource
(
R
.
drawable
.
icon_content_detail_check_deselected
);
mTxtSelectAll
.
setText
(
R
.
string
.
allDelete
);
}
else
{
mIconSelectAll
.
setBackgroundResource
(
R
.
drawable
.
icon_content_detail_check_selected
);
mTxtSelectAll
.
setText
(
R
.
string
.
allSelect
);
}
}
}
@Override
public
boolean
OnDownloadTransfer
(
long
contentId
,
ContentLinkAdapterDto
dto
)
{
boolean
result
=
true
;
//관련콘텐츠의 다운로드 처리
// 関連コンテンツのダウンロード処理
switch
(
dto
.
contentStatus
)
{
case
IMPOSSIBLE:
break
;
case
DONE:
break
;
case
POSSIBLE:
if
(
dto
.
selectable
)
{
ContentDto
contentDto
=
AbstractDao
.
getDao
(
ContentDao
.
class
).
getContent
(
contentId
);
contentOpenOrDownload
(
contentDto
);
}
else
{
contentValidCheckAndDownload
(
contentId
,
false
);
dto
.
contentStatus
=
ContentStatus
.
DOWNLOADING
;
dto
.
checkable
=
false
;
}
break
;
case
DOWNLOADING:
break
;
case
WAITING:
resumeContentDownload
(
contentId
);
break
;
case
STREAMING:
break
;
default
:
break
;
}
setRelRelatedDownVisibility
();
return
result
;
}
@Override
public
void
onViewTransfer
(
long
contentId
)
{
startContentViewActivity
(
contentId
);
}
});
mRelSelectAll
.
setOnClickListener
(
new
View
.
OnClickListener
()
{
@Override
public
void
onClick
(
View
v
)
{
if
(
mLinkAdapter
.
allCheck
)
{
mIconSelectAll
.
setBackgroundResource
(
R
.
drawable
.
icon_content_detail_check_selected
);
mTxtSelectAll
.
setText
(
R
.
string
.
allSelect
);
}
else
{
mIconSelectAll
.
setBackgroundResource
(
R
.
drawable
.
icon_content_detail_check_deselected
);
mTxtSelectAll
.
setText
(
R
.
string
.
allDelete
);
}
mLinkAdapter
.
allCheck
();
mLinkAdapter
.
notifyDataSetChanged
();
}
});
//관련 콘텐츠 전체 다운로드 처리
// 関連コンテンツの全体ダウンロード処理
mRelRelatedDown
.
setOnClickListener
(
new
View
.
OnClickListener
()
{
@Override
public
void
onClick
(
View
v
)
{
if
(
mLinkAdapter
.
getCheckedCount
()
==
0
)
{
ABVToastUtil
.
showMakeText
(
ContentDetailViewActivity
.
this
,
R
.
string
.
link_non_selected
,
Toast
.
LENGTH_SHORT
);
}
else
{
List
<
ContentLinkAdapterDto
>
pausedList
=
mLinkAdapter
.
getPausedList
();
if
(
pausedList
.
size
()
>
0
)
{
for
(
ContentLinkAdapterDto
dto
:
pausedList
)
{
for
(
ContentLinkAdapterDto
linkDto
:
mLinkListItem
)
{
if
(
linkDto
.
contentId
==
dto
.
contentId
)
{
linkDto
.
contentStatus
=
ContentStatus
.
DOWNLOADING
;
mLinkAdapter
.
notifyDataSetChanged
();
resumeContentDownload
(
dto
.
contentId
);
}
}
}
}
long
[]
downloadIds
=
mLinkAdapter
.
getDownloadList
();
startContentDownload
(
downloadIds
);
}
}
});
mGridView
.
setAdapter
(
mLinkAdapter
);
setRelRelatedDownVisibility
();
}
}
}
/**
* リスト画面のデータ設定
* @since 1.0.0
*/
private
void
contentDetailDown
()
{
setDetailList
();
setOnButtonEvent
();
setDetal
();
setDownloadStatus
();
if
(
mDownloadedFlg
)
{
checkSubMenu
();
}
else
{
mBtnSubmenu
.
setVisibility
(
View
.
GONE
);
}
}
@Override
public
void
onDownloadingContentZip
(
ContentZipDownloadNotification
notification
)
{
super
.
onDownloadingContentZip
(
notification
);
switch
(
notification
.
getDownloadStatus
())
{
case
Waiting:
break
;
case
Paused:
break
;
case
AutoPaused:
break
;
case
Initializing:
break
;
case
Failed:
break
;
case
None:
break
;
case
Downloading:
if
(
notification
.
getContentId
()
!=
mContentId
&&
mLinkListItem
!=
null
)
{
for
(
ContentLinkAdapterDto
dto
:
mLinkListItem
)
{
if
(
dto
.
contentId
==
notification
.
getContentId
()
&&
dto
.
contentStatus
!=
ContentStatus
.
DOWNLOADING
)
{
dto
.
contentStatus
=
ContentStatus
.
DOWNLOADING
;
break
;
}
}
runOnUiThread
(
new
Runnable
()
{
@Override
public
void
run
()
{
mLinkAdapter
.
notifyDataSetChanged
();
}
});
}
break
;
case
Succeeded:
if
(
notification
.
getContentId
()
==
mContentId
)
{
mDownloadedFlg
=
true
;
mDownloadingFlg
=
false
;
mPausedFlg
=
false
;
mUpdatedFlg
=
false
;
runOnUiThread
(
new
Runnable
()
{
@Override
public
void
run
()
{
setDownloadStatus
();
}
});
}
else
{
long
linkContentId
=
notification
.
getContentId
();
if
(
mLinkListItem
!=
null
)
{
for
(
ContentLinkAdapterDto
dto
:
mLinkListItem
)
{
if
(
dto
.
contentId
==
linkContentId
)
{
makeContentLinkDto
(
dto
,
linkContentId
,
dto
.
contentName
);
dto
.
contentStatus
=
ContentStatus
.
DONE
;
dto
.
checkable
=
false
;
}
}
}
runOnUiThread
(
new
Runnable
()
{
@Override
public
void
run
()
{
setRelRelatedDownVisibility
();
//プッシュメッセージを経由して、コンテンツダウンロードする場合対応
if
(
mLinkAdapter
!=
null
)
{
mLinkAdapter
.
notifyDataSetChanged
();
}
}
});
}
ActivityHandlingHelper
.
getInstance
().
setRequireHomeReload
(
true
);
break
;
case
Canceled:
if
(
notification
.
getContentId
()
!=
mContentId
)
{
long
linkContentId
=
notification
.
getContentId
();
if
(
mLinkListItem
!=
null
)
{
for
(
ContentLinkAdapterDto
dto
:
mLinkListItem
)
{
if
(
dto
.
contentId
==
linkContentId
)
{
dto
.
contentStatus
=
ContentStatus
.
POSSIBLE
;
dto
.
checkable
=
true
;
}
}
}
runOnUiThread
(
new
Runnable
()
{
@Override
public
void
run
()
{
setRelRelatedDownVisibility
();
mLinkAdapter
.
notifyDataSetChanged
();
}
});
}
break
;
default
:
break
;
}
}
@Override
protected
void
onStop
()
{
super
.
onStop
();
}
@Override
protected
void
onDestroy
()
{
super
.
onDestroy
();
Logger
.
v
(
TAG
,
"onDestroy()"
);
}
@Override
public
void
onResume
()
{
Logger
.
v
(
TAG
,
"onResume()"
);
super
.
onResume
();
mContentDto
=
AbstractDao
.
getDao
(
ContentDao
.
class
).
getContent
(
mContentId
);
setDownloadStatus
();
if
(
ABVDataCache
.
getInstance
().
serviceOption
.
isPayment
()
&&
BillingHelper
.
getInstance
().
requireInit
())
{
BillingHelper
.
getInstance
().
init
(
this
);
}
}
@Override
protected
void
onActivityResult
(
int
requestCode
,
int
resultCode
,
Intent
data
)
{
Logger
.
d
(
"onActivityResult"
);
if
(
ABVDataCache
.
getInstance
().
serviceOption
.
isPayment
())
{
if
(
BillingHelper
.
getInstance
().
handleActivityResult
(
requestCode
,
resultCode
,
data
))
{
Log
.
d
(
TAG
,
"onActivityResult handled by IABUtil."
);
}
else
{
super
.
onActivityResult
(
requestCode
,
resultCode
,
data
);
}
}
}
@Override
public
void
finish
()
{
// ホーム画面リロード
ActivityHandlingHelper
.
getInstance
().
setRequireHomeReload
(
true
);
super
.
finish
();
}
@Override
public
void
onConfigurationChanged
(
Configuration
newConfig
)
{
super
.
onConfigurationChanged
(
newConfig
);
if
(!
isNormalSize
())
{
int
widthPixels
=
(
int
)
(
getResources
().
getDisplayMetrics
().
widthPixels
*
0.9
)
;
int
heightPixels
=
(
int
)
(
getResources
().
getDisplayMetrics
().
heightPixels
*
0.9
);
WindowManager
.
LayoutParams
lp
=
getWindow
().
getAttributes
();
if
(
widthPixels
>
heightPixels
)
{
lp
.
width
=
heightPixels
;
lp
.
height
=
heightPixels
;
}
else
{
lp
.
width
=
widthPixels
;
lp
.
height
=
widthPixels
;
}
getWindow
().
setAttributes
(
lp
);
}
contentDetailDown
();
}
/**
* 指定したコンテンツIDのjson.txtの情報を返します。
* @param contentId
* @return JSONArray
* @throws IOException
* @throws AcmsException
*/
private
JSONArray
loadContentLinksJSON
(
long
contentId
)
throws
IOException
,
AcmsException
{
DownloadedContentInfoJSON
json
=
ContentFileUtil
.
getDownloadedContentInfoJSON
(
contentId
);
return
json
.
contentLinks
;
}
/**
* コンテンツの状態をチェックしてステータスを返します。
* @param contentDto
* @return
* @throws Exception
*/
private
ContentLinkAdapterDto
.
ContentStatus
getContentStatus
(
ContentDto
contentDto
)
{
// ローカルに存在しない場合、ダウンロード不可
if
(
contentDto
==
null
)
{
return
ContentLinkAdapterDto
.
ContentStatus
.
IMPOSSIBLE
;
}
// ダウンロード済みならば、ダウンロード済み
if
(
contentDto
.
downloadedFlg
)
{
return
ContentLinkAdapterDto
.
ContentStatus
.
DONE
;
}
if
(
isStreamingOnly
(
contentDto
))
{
// Streamingのみの場合
return
ContentLinkAdapterDto
.
ContentStatus
.
STREAMING
;
}
if
(
isStreamingEnable
(
contentDto
))
{
// Streamingが可能な場合、設定の優先に従って変更
int
tapActionOnDeliverySelect
=
PreferenceUtil
.
getInt
(
this
,
DefPrefKey
.
TAP_ACTION_ON_DELIVERY_SELECT
,
"2"
);
switch
(
tapActionOnDeliverySelect
)
{
case
DeliveryType
.
SELECT
:
return
ContentLinkAdapterDto
.
ContentStatus
.
POSSIBLE
;
case
DeliveryType
.
STREAMING
:
return
ContentLinkAdapterDto
.
ContentStatus
.
STREAMING
;
}
}
// ダウンロードしていなければ、ダウンロード可能
if
(!
contentDto
.
downloadingFlg
)
{
return
ContentLinkAdapterDto
.
ContentStatus
.
POSSIBLE
;
}
//-------- 以下、ダウンロード中のコンテンツのみ --------//
if
(
contentDto
.
downloadProgress
>
0
)
{
return
ContentLinkAdapterDto
.
ContentStatus
.
DOWNLOADING
;
}
else
{
return
ContentLinkAdapterDto
.
ContentStatus
.
WAITING
;
}
}
/**
* ContentLinkDtoを作成する。コンテンツIDとコンテンツの情報が取得できない時に表示するコンテンツ名を指定します。
* @param contentLinkDto
* @throws Exception
*/
private
void
makeContentLinkDto
(
ContentLinkAdapterDto
contentLinkDto
,
long
contentId
,
String
contentName
)
{
contentLinkDto
.
contentName
=
contentName
;
contentLinkDto
.
contentId
=
contentId
;
ContentDto
contentDto
=
contentDao
.
getContent
(
contentLinkDto
.
contentId
);
contentLinkDto
.
contentStatus
=
getContentStatus
(
contentDto
);
if
(
contentDto
!=
null
)
{
contentLinkDto
.
contentName
=
contentDto
.
contentName
;
contentLinkDto
.
thumbnailPath
=
contentDto
.
thumbnailNormalPath
;
contentLinkDto
.
contentId
=
contentDto
.
contentId
;
contentLinkDto
.
deliveryStartDate
=
contentDto
.
deliveryStartDate
;
//jeonghun Test
contentLinkDto
.
checkable
=
!
contentDto
.
downloadedFlg
&&
!
isStreamingOnly
(
contentDto
)
&&
!
contentDto
.
downloadingFlg
;
if
(
isStreamingEnable
(
contentDto
)
&&
PreferenceUtil
.
getInt
(
this
,
DefPrefKey
.
TAP_ACTION_ON_DELIVERY_SELECT
,
"2"
)
==
DeliveryType
.
SELECT
)
{
// Streaming選択が可能な場合、設定の優先に従って変更
contentLinkDto
.
selectable
=
true
;
}
}
}
/**
* 複数指定したコンテンツIDをダウンロードします。
* ダウンロードできないコンテンツがある場合、スキップされます。
* ダウンロードできないコンテンツが一つでもある場合、最後にメッセージを表示します。
* @param downloadIds
*/
private
void
startContentDownload
(
final
long
[]
downloadIds
)
{
try
{
showWifiDisconnectAlert
(
R
.
string
.
C_E_SYSTEM_0005
,
new
DialogInterface
.
OnClickListener
()
{
@Override
public
void
onClick
(
DialogInterface
dialog
,
int
which
)
{
boolean
allContentStart
=
true
;
try
{
for
(
int
i
=
0
;
i
<
downloadIds
.
length
;
i
++)
{
if
(
contentValidCheck
(
downloadIds
[
i
])
==
ContentCheckResultType
.
SUCCESS
)
{
if
(
mLinkListItem
!=
null
)
{
for
(
ContentLinkAdapterDto
linkDto
:
mLinkListItem
)
{
if
(
linkDto
.
contentId
==
downloadIds
[
i
])
{
linkDto
.
contentStatus
=
ContentStatus
.
DOWNLOADING
;
linkDto
.
checkable
=
false
;
contentDownloader
.
download
(
downloadIds
[
i
]);
mLinkAdapter
.
notifyDataSetChanged
();
}
}
}
}
else
{
allContentStart
=
false
;
}
}
if
(!
allContentStart
)
{
ErrorMessage
.
showErrorMessageDialog
(
ContentDetailViewActivity
.
this
,
R
.
string
.
app_name
,
ErrorCode
.
M003
);
}
}
catch
(
NetworkDisconnectedException
e
)
{
handleErrorMessageToast
(
ErrorCode
.
NETWORK
);
}
catch
(
Exception
e
)
{
Logger
.
e
(
TAG
,
"startContentDownload failed."
,
e
);
handleErrorMessageToast
(
ErrorCode
.
ERROR
);
}
}
},
new
DialogInterface
.
OnClickListener
()
{
@Override
public
void
onClick
(
DialogInterface
dialog
,
int
which
)
{
}
});
}
catch
(
NetworkDisconnectedException
e
)
{
handleErrorMessageToast
(
ErrorCode
.
NETWORK
);
}
}
private
void
startReaderContentDownload
(
final
long
[]
downloadIds
)
{
try
{
showWifiDisconnectAlert
(
R
.
string
.
C_E_SYSTEM_0005
,
new
DialogInterface
.
OnClickListener
()
{
@Override
public
void
onClick
(
DialogInterface
dialog
,
int
which
)
{
ArrayList
<
Long
>
successIds
=
readerContentDownload
(
mContractDto
,
downloadIds
);
for
(
long
contentId
:
successIds
)
{
if
(
mLinkListItem
!=
null
)
{
for
(
ContentLinkAdapterDto
linkDto
:
mLinkListItem
)
{
if
(
linkDto
.
contentId
==
contentId
)
{
linkDto
.
contentStatus
=
ContentStatus
.
DOWNLOADING
;
linkDto
.
checkable
=
false
;
mLinkAdapter
.
notifyDataSetChanged
();
}
}
}
}
}
},
new
DialogInterface
.
OnClickListener
()
{
@Override
public
void
onClick
(
DialogInterface
dialog
,
int
which
)
{
}
});
}
catch
(
NetworkDisconnectedException
e
)
{
ABVToastUtil
.
showMakeText
(
this
,
R
.
string
.
NETWORK
,
Toast
.
LENGTH_SHORT
);
}
}
@Override
public
boolean
onKeyUp
(
int
keyCode
,
KeyEvent
event
)
{
if
(
keyCode
==
KeyEvent
.
KEYCODE_BACK
)
{
if
(
contentLinkFlag
&&
contentDownloader
.
getActiveCountWithoutWaiting
()
>
0
)
{
showDownloadPauseDialog
();
}
else
{
finish
();
}
}
return
super
.
onKeyUp
(
keyCode
,
event
);
}
//일시 정지 중인 콘텐츠를 상세화면에서도 다운로드 가능
private
void
resumeContentDownload
(
long
downPausedIds
)
{
try
{
contentDownloader
.
resume
(
downPausedIds
);
}
catch
(
NetworkDisconnectedException
e
)
{
handleErrorMessageToast
(
ErrorCode
.
NETWORK
);
}
catch
(
AcmsException
e
)
{
Logger
.
e
(
TAG
,
"AcmsException"
,
e
);
handleErrorMessageToast
(
e
);
}
}
// サブメニュー表示
public
void
showSubMenuDialog
(
View
anchor
)
{
final
ContentDto
contentDto
=
contentDao
.
getContent
(
mContentId
);
final
List
<
ContentCheckListTypeItem
>
members
=
createSubMenuItems
(
contentDto
,
false
);
ArrayList
<
String
>
menuNameList
=
new
ArrayList
<>();
for
(
ContentCheckListTypeItem
member
:
members
){
menuNameList
.
add
(
member
.
name
);
}
final
ABVPopupListWindow
popupWindow
=
new
ABVPopupListWindow
(
this
);
popupWindow
.
setWidth
(
getRDimensionSize
(
R
.
dimen
.
popup_size_large
));
popupWindow
.
setRepresentNames
(
menuNameList
);
popupWindow
.
setOnItemClickListener
(
new
OnItemClickListener
()
{
@Override
public
void
onItemClick
(
AdapterView
<?>
parent
,
View
view
,
int
position
,
long
id
)
{
switch
(
members
.
get
(
position
).
id
)
{
case
SubMenuType
.
CONTENT_DELETE
:
showContentDeleteDialog
(
contentDto
);
break
;
case
SubMenuType
.
USER_INFO_COPY
:
getABVUIDataCache
().
srcContentId
=
contentDto
.
contentId
;
ABVToastUtil
.
showMakeText
(
ContentDetailViewActivity
.
this
,
AndroidStringUtil
.
format
(
ContentDetailViewActivity
.
this
,
R
.
string
.
complete_state
,
R
.
string
.
copy
),
Toast
.
LENGTH_SHORT
);
break
;
case
SubMenuType
.
USER_INFO_PASTE
:
copyUserInfoCheckOrientation
(
getABVUIDataCache
().
srcContentId
,
contentDto
.
contentId
);
break
;
}
popupWindow
.
dismiss
();
}
});
popupWindow
.
showAsDropDown
(
anchor
);
}
public
void
showContentDeleteDialog
(
final
ContentDto
contentDto
)
{
ABookAlertDialog
contentsDeleteDialog
=
AlertDialogUtil
.
deleteContentAlertDialog
(
this
);
contentsDeleteDialog
.
setNegativeButton
(
R
.
string
.
cancel
,
null
);
contentsDeleteDialog
.
setPositiveButton
(
R
.
string
.
confirm
,
new
DialogInterface
.
OnClickListener
()
{
@Override
public
void
onClick
(
DialogInterface
dialog
,
int
which
)
{
if
(
contentDelete
(
contentDto
))
{
// ダウンロードボタンの表示変更
mPausedFlg
=
false
;
mDownloadingFlg
=
false
;
mDownloadedFlg
=
false
;
setDownloadStatus
();
}
}
});
showAlertDialog
(
contentsDeleteDialog
);
}
private
void
showDownloadPauseDialog
()
{
ABookAlertDialog
contentsDeleteDialog
=
AlertDialogUtil
.
createAlertDialog
(
this
,
getString
(
R
.
string
.
confirm
),
getString
(
R
.
string
.
confirm_download_pause
));
contentsDeleteDialog
.
setNegativeButton
(
R
.
string
.
cancel
,
null
);
contentsDeleteDialog
.
setPositiveButton
(
R
.
string
.
confirm
,
new
DialogInterface
.
OnClickListener
()
{
@Override
public
void
onClick
(
DialogInterface
dialog
,
int
which
)
{
contentDownloader
.
pauseAll
();
// FIXME: なぜここですべてPauseにしている
finish
();
}
});
showAlertDialog
(
contentsDeleteDialog
);
}
private
void
setRelRelatedDownVisibility
(){
if
(
mLinkAdapter
==
null
||
mLinkAdapter
.
getCheckableCount
()
==
0
)
{
mRelSelectAll
.
setVisibility
(
View
.
GONE
);
mRelRelatedDown
.
setVisibility
(
View
.
GONE
);
}
}
/**
* 発行者コンテンツの表示・非表示
*
* @param view
*/
public
void
onClickPublisherAll
(
View
view
)
{
Logger
.
d
(
TAG
,
"onClickPublisherAll: %s"
,
view
.
getId
());
}
}
ABVJE_UI_Android/src/jp/agentec/abook/abv/ui/home/activity/GuideViewActivity.java
View file @
3e307bda
...
...
@@ -176,7 +176,6 @@ public class GuideViewActivity extends ABVContentViewActivity {
private
ContentJSON
mContentJSON
;
// コンテンツのJSONデータ
private
PDFIndexInfoJSON
mPDFIndexInfoJSON
;
// PDFインデックスのJSONデータ
private
PDFLinkJSON
mPDFLinkJSON
;
// PDFリンクのJSONデータ
private
PageInfoJSON
mPageInfoJSON
;
// オーサリング画面の各ページサイズのJSONデータ
private
Size
mBaseFileSize
;
...
...
ABVJE_UI_Android/src/jp/agentec/abook/abv/ui/home/adapter/ContentDetailLinkAdapter.java
deleted
100644 → 0
View file @
32ec4e3a
package
jp
.
agentec
.
abook
.
abv
.
ui
.
home
.
adapter
;
import
java.util.ArrayList
;
import
java.util.List
;
import
jp.agentec.abook.abv.cl.util.BitmapUtil
;
import
jp.agentec.abook.abv.launcher.android.R
;
import
jp.agentec.abook.abv.ui.common.activity.ABVAuthenticatedActivity
;
import
jp.agentec.abook.abv.ui.home.dto.ContentLinkAdapterDto
;
import
jp.agentec.abook.abv.ui.home.dto.ContentLinkAdapterDto.ContentStatus
;
import
android.content.Context
;
import
android.graphics.Bitmap
;
import
android.graphics.Bitmap.Config
;
import
android.graphics.drawable.BitmapDrawable
;
import
android.graphics.drawable.Drawable
;
import
android.view.LayoutInflater
;
import
android.view.View
;
import
android.view.ViewGroup
;
import
android.widget.BaseAdapter
;
import
android.widget.Button
;
import
android.widget.CompoundButton
;
import
android.widget.ImageView
;
import
android.widget.TextView
;
import
android.widget.ToggleButton
;
/**
* @author Chae
*
*/
public
class
ContentDetailLinkAdapter
extends
BaseAdapter
{
private
Context
context
;
private
LayoutInflater
inflater
;
private
List
<
ContentLinkAdapterDto
>
listItem
;
public
boolean
allCheck
=
false
;
private
ContentLinkAdapterListener
listener
;
private
final
int
mThumbnailSize
;
public
interface
ContentLinkAdapterListener
{
/**
* コンテンツリストが全てチェックの状態になった場合<br>
* または、コンテンツリストが全てチェックの状態じゃなくなった場合に呼び出されます。
* @param allChecked true:全てチェック、false:全てチェックではない
*/
void
onAllCheckChanged
(
boolean
allChecked
);
boolean
OnDownloadTransfer
(
long
contentId
,
ContentLinkAdapterDto
dto
);
void
onViewTransfer
(
long
contentId
);
}
public
ContentDetailLinkAdapter
(
Context
context
,
List
<
ContentLinkAdapterDto
>
listItem
,
ContentLinkAdapterListener
listener
)
{
this
.
context
=
context
;
inflater
=
(
LayoutInflater
)
context
.
getSystemService
(
Context
.
LAYOUT_INFLATER_SERVICE
);
mThumbnailSize
=
context
.
getResources
().
getDimensionPixelSize
(
R
.
dimen
.
detail_view_thumbnail_size
);
this
.
listItem
=
listItem
;
this
.
listener
=
listener
;
}
@Override
public
int
getCount
()
{
return
listItem
.
size
();
}
@Override
public
ContentLinkAdapterDto
getItem
(
int
position
)
{
return
listItem
.
get
(
position
);
}
@Override
public
long
getItemId
(
int
position
)
{
return
position
;
}
@Override
public
View
getView
(
int
position
,
View
convertView
,
ViewGroup
parent
)
{
if
(
null
==
convertView
)
{
convertView
=
inflater
.
inflate
(
R
.
layout
.
item_content_detail_link_render
,
null
);
}
final
ContentLinkAdapterDto
dto
=
listItem
.
get
(
position
);
// int heightPixels = (int) (context.getResources().getDisplayMetrics().heightPixels * 0.4 * 0.55 * 0.5);
// LinearLayout mainLayout = (LinearLayout)convertView.findViewById(R.id.linear_detail_render);
// mainLayout.getLayoutParams().height = heightPixels;
ImageView
imgThumbnail
=
(
ImageView
)
convertView
.
findViewById
(
R
.
id
.
img_thumbnail
);
if
(
imgThumbnail
.
getDrawable
()
!=
null
)
{
((
BitmapDrawable
)
imgThumbnail
.
getDrawable
()).
getBitmap
().
recycle
();
}
Bitmap
resized
=
BitmapUtil
.
getResizedBitmap
(
listItem
.
get
(
position
).
thumbnailPath
,
mThumbnailSize
,
mThumbnailSize
,
Config
.
RGB_565
);
// nullの場合サムネイルなしイメージを表示
if
(
resized
==
null
||
dto
.
contentStatus
==
ContentStatus
.
IMPOSSIBLE
)
{
resized
=
BitmapUtil
.
getResizedBitmapResource
(
context
.
getResources
(),
R
.
drawable
.
not_exist_thumbnail
,
120
,
120
,
Config
.
RGB_565
);
}
imgThumbnail
.
setImageBitmap
(
resized
);
imgThumbnail
.
setPadding
(
0
,
0
,
1
,
1
);
TextView
tvContentName
=
(
TextView
)
convertView
.
findViewById
(
R
.
id
.
txt_content_name
);
tvContentName
.
setText
(
dto
.
contentName
);
final
int
p
=
position
;
final
ToggleButton
cbDownload
=
(
ToggleButton
)
convertView
.
findViewById
(
R
.
id
.
chk_download
);
if
(
dto
.
checkable
){
cbDownload
.
setOnCheckedChangeListener
(
new
CompoundButton
.
OnCheckedChangeListener
()
{
@Override
public
void
onCheckedChanged
(
CompoundButton
buttonView
,
boolean
isChecked
)
{
if
(
isChecked
)
{
listItem
.
get
(
p
).
checked
=
true
;
if
(
getCheckedCount
()
==
getCheckableCount
())
{
allCheck
=
true
;
listener
.
onAllCheckChanged
(
true
);
}
}
else
{
if
(
allCheck
)
{
allCheck
=
false
;
listener
.
onAllCheckChanged
(
false
);
}
listItem
.
get
(
p
).
checked
=
false
;
}
}
});
}
if
(
dto
.
checkable
)
{
cbDownload
.
setVisibility
(
View
.
VISIBLE
);
cbDownload
.
setChecked
(
dto
.
checked
);
}
else
{
cbDownload
.
setVisibility
(
View
.
GONE
);
cbDownload
.
setChecked
(
false
);
dto
.
checked
=
false
;
}
Button
btnDownload
=
(
Button
)
convertView
.
findViewById
(
R
.
id
.
btn_download_status
);
//noinspection VariableNotUsedInsideIf
if
(
dto
.
contentStatus
!=
null
)
{
makeContentStatusText
(
btnDownload
,
dto
);
makeContentStatus
(
listItem
.
get
(
position
).
contentId
,
btnDownload
,
dto
,
cbDownload
);
}
return
convertView
;
}
/**
* コンテンツリストを全てチェックの状態にします。<br>
* 全てチェックされている場合はチェックが全て外れます。
*/
public
void
allCheck
()
{
for
(
ContentLinkAdapterDto
dto
:
listItem
)
{
if
(
dto
.
checkable
)
{
dto
.
checked
=
!
allCheck
;
}
}
}
/**
* textViewをContentStatusの状態に合わせて編集します。
*
* @param btnDownload
* @param dto
*/
private
void
makeContentStatusText
(
Button
btnDownload
,
ContentLinkAdapterDto
dto
)
{
String
download
=
context
.
getString
(
R
.
string
.
download
);
switch
(
dto
.
contentStatus
)
{
case
IMPOSSIBLE:
btnDownload
.
setEnabled
(
false
);
btnDownload
.
setText
(
download
);
break
;
case
DONE:
btnDownload
.
setEnabled
(
true
);
btnDownload
.
setText
(
context
.
getString
(
R
.
string
.
open
));
break
;
case
POSSIBLE:
btnDownload
.
setEnabled
(
true
);
if
(
dto
.
selectable
)
{
btnDownload
.
setText
(
download
+
"/"
+
context
.
getString
(
R
.
string
.
streaming
));
}
else
{
btnDownload
.
setText
(
download
);
}
break
;
case
DOWNLOADING:
btnDownload
.
setEnabled
(
false
);
btnDownload
.
setText
(
context
.
getString
(
R
.
string
.
downloading
));
break
;
case
WAITING:
// もうこのパターンはありえない? Jang
btnDownload
.
setEnabled
(
false
);
btnDownload
.
setText
(
context
.
getString
(
R
.
string
.
waiting
));
break
;
case
STREAMING:
btnDownload
.
setEnabled
(
true
);
btnDownload
.
setText
(
context
.
getString
(
R
.
string
.
streaming
));
break
;
default
:
break
;
}
}
private
void
makeContentStatus
(
final
long
contentId
,
final
Button
btnDownload
,
final
ContentLinkAdapterDto
dto
,
final
ToggleButton
cbDownload
)
{
final
ContentStatus
contentStatus
=
dto
.
contentStatus
;
btnDownload
.
setOnClickListener
(
new
View
.
OnClickListener
()
{
@Override
public
void
onClick
(
View
v
)
{
if
(
contentStatus
==
ContentStatus
.
POSSIBLE
||
contentStatus
==
ContentStatus
.
WAITING
)
{
if
(!
listener
.
OnDownloadTransfer
(
contentId
,
dto
)){
// ダウンロードできなかった場合、ステータスを戻す
dto
.
contentStatus
=
ContentStatus
.
POSSIBLE
;
dto
.
checkable
=
true
;
}
ContentDetailLinkAdapter
.
this
.
notifyDataSetChanged
();
}
else
if
(
contentStatus
==
ContentStatus
.
DONE
)
{
listener
.
onViewTransfer
(
contentId
);
}
else
if
(
contentStatus
==
ContentStatus
.
STREAMING
)
{
((
ABVAuthenticatedActivity
)
context
).
startStreamingActivity
(
contentId
);
}
}
});
switch
(
contentStatus
)
{
case
IMPOSSIBLE:
btnDownload
.
setCompoundDrawablesWithIntrinsicBounds
(
null
,
null
,
null
,
null
);
cbDownload
.
setEnabled
(
false
);
break
;
case
DONE:
btnDownload
.
setCompoundDrawablesWithIntrinsicBounds
(
context
.
getResources
().
getDrawable
(
R
.
drawable
.
icon_contentdetail_open
),
null
,
null
,
null
);
cbDownload
.
setVisibility
(
View
.
INVISIBLE
);
cbDownload
.
setEnabled
(
true
);
break
;
case
POSSIBLE:
btnDownload
.
setVisibility
(
View
.
VISIBLE
);
int
resId
=
dto
.
selectable
?
R
.
drawable
.
ic_download_streaming_select
:
R
.
drawable
.
icon_contentdetail_download
;
btnDownload
.
setCompoundDrawablesWithIntrinsicBounds
(
context
.
getResources
().
getDrawable
(
resId
),
null
,
null
,
null
);
cbDownload
.
setEnabled
(
true
);
break
;
case
DOWNLOADING:
btnDownload
.
setCompoundDrawablesWithIntrinsicBounds
(
null
,
null
,
null
,
null
);
cbDownload
.
setEnabled
(
false
);
break
;
case
WAITING:
btnDownload
.
setVisibility
(
View
.
VISIBLE
);
btnDownload
.
setCompoundDrawablesWithIntrinsicBounds
(
context
.
getResources
().
getDrawable
(
R
.
drawable
.
ic_download_resume
),
null
,
null
,
null
);
cbDownload
.
setEnabled
(
false
);
break
;
case
STREAMING:
btnDownload
.
setVisibility
(
View
.
VISIBLE
);
btnDownload
.
setCompoundDrawablesWithIntrinsicBounds
(
context
.
getResources
().
getDrawable
(
R
.
drawable
.
icon_contentdetail_streaming
),
null
,
null
,
null
);
cbDownload
.
setEnabled
(
dto
.
checkable
);
break
;
default
:
break
;
}
}
/**
* チェックされているコンテンツIDを返します。
* @return
*/
public
long
[]
getDownloadList
()
{
List
<
ContentLinkAdapterDto
>
downloadlist
=
new
ArrayList
<>();
for
(
ContentLinkAdapterDto
dto
:
listItem
)
{
//다운로드 일시정지 중인 콘텐츠는 다운로드 리스트에서 제외(contentLogic.resumeDownload 로 따로 재개)
if
(
dto
.
checkable
&&
dto
.
checked
&&
!
dto
.
contentStatus
.
equals
(
ContentLinkAdapterDto
.
ContentStatus
.
WAITING
))
{
downloadlist
.
add
(
dto
);
}
}
long
[]
downloadIds
=
new
long
[
downloadlist
.
size
()];
for
(
int
i
=
0
;
i
<
downloadIds
.
length
;
i
++)
{
downloadIds
[
i
]
=
downloadlist
.
get
(
i
).
contentId
;
}
return
downloadIds
;
}
/**
* チェックできるコンテンツの個数を返します。
* @return
*/
public
int
getCheckableCount
()
{
int
count
=
0
;
for
(
ContentLinkAdapterDto
dto
:
listItem
)
{
if
(
dto
.
checkable
)
{
count
++;
}
}
return
count
;
}
//2012 12 17 Contents Link else if문 제거
/**
* チェックされているコンテンツの個数を返します。
* @return
*/
public
int
getCheckedCount
()
{
int
count
=
0
;
for
(
ContentLinkAdapterDto
dto
:
listItem
)
{
if
(
dto
.
checkable
&&
dto
.
checked
)
{
count
++;
}
}
return
count
;
}
//다운로드 일시 정지중인 콘텐츠 수 체크
public
int
getDownPauseCheckedCount
()
{
int
count
=
0
;
for
(
ContentLinkAdapterDto
dto
:
listItem
)
{
if
(
dto
.
contentStatus
.
equals
(
ContentLinkAdapterDto
.
ContentStatus
.
WAITING
))
{
count
++;
}
}
return
count
;
}
//다운로드 일시 정지중인 콘텐츠 아이디 체크
public
List
<
ContentLinkAdapterDto
>
getPausedList
()
{
List
<
ContentLinkAdapterDto
>
downloadlist
=
new
ArrayList
<>();
for
(
ContentLinkAdapterDto
dto
:
listItem
)
{
if
(
dto
.
contentStatus
.
equals
(
ContentLinkAdapterDto
.
ContentStatus
.
WAITING
))
{
downloadlist
.
add
(
dto
);
}
}
return
downloadlist
;
}
}
ABVJE_UI_Android/src/jp/agentec/abook/abv/ui/home/adapter/ContentDetailListAdapter.java
deleted
100644 → 0
View file @
32ec4e3a
package
jp
.
agentec
.
abook
.
abv
.
ui
.
home
.
adapter
;
import
java.util.ArrayList
;
import
jp.agentec.abook.abv.cl.util.BitmapUtil
;
import
jp.agentec.abook.abv.launcher.android.R
;
import
jp.agentec.abook.abv.ui.common.appinfo.AppColor
;
import
jp.agentec.abook.abv.ui.common.dto.ContentPageSerializableDto
;
import
android.content.Context
;
import
android.graphics.Bitmap
;
import
android.graphics.Bitmap.Config
;
import
android.graphics.Color
;
import
android.graphics.drawable.GradientDrawable
;
import
android.view.LayoutInflater
;
import
android.view.View
;
import
android.view.ViewGroup
;
import
android.widget.BaseAdapter
;
import
android.widget.ImageView
;
import
android.widget.TextView
;
/**
* 詳細リストデータ
* @author Minhyuk Seok
* @version 1.0.0
*/
public
class
ContentDetailListAdapter
extends
BaseAdapter
{
Context
context
;
LayoutInflater
Inflater
;
ArrayList
<
ContentPageSerializableDto
>
listItem
;
private
final
int
mThumbnailSize
;
int
layout
;
public
ContentDetailListAdapter
(
Context
context
,
int
alayout
,
ArrayList
<
ContentPageSerializableDto
>
detailPage
)
{
this
.
context
=
context
;
Inflater
=
(
LayoutInflater
)
context
.
getSystemService
(
Context
.
LAYOUT_INFLATER_SERVICE
);
this
.
listItem
=
detailPage
;
layout
=
alayout
;
mThumbnailSize
=
context
.
getResources
().
getDimensionPixelSize
(
R
.
dimen
.
content_thumbnail_image_size
);
}
@Override
public
int
getCount
()
{
if
(
listItem
==
null
)
{
return
0
;
}
else
{
return
listItem
.
size
();
}
}
@Override
public
long
getItemId
(
int
position
)
{
return
position
;
}
public
void
setItemId
(
int
position
)
{
}
@Override
public
View
getView
(
int
position
,
View
convertView
,
ViewGroup
parent
)
{
if
(
convertView
==
null
)
{
convertView
=
Inflater
.
inflate
(
layout
,
parent
,
false
);
}
// setStripeColor(context, convertView, position);
ImageView
image
=
(
ImageView
)
convertView
.
findViewById
(
R
.
id
.
img_content_detail_list
);
final
Bitmap
resized
=
BitmapUtil
.
getResizedBitmap
(
listItem
.
get
(
position
).
getPageThumbnailPath
(),
mThumbnailSize
,
mThumbnailSize
,
Config
.
RGB_565
);
image
.
setImageBitmap
(
resized
);
image
.
setAdjustViewBounds
(
true
);
image
.
setScaleType
(
ImageView
.
ScaleType
.
FIT_CENTER
);
image
.
setPadding
(
0
,
0
,
1
,
1
);
GradientDrawable
g
=
new
GradientDrawable
(
GradientDrawable
.
Orientation
.
TL_BR
,
new
int
[]
{
Color
.
WHITE
,
Color
.
WHITE
,
AppColor
.
getBackground
()});
//noinspection deprecation(API16から非推奨になった。無視)
image
.
setBackgroundDrawable
(
g
);
TextView
comment
=
(
TextView
)
convertView
.
findViewById
(
R
.
id
.
txt_content_detail_list_comment
);
comment
.
setText
(
listItem
.
get
(
position
).
getPageText
());
return
convertView
;
}
@Override
public
Object
getItem
(
int
position
)
{
return
null
;
}
}
\ No newline at end of file
ABVJE_UI_Android/src/jp/agentec/abook/abv/ui/home/adapter/PushMessageContractListAdapter.java
deleted
100644 → 0
View file @
32ec4e3a
package
jp
.
agentec
.
abook
.
abv
.
ui
.
home
.
adapter
;
import
java.util.List
;
import
jp.agentec.abook.abv.bl.common.Constant.ReaderConstant.ReceivePushMessage
;
import
jp.agentec.abook.abv.bl.dto.ContractDto
;
import
jp.agentec.abook.abv.launcher.android.R
;
import
android.content.Context
;
import
android.view.LayoutInflater
;
import
android.view.View
;
import
android.view.ViewGroup
;
import
android.widget.BaseAdapter
;
import
android.widget.CompoundButton
;
import
android.widget.Switch
;
import
android.widget.TextView
;
public
class
PushMessageContractListAdapter
extends
BaseAdapter
{
private
Context
context
;
private
LayoutInflater
inflater
;
public
List
<
ContractDto
>
listItem
;
public
PushMessageContractListAdapter
(
Context
context
,
List
<
ContractDto
>
listItem
)
{
this
.
context
=
context
;
this
.
listItem
=
listItem
;
inflater
=
(
LayoutInflater
)
context
.
getSystemService
(
Context
.
LAYOUT_INFLATER_SERVICE
);
for
(
ContractDto
contractDto
:
listItem
){
if
(
ReceivePushMessage
.
NOT_SET
==
contractDto
.
receivePushMessage
){
contractDto
.
receivePushMessage
=
ReceivePushMessage
.
REFUSE
;
}
}
}
@Override
public
int
getCount
()
{
return
listItem
.
size
();
}
@Override
public
Object
getItem
(
int
position
)
{
return
listItem
.
get
(
position
);
}
@Override
public
long
getItemId
(
int
position
)
{
return
position
;
}
@Override
public
View
getView
(
int
position
,
View
convertView
,
ViewGroup
parent
)
{
ViewHolder
holder
;
if
(
null
==
convertView
)
{
convertView
=
inflater
.
inflate
(
R
.
layout
.
item_push_message_contract
,
null
);
holder
=
new
ViewHolder
();
holder
.
tvContractName
=
(
TextView
)
convertView
.
findViewById
(
R
.
id
.
tv_contract_name
);
holder
.
swContract
=
(
Switch
)
convertView
.
findViewById
(
R
.
id
.
sw_contract
);
convertView
.
setTag
(
holder
);
}
else
{
holder
=
(
ViewHolder
)
convertView
.
getTag
();
}
final
ContractDto
contractDto
=
listItem
.
get
(
position
);
holder
.
tvContractName
.
setText
(
contractDto
.
companyName
+
"["
+
contractDto
.
siteId
+
"-"
+
contractDto
.
contractId
+
"]"
);
holder
.
swContract
.
setOnCheckedChangeListener
(
new
CompoundButton
.
OnCheckedChangeListener
()
{
@Override
public
void
onCheckedChanged
(
CompoundButton
buttonView
,
boolean
isChecked
)
{
if
(
isChecked
){
contractDto
.
receivePushMessage
=
ReceivePushMessage
.
PERMIT
;
}
else
{
contractDto
.
receivePushMessage
=
ReceivePushMessage
.
REFUSE
;
}
}
});
if
(
ReceivePushMessage
.
PERMIT
==
contractDto
.
receivePushMessage
){
holder
.
swContract
.
setChecked
(
true
);
}
else
{
holder
.
swContract
.
setChecked
(
false
);
}
return
convertView
;
}
private
static
class
ViewHolder
{
TextView
tvContractName
;
Switch
swContract
;
}
}
ABVJE_UI_Android/src/jp/agentec/abook/abv/ui/home/dialog/HtmlViewDialog.java
deleted
100644 → 0
View file @
32ec4e3a
package
jp
.
agentec
.
abook
.
abv
.
ui
.
home
.
dialog
;
import
jp.agentec.abook.abv.launcher.android.R
;
import
jp.agentec.abook.abv.ui.common.view.ABVDialog
;
import
android.annotation.SuppressLint
;
import
android.content.Context
;
import
android.view.View
;
import
android.view.Window
;
import
android.webkit.WebSettings
;
import
android.webkit.WebView
;
import
android.widget.TextView
;
public
class
HtmlViewDialog
extends
ABVDialog
{
public
HtmlViewDialog
(
Context
context
,
String
linkUrl
)
{
super
(
context
,
android
.
R
.
style
.
Theme_Holo_Light_Dialog_NoActionBar
);
init
(
linkUrl
);
}
@SuppressLint
(
"SetJavaScriptEnabled"
)
private
void
init
(
String
linkUrl
)
{
requestWindowFeature
(
Window
.
FEATURE_NO_TITLE
);
setContentView
(
R
.
layout
.
dialog_htmlview
);
setCanceledOnTouchOutside
(
false
);
findViewById
(
R
.
id
.
close_dialog
).
setOnClickListener
(
new
View
.
OnClickListener
()
{
@Override
public
void
onClick
(
View
v
)
{
dismiss
();
}
});
WebView
webView
=
(
WebView
)
findViewById
(
R
.
id
.
htmlWebView
);
webView
.
loadUrl
(
linkUrl
);
// //ブラウザの描画領域を対象としたイベントをフック
WebSettings
settings
=
webView
.
getSettings
();
settings
.
setSupportMultipleWindows
(
true
);
// 新しいウィンドウを開くイベントを取得する
settings
.
setLoadsImagesAutomatically
(
true
);
// イメージを自動的にロードする
settings
.
setBuiltInZoomControls
(
true
);
// ズーム機能を有効にする
settings
.
setSupportZoom
(
true
);
// ズーム機能を有効にする
settings
.
setJavaScriptEnabled
(
true
);
// JavaScriptを有効にする
settings
.
setLoadWithOverviewMode
(
true
);
// 画面の横幅にページの横幅を合わせる
settings
.
setUseWideViewPort
(
true
);
// 画面の横幅にページの横幅を合わせる
}
public
void
setToolbarTitle
(
String
title
)
{
TextView
titleView
=
(
TextView
)
findViewById
(
R
.
id
.
dialog_title
);
titleView
.
setText
(
title
);
}
}
ABVJE_UI_Android/src/jp/agentec/abook/abv/ui/home/dialog/PushMessageSettingDialog.java
deleted
100644 → 0
View file @
32ec4e3a
package
jp
.
agentec
.
abook
.
abv
.
ui
.
home
.
dialog
;
import
android.app.Activity
;
import
android.view.View
;
import
android.view.Window
;
import
android.widget.ListView
;
import
android.widget.TextView
;
import
android.widget.Toast
;
import
java.util.List
;
import
jp.agentec.abook.abv.bl.common.CommonExecutor
;
import
jp.agentec.abook.abv.bl.common.exception.AcmsException
;
import
jp.agentec.abook.abv.bl.common.exception.NetworkDisconnectedException
;
import
jp.agentec.abook.abv.bl.common.log.Logger
;
import
jp.agentec.abook.abv.bl.data.dao.AbstractDao
;
import
jp.agentec.abook.abv.bl.data.dao.ContractDao
;
import
jp.agentec.abook.abv.bl.dto.ContractDto
;
import
jp.agentec.abook.abv.bl.logic.AbstractLogic
;
import
jp.agentec.abook.abv.bl.logic.ContractLogic
;
import
jp.agentec.abook.abv.cl.push.FcmManager
;
import
jp.agentec.abook.abv.launcher.android.R
;
import
jp.agentec.abook.abv.ui.common.constant.ErrorMessage
;
import
jp.agentec.abook.abv.ui.common.helper.ProgressDialogHelper
;
import
jp.agentec.abook.abv.ui.common.util.ABVToastUtil
;
import
jp.agentec.abook.abv.ui.common.view.ABVDialog
;
import
jp.agentec.abook.abv.ui.home.adapter.PushMessageContractListAdapter
;
/**
* Readerアプリへコンテンツを共有する際に設定する情報の画面
* @author jang
*
*/
public
class
PushMessageSettingDialog
extends
ABVDialog
{
private
Activity
activity
;
private
ContractLogic
logic
;
public
PushMessageSettingDialog
(
Activity
activity
)
{
super
(
activity
,
android
.
R
.
style
.
Theme_Holo_Light_Dialog_NoActionBar
);
this
.
activity
=
activity
;
logic
=
AbstractLogic
.
getLogic
(
ContractLogic
.
class
);
init
();
}
private
void
init
()
{
ContractDao
contractDao
=
AbstractDao
.
getDao
(
ContractDao
.
class
);
List
<
ContractDto
>
contractList
=
contractDao
.
getListByUsablePushMessage
();
requestWindowFeature
(
Window
.
FEATURE_NO_TITLE
);
setContentView
(
R
.
layout
.
push_message_setting
);
setCanceledOnTouchOutside
(
false
);
ListView
lvContract
=
(
ListView
)
findViewById
(
R
.
id
.
list_contract
);
// キャンセルボタン
findViewById
(
R
.
id
.
cancel
).
setOnClickListener
(
new
View
.
OnClickListener
()
{
@Override
public
void
onClick
(
View
v
)
{
dismiss
();
}
});
if
(
contractList
.
size
()
>
0
){
final
PushMessageContractListAdapter
adapter
=
new
PushMessageContractListAdapter
(
getContext
(),
contractList
);
lvContract
.
setAdapter
(
adapter
);
findViewById
(
R
.
id
.
ok
).
setOnClickListener
(
new
View
.
OnClickListener
()
{
@Override
public
void
onClick
(
View
v
)
{
ProgressDialogHelper
.
showProgressPopup
(
activity
,
true
);
final
String
fcmToken
=
FcmManager
.
getFcmToken
(
getContext
());
if
(
fcmToken
==
null
||
fcmToken
.
equals
(
"noneId"
))
{
ABVToastUtil
.
showMakeText
(
getContext
(),
R
.
string
.
fcm_not_supported
,
Toast
.
LENGTH_SHORT
);
}
else
{
CommonExecutor
.
execute
(
new
Runnable
()
{
@Override
public
void
run
()
{
try
{
logic
.
updateReceivePushMessage
(
getContext
().
getString
(
R
.
string
.
repository_fqdn
),
fcmToken
,
adapter
.
listItem
);
dismiss
();
}
catch
(
AcmsException
e
)
{
ErrorMessage
.
showErrorMessageToast
(
getContext
(),
e
);
Logger
.
e
(
"PushMessageSettingDialog"
,
e
);
}
catch
(
NetworkDisconnectedException
e
)
{
ABVToastUtil
.
showMakeText
(
getContext
(),
R
.
string
.
request_network_connection
,
Toast
.
LENGTH_SHORT
);
}
finally
{
ProgressDialogHelper
.
closeProgressPopup
();
}
}
});
}
}
});
}
else
{
((
TextView
)
findViewById
(
R
.
id
.
tv_summary
)).
setText
(
getContext
().
getString
(
R
.
string
.
push_message_contract_not_exist
));
findViewById
(
R
.
id
.
ok
).
setOnClickListener
(
new
View
.
OnClickListener
()
{
@Override
public
void
onClick
(
View
v
)
{
dismiss
();
}
});
}
}
}
ABVJE_UI_Android/src/jp/agentec/abook/abv/ui/home/dto/ContentLinkAdapterDto.java
deleted
100644 → 0
View file @
32ec4e3a
package
jp
.
agentec
.
abook
.
abv
.
ui
.
home
.
dto
;
import
java.util.Date
;
public
class
ContentLinkAdapterDto
{
public
String
thumbnailPath
;
public
String
contentName
;
public
long
contentId
;
public
ContentStatus
contentStatus
;
public
boolean
checked
=
false
;
public
boolean
checkable
=
false
;
public
boolean
selectable
=
false
;
public
Date
deliveryStartDate
;
public
enum
ContentStatus
{
IMPOSSIBLE
,
DONE
,
POSSIBLE
,
DOWNLOADING
,
WAITING
,
STREAMING
}
}
ABVJE_UI_Android/src/jp/agentec/abook/abv/ui/home/helper/ActivityHandlingHelper.java
View file @
3e307bda
...
...
@@ -83,7 +83,6 @@ import jp.agentec.abook.abv.ui.common.dto.ContentPageSerializableDto;
import
jp.agentec.abook.abv.ui.common.util.ABVToastUtil
;
import
jp.agentec.abook.abv.ui.common.util.AlertDialogUtil
;
import
jp.agentec.abook.abv.ui.common.vo.ContentMyList
;
import
jp.agentec.abook.abv.ui.home.activity.ContentDetailViewActivity
;
import
jp.agentec.abook.abv.ui.home.activity.ProjectListActivity
;
import
jp.agentec.abook.abv.ui.home.activity.ProjectMeetingListActivity
;
import
jp.agentec.abook.abv.ui.home.activity.ProjectRelatedContentActivity
;
...
...
@@ -94,7 +93,6 @@ import jp.agentec.abook.abv.ui.viewer.activity.EnqueteWebViewActivity;
import
jp.agentec.abook.abv.ui.viewer.activity.HTMLWebViewActivity
;
import
jp.agentec.abook.abv.ui.viewer.activity.HTMLXWalkWebViewActivity
;
import
jp.agentec.abook.abv.ui.viewer.activity.ImageViewActivity
;
import
jp.agentec.abook.abv.ui.viewer.activity.PanoViewActivity
;
import
jp.agentec.abook.abv.ui.viewer.activity.ParentWebViewActivity
;
import
jp.agentec.abook.abv.ui.viewer.activity.PreviewActivity
;
import
jp.agentec.abook.abv.ui.viewer.activity.VideoViewActivity
;
...
...
@@ -361,139 +359,8 @@ public class ActivityHandlingHelper extends ABookHelper implements RemoteObserve
}
}
public
void
contentDetailActivityMove
(
long
contentId
,
int
prePage
)
{
ABVAuthenticatedActivity
activity
=
getCurrentActivity
();
contentDetailActivityMove
(
activity
,
contentId
,
activity
.
getClass
().
getSimpleName
(),
prePage
,
false
,
null
);
}
public
void
contentDetailActivityMove
(
final
Context
context
,
final
long
contentId
,
final
String
className
,
final
int
pre_page
,
final
boolean
contentLinkFlag
,
final
Callback
callback
)
{
CommonExecutor
.
execute
(
new
Runnable
()
{
@Override
public
void
run
()
{
try
{
ContentDto
contentDto
=
contentDao
.
getContent
(
contentId
);
ContentDto
detail
;
// PDFコンテンツ以外は詳細を取得しにいかない
if
(
contentDto
.
contentType
==
null
||
ContentJSON
.
KEY_PDF_TYPE
.
equals
(
contentDto
.
contentType
.
toLowerCase
(
Locale
.
US
)))
{
detail
=
contentLogic
.
getContentDetail
(
contentId
);
}
else
{
detail
=
contentDto
;
}
if
(
detail
!=
null
)
{
callContentDetailActivity
(
context
,
detail
,
className
,
pre_page
,
contentLinkFlag
);
if
(
callback
!=
null
)
{
callback
.
callback
(
null
);
}
}
else
{
contentDownloader
.
downloadContentDetail
(
contentId
);
}
}
catch
(
NetworkDisconnectedException
e
)
{
if
(
callback
!=
null
)
{
callback
.
callback
(
ErrorCode
.
NETWORK
);
}
}
catch
(
Exception
e
)
{
Logger
.
e
(
TAG
,
"Exception "
+
e
);
if
(
callback
!=
null
)
{
callback
.
callback
(
ErrorCode
.
E107
);
}
}
}
});
}
// ActivityView에서 사용할수 있기 위하여 callContentDetailActivity 추가
// 상세화면에서 이전화면 이동시 Bug수정
private
void
callContentDetailActivity
(
Context
context
,
final
ContentDto
detail
,
final
String
className
,
int
pre_page
,
boolean
contentLinkFlag
)
{
Intent
intent
=
new
Intent
();
intent
.
setClassName
(
context
.
getPackageName
(),
ContentDetailViewActivity
.
class
.
getName
());
if
(
contentLinkFlag
)
{
intent
.
setFlags
(
Intent
.
FLAG_ACTIVITY_NO_HISTORY
);
}
if
(
context
instanceof
PanoViewActivity
)
{
intent
.
setFlags
(
Intent
.
FLAG_ACTIVITY_CLEAR_TOP
|
Intent
.
FLAG_ACTIVITY_NEW_TASK
);
}
String
dateFormat
=
"yyyy'"
+
context
.
getResources
().
getString
(
R
.
string
.
date_format_year
)
+
"'MM'"
+
context
.
getResources
().
getString
(
R
.
string
.
date_format_month
)
+
"'dd'"
+
context
.
getResources
().
getString
(
R
.
string
.
date_format_day
)
+
"'HH:mm:ss"
;
intent
.
putExtra
(
ABookKeys
.
CONTENT_ID
,
detail
.
contentId
);
intent
.
putExtra
(
"ThumbnailNormalPath"
,
detail
.
thumbnailNormalPath
);
intent
.
putExtra
(
"ContentName"
,
detail
.
contentName
);
intent
.
putExtra
(
"ContentDetail"
,
detail
.
contentDetail
);
intent
.
putExtra
(
"DeliveryStartDate"
,
DateTimeUtil
.
toString
(
detail
.
deliveryStartDate
,
dateFormat
));
intent
.
putExtra
(
"DeliveryEndDate"
,
DateTimeUtil
.
toString
(
detail
.
deliveryEndDate
,
dateFormat
));
intent
.
putExtra
(
"ContentSize"
,
detail
.
contentSize
);
intent
.
putExtra
(
"LastDeliveryDate"
,
DateTimeUtil
.
toString
(
detail
.
lastDeliveryDate
,
dateFormat
));
intent
.
putExtra
(
"ContentType"
,
detail
.
contentType
);
intent
.
putExtra
(
"ContractContentId"
,
detail
.
contractContentId
);
// 콘텐츠 정보 (콘텐츠 경고 ?)
intent
.
putExtra
(
"ContentAlertLevel"
,
detail
.
alertMessageLevel
);
intent
.
putExtra
(
"AllPageNum"
,
detail
.
allPageNum
);
intent
.
putExtra
(
"DownloadedFlg"
,
detail
.
downloadedFlg
);
intent
.
putExtra
(
"DownloadingFlg"
,
detail
.
downloadingFlg
);
intent
.
putExtra
(
"UpdatedFlg"
,
detail
.
updatedFlg
);
intent
.
putExtra
(
"FromClassName"
,
className
);
boolean
pdfSendMailFlg
=
false
;
ContractLogic
contractLgic
=
AbstractLogic
.
getLogic
(
ContractLogic
.
class
);
if
(
contractLgic
.
getPdfSendMail
()
&&
detail
.
pdfSendMailFlg
&&
detail
.
contentType
.
equals
(
ContentJSON
.
KEY_PDF_TYPE
))
{
pdfSendMailFlg
=
true
;
}
intent
.
putExtra
(
"PdfSendMailFlg"
,
pdfSendMailFlg
);
intent
.
putExtra
(
"PrintFlg"
,
detail
.
printFlg
);
intent
.
putExtra
(
"ReaderShareFlg"
,
detail
.
readerShareFlg
);
intent
.
putExtra
(
"HideFlg"
,
detail
.
hideFlg
);
DownloadStatusType
type
=
detail
.
getDownloadStatus
();
if
(
type
==
DownloadStatusType
.
Paused
)
{
intent
.
putExtra
(
"PausedFlg"
,
true
);
}
else
{
intent
.
putExtra
(
"PausedFlg"
,
false
);
}
if
(
pre_page
!=
-
1
)
{
intent
.
putExtra
(
"pre_page"
,
pre_page
);
}
intent
.
putExtra
(
"ContentLinkFlag"
,
contentLinkFlag
);
if
(
ContentMyList
.
searchDivisionType
!=
null
)
{
intent
.
putExtra
(
"seartSelect"
,
ContentMyList
.
searchDivisionType
.
type
());
intent
.
putExtra
(
"seartComment"
,
ContentMyList
.
searchKeyword
);
}
ArrayList
<
ContentPageSerializableDto
>
spages
=
new
ArrayList
<>();
if
(
detail
.
pages
!=
null
)
{
for
(
int
i
=
0
;
i
<
detail
.
pages
.
size
()
&&
i
<
6
;
i
++)
{
ContentPageSerializableDto
pagedata
=
new
ContentPageSerializableDto
();
pagedata
.
setPageText
(
detail
.
pages
.
get
(
i
).
pageText
);
pagedata
.
setPageThumbnailPath
(
detail
.
pages
.
get
(
i
).
getPageThumbnailPath
());
spages
.
add
(
pagedata
);
}
}
intent
.
putExtra
(
"Pages"
,
spages
);
// 그룹, 장르 정보
long
contentId
=
detail
.
contentId
;
ArrayList
<
String
>
groupList
;
ArrayList
<
String
>
categoryList
;
groupList
=
AbstractLogic
.
getLogic
(
GroupLogic
.
class
).
getExistContentsGroupInfo
(
contentId
);
categoryList
=
AbstractLogic
.
getLogic
(
CategoryLogic
.
class
).
getExistContentsCategoryInfo
(
contentId
);
intent
.
putStringArrayListExtra
(
"GroupInfo"
,
groupList
);
intent
.
putStringArrayListExtra
(
"CategoryInfo"
,
categoryList
);
if
(
context
instanceof
PanoViewActivity
)
{
((
Activity
)
context
).
finish
();
}
context
.
startActivity
(
intent
);
}
private
void
startActivity
(
Context
context
,
Intent
intent
,
NaviConsts
ABVNavi
,
Integer
flags
,
long
contentId
,
String
contentType
,
String
path
)
throws
Exception
{
contentRefresher
.
stopRefresh
();
// 新着更新を停止する
// 360°用のWebサーバが動作している場合停止
PanoViewHelper
.
getInstance
().
callStopPanoServer
();
if
(
intent
==
null
)
{
intent
=
new
Intent
();
}
...
...
@@ -514,11 +381,6 @@ public class ActivityHandlingHelper extends ABookHelper implements RemoteObserve
intent
.
setClass
(
context
,
ImageViewActivity
.
class
);
}
else
if
(
contentType
.
equals
(
ContentJSON
.
KEY_MOVIE_TYPE
))
{
// 動画ファイル
intent
.
setClass
(
context
,
VideoViewActivity
.
class
);
}
else
if
(
contentType
.
equals
(
ContentJSON
.
KEY_PANO_MOVIE_TYPE
)
&&
Build
.
VERSION
.
SDK_INT
<
Build
.
VERSION_CODES
.
LOLLIPOP
)
{
// 360°動画(5.0未満)
intent
.
setClass
(
context
,
PanoViewActivity
.
class
);
intent
.
putExtra
(
"path"
,
path
);
intent
.
putExtra
(
"contentId"
,
contentId
);
context
.
startActivity
(
intent
);
}
else
if
(
contentType
.
equals
(
ContentJSON
.
KEY_MUSIC_TYPE
))
{
// 音声ファイル
intent
.
setClass
(
context
,
AudioPlayActivity
.
class
);
}
else
if
(
contentType
.
equals
(
ContentJSON
.
KEY_HTML_TYPE
))
{
// HTMLファイル
...
...
@@ -1365,7 +1227,8 @@ public class ActivityHandlingHelper extends ABookHelper implements RemoteObserve
}
else
{
handler
.
post
(
new
Runnable
()
{
@Override
public
void
run
()
{
showDownloadConfirm
(
contentId
,
contentDto
.
contentName
);
public
void
run
()
{
showDownloadConfirm
(
contentId
,
contentDto
.
contentName
);
}
});
}
...
...
ABVJE_UI_Android/src/jp/agentec/abook/abv/ui/home/helper/PanoViewHelper.java
deleted
100644 → 0
View file @
32ec4e3a
package
jp
.
agentec
.
abook
.
abv
.
ui
.
home
.
helper
;
import
android.app.Activity
;
import
android.content.Context
;
import
android.widget.Toast
;
import
java.io.IOException
;
import
java.util.ArrayList
;
import
java.util.Arrays
;
import
java.util.Date
;
import
java.util.HashMap
;
import
java.util.List
;
import
java.util.Map
;
import
fi.iki.elonen.NanoHTTPD
;
import
jp.agentec.abook.abv.bl.common.ABVEnvironment
;
import
jp.agentec.abook.abv.bl.common.Callback
;
import
jp.agentec.abook.abv.bl.common.Constant
;
import
jp.agentec.abook.abv.bl.common.log.Logger
;
import
jp.agentec.abook.abv.bl.data.dao.AbstractDao
;
import
jp.agentec.abook.abv.bl.data.dao.ContentDao
;
import
jp.agentec.abook.abv.bl.dto.ContentDto
;
import
jp.agentec.abook.abv.bl.logic.AbstractLogic
;
import
jp.agentec.abook.abv.bl.logic.ContentObjectLogLogic
;
import
jp.agentec.abook.abv.bl.logic.ContentReadingLogLogic
;
import
jp.agentec.abook.abv.bl.net.PanoServer
;
import
jp.agentec.abook.abv.cl.environment.NetworkAdapter
;
import
jp.agentec.abook.abv.cl.util.ContentLogUtil
;
import
jp.agentec.abook.abv.cl.util.PreferenceUtil
;
import
jp.agentec.abook.abv.launcher.android.R
;
import
jp.agentec.abook.abv.ui.common.activity.ABVContentViewActivity
;
import
jp.agentec.abook.abv.ui.common.appinfo.AppDefType
;
import
jp.agentec.abook.abv.ui.common.util.ABVToastUtil
;
import
jp.agentec.abook.abv.ui.viewer.activity.HTMLWebViewActivity
;
import
jp.agentec.adf.util.DateTimeFormat
;
import
jp.agentec.adf.util.DateTimeUtil
;
import
jp.agentec.adf.util.FileUtil
;
/**
* Created by jang on 2016/03/07.
*/
public
class
PanoViewHelper
extends
ABookHelper
{
private
static
final
String
TAG
=
PanoViewHelper
.
class
.
getSimpleName
();
private
static
PanoViewHelper
panoViewHelper
=
null
;
private
List
<
PanoServer
>
panoServerList
=
new
ArrayList
<>();
public
static
synchronized
PanoViewHelper
getInstance
()
{
if
(
panoViewHelper
==
null
)
{
panoViewHelper
=
new
PanoViewHelper
();
}
return
panoViewHelper
;
}
public
void
startPanoContent
(
Context
context
,
String
path
,
long
contentId
)
{
// ローカルIPアドレス取得
String
ipAddress
=
NetworkAdapter
.
getInstance
().
getLocalIpAddress
();
if
(
ipAddress
==
null
)
{
Logger
.
e
(
TAG
,
"unable to get local ip. Wi-Fi Network Not Available."
);
ABVToastUtil
.
showMakeText
(
context
,
R
.
string
.
C_E_SYSTEM_0004
,
Toast
.
LENGTH_LONG
);
return
;
}
// Webサーバ開始
int
port
=
context
.
getResources
().
getInteger
(
R
.
integer
.
pano_web_server_port
);
boolean
isStart
=
false
;
for
(
int
i
=
0
;
i
<
20
;
i
++)
{
// 最大20までポート番号を増やす
if
(
startPanoServer
(
context
,
ipAddress
,
port
,
contentId
,
path
))
{
isStart
=
true
;
break
;
}
port
++;
}
if
(!
isStart
)
{
// 10回行ってもすべてPortが埋まっている場合はエラーとする
ABVToastUtil
.
showMakeText
(
context
,
R
.
string
.
C_E_SYSTEM_0001
,
Toast
.
LENGTH_LONG
);
return
;
}
// Chromeを起動し、起動したWebServerのアドレスを渡す。
startChrome
(
context
,
"http://"
+
ipAddress
+
":"
+
port
+
"/"
+
contentId
+
"/?app=android"
);
}
private
boolean
startPanoServer
(
final
Context
context
,
String
ipAddress
,
int
port
,
final
Long
contentId
,
String
path
)
{
final
PanoServer
panoServer
=
new
PanoServer
(
ipAddress
,
port
,
contentId
,
FileUtil
.
getParentPath
(
path
)
+
"/"
,
!
Logger
.
isDebugEnabled
(),
false
,
Arrays
.
asList
(
"Android"
,
"Chrome"
),
new
Callback
()
{
int
lastPageNo
=
0
;
Date
lastPageStartDate
=
null
;
Integer
readingLogId
=
null
;
@Override
public
Object
callback
(
Object
ret
)
{
if
(
ret
instanceof
Map
)
{
Map
<
String
,
String
>
param
=
(
Map
<
String
,
String
>)
ret
;
return
doParameter
(
param
,
context
,
contentId
,
lastPageNo
,
readingLogId
,
lastPageStartDate
,
new
Callback
()
{
@Override
public
Object
callback
(
Object
ret
)
{
Map
<
String
,
Object
>
map
=
(
Map
<
String
,
Object
>)
ret
;
if
(
map
.
containsKey
(
"lastPageNo"
))
{
lastPageNo
=
(
int
)
map
.
get
(
"lastPageNo"
);
}
if
(
map
.
containsKey
(
"lastPageStartDate"
))
{
lastPageStartDate
=
(
Date
)
map
.
get
(
"lastPageStartDate"
);
}
if
(
map
.
containsKey
(
"readingLogId"
))
{
readingLogId
=
(
Integer
)
map
.
get
(
"readingLogId"
);
}
return
null
;
}
});
}
else
if
(
ret
instanceof
Long
)
{
// onStop
Long
contentId
=
(
Long
)
ret
;
// srcContentIdと同じはずなので使わない
ContentLogUtil
.
getInstance
().
endContentPageReadLog
(
contentId
,
lastPageNo
,
readingLogId
);
AbstractLogic
.
getLogic
(
ContentReadingLogLogic
.
class
).
endContentReadLog
(
contentId
);
}
return
null
;
}
});
try
{
panoServer
.
start
(
NanoHTTPD
.
SOCKET_READ_TIMEOUT
,
false
);
// メインスレッド終了後も起動し続ける場合false
addPanoServerList
(
panoServer
);
return
true
;
}
catch
(
IOException
e
)
{
Logger
.
e
(
TAG
,
"The server could not start."
,
e
);
stopPanoServer
(
panoServer
);
return
false
;
}
}
public
String
doParameter
(
Map
<
String
,
String
>
param
,
Context
context
,
long
contentId
,
Integer
lastPageNo
,
Integer
readingLogId
,
Date
lastPageStartDate
,
Callback
callback
)
{
String
uri
=
param
.
get
(
PanoServer
.
URI
);
Long
dstContentId
=
Long
.
valueOf
(
param
.
get
(
"contentId"
));
Integer
pageNo
=
param
.
containsKey
(
"pageNo"
)?
Integer
.
valueOf
(
param
.
get
(
"pageNo"
))
-
1
:
0
;
// 1スタートを0スタート
if
(
uri
.
startsWith
(
PanoServer
.
CONTENTLINK
))
{
int
result
=
ContentViewHelper
.
getInstance
().
linkDownloadChecked
(
dstContentId
,
pageNo
);
Logger
.
d
(
TAG
,
"linkDownloadChecked result=%s"
,
result
);
if
(
result
==
ContentViewHelper
.
LinkContentStatus
.
NoExist
)
{
return
context
.
getString
(
R
.
string
.
msg_require_content_refresh
);
}
ContentLogUtil
.
getInstance
().
endContentPageReadLog
(
contentId
,
lastPageNo
,
readingLogId
);
if
(
result
==
ContentViewHelper
.
LinkContentStatus
.
DownloadedContent
)
{
Activity
currentActivity
=
ActivityHandlingHelper
.
getInstance
().
getContentViewActivity
();
// HTMLWebViewActivityの場合はfinish()を実施して、コンテンツを開く
if
(
currentActivity
instanceof
HTMLWebViewActivity
)
{
currentActivity
.
finish
();
}
ActivityHandlingHelper
.
getInstance
().
startContentActivity
(
dstContentId
,
pageNo
);
}
else
{
int
prePage
=
0
;
ABVContentViewActivity
viewActivity
=
ActivityHandlingHelper
.
getInstance
().
getContentViewActivity
();
if
(
viewActivity
!=
null
)
{
prePage
=
viewActivity
.
getCurrentPageNumber
();
}
ActivityHandlingHelper
.
getInstance
().
contentDetailActivityMove
(
dstContentId
,
prePage
);
ContentDto
contentDto
=
AbstractDao
.
getDao
(
ContentDao
.
class
).
getContent
(
dstContentId
);
return
PanoServer
.
OK
+
"."
+
String
.
format
(
context
.
getString
(
R
.
string
.
msg_require_content_download
),
(
contentDto
==
null
?
""
:
contentDto
.
contentName
));
}
}
else
if
(
uri
.
startsWith
(
PanoServer
.
DETAILLOG
))
{
if
(
readingLogId
==
null
)
{
// 開始
readingLogId
=
ContentLogUtil
.
getInstance
().
startContentReadLog
(
context
,
contentId
,
PreferenceUtil
.
getUserPref
(
context
,
AppDefType
.
DefPrefKey
.
PERMISSION_ACCESS_LOCATION
,
false
));
}
AbstractLogic
.
getLogic
(
ContentObjectLogLogic
.
class
).
insertContentObjectLog
(
contentId
,
readingLogId
,
pageNo
,
param
);
}
else
if
(
uri
.
startsWith
(
PanoServer
.
MOVEPAGE
))
{
// ブラウザから送られてきた時間は使わず、アプリの時間を用いる
if
(
readingLogId
==
null
)
{
// 開始ページ
readingLogId
=
ContentLogUtil
.
getInstance
().
startContentReadLog
(
context
,
contentId
,
PreferenceUtil
.
getUserPref
(
context
,
AppDefType
.
DefPrefKey
.
PERMISSION_ACCESS_LOCATION
,
false
));
ContentLogUtil
.
getInstance
().
startContentPageReadLog
(
contentId
,
readingLogId
,
pageNo
);
}
else
{
if
(
param
.
get
(
"readingEndDate"
)
!=
null
)
{
// 終了時刻有
ContentLogUtil
.
getInstance
().
endContentPageReadLog
(
contentId
,
pageNo
,
readingLogId
);
}
else
{
ContentLogUtil
.
getInstance
().
endContentPageReadLog
(
contentId
,
lastPageNo
,
readingLogId
);
// crosswalkのときもjsではローカルサーバに送るが受取がないためここで終了を呼び出す。ただしローカルサーバを使う場合2重に処理が走る。
ContentLogUtil
.
getInstance
().
startContentPageReadLog
(
contentId
,
readingLogId
,
pageNo
);
}
}
String
[]
readingStartDate
=
param
.
get
(
"readingStartDate"
).
split
(
","
);
Date
pageStartDate
=
DateTimeUtil
.
toDate
(
readingStartDate
[
0
],
readingStartDate
[
1
],
DateTimeFormat
.
yyyyMMddHHmmss_hyphen
);
if
(
lastPageStartDate
==
null
||
lastPageStartDate
.
before
(
pageStartDate
))
{
lastPageStartDate
=
pageStartDate
;
lastPageNo
=
pageNo
;
}
}
Map
<
String
,
Object
>
ret
=
new
HashMap
<
String
,
Object
>();
if
(
lastPageStartDate
!=
null
)
{
ret
.
put
(
"lastPageStartDate"
,
lastPageStartDate
);
}
if
(
lastPageNo
!=
null
)
{
ret
.
put
(
"lastPageNo"
,
lastPageNo
);
}
if
(
readingLogId
!=
null
)
{
ret
.
put
(
"readingLogId"
,
readingLogId
);
}
callback
.
callback
(
ret
);
return
null
;
}
private
void
addPanoServerList
(
PanoServer
addPanoServer
)
{
for
(
int
i
=
panoServerList
.
size
()
-
1
;
i
>=
0
;
i
--)
{
// 終了したものがあればListから除去
PanoServer
panoServer
=
panoServerList
.
get
(
i
);
if
(!
panoServer
.
isAlive
())
{
panoServerList
.
remove
(
i
);
}
}
panoServerList
.
add
(
addPanoServer
);
}
private
void
stopPanoServer
(
PanoServer
panoServer
)
{
if
(
panoServer
!=
null
)
{
Logger
.
i
(
TAG
,
"stop pano server."
);
panoServer
.
stop
();
panoServerList
.
remove
(
panoServer
);
}
}
public
void
callStopPanoServer
()
{
for
(
PanoServer
panoServer
:
panoServerList
)
{
panoServer
.
callStop
();
}
}
public
void
stopAllPanoServer
()
{
Logger
.
i
(
TAG
,
"stop all pano server."
);
for
(
int
i
=
panoServerList
.
size
()
-
1
;
i
>=
0
;
i
--)
{
PanoServer
panoServer
=
panoServerList
.
get
(
i
);
panoServer
.
stop
();
panoServerList
.
remove
(
i
);
}
}
public
boolean
hasAliveServer
()
{
if
(
panoServerList
.
isEmpty
())
{
return
false
;
}
for
(
PanoServer
panoServer
:
panoServerList
)
{
if
(!
panoServer
.
isCloseWaiting
())
{
return
true
;
}
}
return
false
;
}
}
ABVJE_UI_Android/src/jp/agentec/abook/abv/ui/home/view/BreadCrumbButton.java
deleted
100644 → 0
View file @
32ec4e3a
package
jp
.
agentec
.
abook
.
abv
.
ui
.
home
.
view
;
import
jp.agentec.abook.abv.launcher.android.R
;
import
android.content.Context
;
import
android.graphics.Color
;
import
android.widget.Button
;
/**
* パンくず履歴用のボタン
* @author jang
*
*/
public
class
BreadCrumbButton
extends
Button
{
private
BreadCrumbButton
(
Context
context
)
{
super
(
context
);
}
public
BreadCrumbButton
(
Context
context
,
String
name
)
{
super
(
context
);
this
.
name
=
name
;
setText
(
name
);
setTextColor
(
Color
.
BLACK
);
setBackgroundResource
(
R
.
drawable
.
btn_breadcrumbs
);
setPadding
(
10
,
0
,
40
,
0
);
}
public
int
level
;
public
long
dtoId
;
public
String
name
;
}
ABVJE_UI_Android/src/jp/agentec/abook/abv/ui/home/view/CustomListPreference.java
deleted
100644 → 0
View file @
32ec4e3a
package
jp
.
agentec
.
abook
.
abv
.
ui
.
home
.
view
;
import
android.content.Context
;
import
android.os.Bundle
;
import
android.preference.ListPreference
;
import
android.util.AttributeSet
;
/**
* Created by ThanhChung on 2016/06/02.
*/
public
class
CustomListPreference
extends
ListPreference
{
private
Context
mContext
;
private
boolean
isHideDialog
;
public
CustomListPreference
(
Context
context
)
{
super
(
context
);
mContext
=
context
;
}
public
CustomListPreference
(
Context
context
,
AttributeSet
attrs
)
{
super
(
context
,
attrs
);
mContext
=
context
;
}
public
void
setHideDialog
(
boolean
isHideDialog
)
{
this
.
isHideDialog
=
isHideDialog
;
}
@Override
protected
void
showDialog
(
Bundle
state
)
{
if
(!
isHideDialog
)
{
super
.
showDialog
(
state
);
}
}
@Override
protected
void
onDialogClosed
(
boolean
positiveResult
)
{
super
.
onDialogClosed
(
positiveResult
);
}
}
ABVJE_UI_Android/src/jp/agentec/abook/abv/ui/viewer/activity/ContentViewActivity.java
View file @
3e307bda
...
...
@@ -5003,94 +5003,6 @@ public class ContentViewActivity extends ABVContentViewActivity {
}
//2012 12 17 Contents link by jeonghun
private
void
linkDownloadChecked
(
final
long
contentId
,
int
page
)
{
Logger
.
i
(
TAG
,
"linkDownloadChecked targetContentId="
+
contentId
+
" targetPage="
+
page
);
int
result
=
ContentViewHelper
.
getInstance
().
linkDownloadChecked
(
contentId
,
page
);
switch
(
result
)
{
case
LinkContentStatus
.
FolderLock
:
{
// フォルダーロックしている状態でかつリンク先のコンテンツが別のフォルダーにある
ABookAlertDialog
linkLockDialog
=
AlertDialogUtil
.
createAlertDialog
(
this
,
R
.
string
.
content_link
);
linkLockDialog
.
setMessage
(
R
.
string
.
link_lock_folder
);
linkLockDialog
.
setPositiveButton
(
R
.
string
.
confirm
,
new
DialogInterface
.
OnClickListener
()
{
@Override
public
void
onClick
(
DialogInterface
dialog
,
int
whichButton
)
{
dialog
.
dismiss
();
}
});
showAlertDialog
(
linkLockDialog
);
}
break
;
case
LinkContentStatus
.
NoExist
:
{
// コンテンツが存在しない
ABookAlertDialog
linknonServerDialog
=
AlertDialogUtil
.
createAlertDialog
(
this
,
R
.
string
.
content_link
);
linknonServerDialog
.
setMessage
(
R
.
string
.
link_new_nonexits
);
linknonServerDialog
.
setPositiveButton
(
R
.
string
.
confirm
,
new
DialogInterface
.
OnClickListener
()
{
@Override
public
void
onClick
(
DialogInterface
dialog
,
int
whichButton
)
{
dialog
.
dismiss
();
}
});
showAlertDialog
(
linknonServerDialog
);
}
break
;
case
LinkContentStatus
.
BeforeReleaseDate
:
{
// 公開日前
ABookAlertDialog
linknonServerDialog
=
AlertDialogUtil
.
createAlertDialog
(
this
,
R
.
string
.
content_link
);
linknonServerDialog
.
setMessage
(
R
.
string
.
reader_content_download_404
);
linknonServerDialog
.
setPositiveButton
(
R
.
string
.
confirm
,
new
DialogInterface
.
OnClickListener
()
{
@Override
public
void
onClick
(
DialogInterface
dialog
,
int
whichButton
)
{
dialog
.
dismiss
();
}
});
showAlertDialog
(
linknonServerDialog
);
}
break
;
case
LinkContentStatus
.
DownloadedContent
:
{
// コンテンツがダウンロード済み
mActivityFinishFlg
=
true
;
allReset
();
if
(
isEnquete
)
{
isEnquete
=
false
;
mMainLayout
.
removeView
(
enqueteLayout
);
}
//戻る用のコンテンツIDをセット
getABVUIDataCache
().
setReturnContentIdList
(
getContentId
(),
getCurrentPageNumber
());
Intent
intent
=
new
Intent
();
intent
.
putExtra
(
"page"
,
page
-
1
);
Logger
.
d
(
TAG
,
"next page : %s"
,
(
page
-
1
));
if
(
mProjectId
!=
null
)
{
intent
.
putExtra
(
ABookKeys
.
PROJECT_ID
,
mProjectId
);
}
startContentViewActivity
(
intent
,
contentId
);
}
break
;
case
LinkContentStatus
.
StreamingContent
:
{
Intent
intent
=
new
Intent
();
intent
.
putExtra
(
"page"
,
page
-
1
);
startStreamingActivity
(
contentId
,
intent
);
}
break
;
case
LinkContentStatus
.
ShowDetailContent
:
{
// 未ダウンロードの場合詳細画面アラートを表示
showDetailOpenAlert
();
}
break
;
}
}
private
boolean
checkValidContentLink
(
long
contentId
)
{
ContentDto
content
=
AbstractDao
.
getDao
(
ContentDao
.
class
).
getContent
(
contentId
);
if
(
content
==
null
)
{
...
...
@@ -5100,39 +5012,9 @@ public class ContentViewActivity extends ABVContentViewActivity {
return
ContentJSON
.
KEY_PDF_TYPE
.
equals
(
content
.
contentType
)
||
ContentJSON
.
KEY_NONE_TYPE
.
equals
(
content
.
contentType
);
}
private
void
showDetailOpenAlert
()
{
//해당 콘텐츠를 다운받기위한 AlertDialog 호출
ABookAlertDialog
linkDialog
=
AlertDialogUtil
.
createAlertDialog
(
ContentViewActivity
.
this
,
getString
(
R
.
string
.
confirm
),
getString
(
R
.
string
.
link_non_download
));
linkDialog
.
setNegativeButton
(
R
.
string
.
no
,
new
DialogInterface
.
OnClickListener
()
{
@Override
public
void
onClick
(
DialogInterface
dialog
,
int
which
)
{
dialog
.
dismiss
();
}
});
//해당 콘텐츠가 없는 경우 다운 받기 위하여 Detail 화면으로 이동하여 콘텐츠 다운로드
linkDialog
.
setPositiveButton
(
R
.
string
.
confirm
,
new
DialogInterface
.
OnClickListener
()
{
@Override
public
void
onClick
(
DialogInterface
dialog
,
int
which
)
{
contentLinkStatus
=
true
;
//jeonghun 콘텐츠 링크 실행시 앙케이트 닫아 버린다.
if
(
isEnquete
)
{
isEnquete
=
false
;
mMainLayout
.
removeView
(
enqueteLayout
);
}
contentDetailActivityMove
(
getContentId
(),
ContentViewActivity
.
class
.
getName
(),
mCurrentPageNumber
,
contentLinkStatus
);
}
});
showAlertDialog
(
linkDialog
);
}
/**
*
콘텐츠 링크 중 콘텐츠가 없을 경우 콘텐츠 다운을 받기위하여
* c
ontentDetailActivityMove 를 다시 한번 호출
*
コンテンツリンク中でコンテンツがない場合、ダウンロードするように
* c
heckContentをもう一度呼び出す
*
*/
...
...
@@ -5154,7 +5036,7 @@ public class ContentViewActivity extends ABVContentViewActivity {
}
});
}
else
{
contentDetailActivityMove
(
getContentId
(),
ContentViewActivity
.
class
.
getName
(),
mCurrentPageNumber
,
contentLinkStatus
);
ActivityHandlingHelper
.
getInstance
().
checkContent
(
getContentId
(),
mCurrentPageNumber
);
}
}
...
...
ABVJE_UI_Android/src/jp/agentec/abook/abv/ui/viewer/activity/HTMLWebViewActivity.java
View file @
3e307bda
...
...
@@ -52,7 +52,6 @@ import jp.agentec.abook.abv.bl.dto.ContentDto;
import
jp.agentec.abook.abv.bl.logic.AbstractLogic
;
import
jp.agentec.abook.abv.bl.logic.ContentCustomLogLogic
;
import
jp.agentec.abook.abv.bl.logic.ContractLogic
;
import
jp.agentec.abook.abv.bl.net.PanoServer
;
import
jp.agentec.abook.abv.cl.util.ContentLogUtil
;
import
jp.agentec.abook.abv.cl.util.LocationManagerUtil
;
import
jp.agentec.abook.abv.cl.util.PreferenceUtil
;
...
...
@@ -382,7 +381,7 @@ public class HTMLWebViewActivity extends ParentWebViewActivity {
}
else
{
// AndroidOSが5以下のPANO_SERVER処理のため、置き換える必要がある。
url
=
"/"
+
url
;
if
(
url
.
startsWith
(
PanoServer
.
SEND_CUSTOM_LOG
))
{
if
(
url
.
startsWith
(
ABookKeys
.
SEND_CUSTOM_LOG
))
{
CommonExecutor
.
execute
(
new
Runnable
()
{
@Override
public
void
run
()
{
...
...
@@ -403,7 +402,6 @@ public class HTMLWebViewActivity extends ParentWebViewActivity {
commonShouldOverrideUrlLoading
(
uri
,
null
);
}
}
return
true
;
}
...
...
@@ -757,24 +755,21 @@ public class HTMLWebViewActivity extends ParentWebViewActivity {
pauseBtn
.
setVisibility
(
View
.
GONE
);
exitMeetingBtn
.
setVisibility
(
View
.
GONE
);
promoteBtn
.
setVisibility
(
View
.
GONE
);
}
else
{
}
else
{
subMenuBtn
.
setVisibility
(
View
.
GONE
);
mBtnRemoteStart
.
setVisibility
(
View
.
GONE
);
pauseBtn
.
setVisibility
(
View
.
VISIBLE
);
exitMeetingBtn
.
setVisibility
(
View
.
VISIBLE
);
promoteBtn
.
setVisibility
(
View
.
VISIBLE
);
}
}
else
{
}
else
{
closeButton
.
setVisibility
(
View
.
VISIBLE
);
if
(
objectId
==
-
1
)
{
historyListBtn
.
setVisibility
(
View
.
VISIBLE
);
if
(!(
ABVDataCache
.
getInstance
().
serviceOption
.
isABookCheck
()
&&
ABVEnvironment
.
getInstance
().
isABookCheck
()))
{
subMenuBtn
.
setVisibility
(
View
.
VISIBLE
);
}
}
else
{
}
else
{
historyListBtn
.
setVisibility
(
View
.
GONE
);
subMenuBtn
.
setVisibility
(
View
.
GONE
);
}
...
...
ABVJE_UI_Android/src/jp/agentec/abook/abv/ui/viewer/activity/HTMLXWalkWebViewActivity.java
View file @
3e307bda
...
...
@@ -2,11 +2,8 @@ package jp.agentec.abook.abv.ui.viewer.activity;
import
android.content.DialogInterface
;
import
android.content.Intent
;
import
android.database.Cursor
;
import
android.net.Uri
;
import
android.os.Bundle
;
import
android.provider.MediaStore
;
import
android.view.Gravity
;
import
android.view.KeyEvent
;
import
android.view.MotionEvent
;
import
android.view.View
;
...
...
@@ -30,7 +27,6 @@ import org.xwalk.core.XWalkView;
import
org.xwalk.core.XWalkWebResourceRequest
;
import
org.xwalk.core.XWalkWebResourceResponse
;
import
java.io.File
;
import
java.util.ArrayList
;
import
java.util.Date
;
import
java.util.HashMap
;
...
...
@@ -53,23 +49,17 @@ import jp.agentec.abook.abv.bl.logic.AbstractLogic;
import
jp.agentec.abook.abv.bl.logic.ContentCustomLogLogic
;
import
jp.agentec.abook.abv.bl.logic.ContentReadingLogLogic
;
import
jp.agentec.abook.abv.bl.logic.ContractLogic
;
import
jp.agentec.abook.abv.bl.logic.ProjectLogic
;
import
jp.agentec.abook.abv.bl.net.PanoServer
;
import
jp.agentec.abook.abv.cl.util.ContentLogUtil
;
import
jp.agentec.abook.abv.cl.util.PreferenceUtil
;
import
jp.agentec.abook.abv.launcher.android.R
;
import
jp.agentec.abook.abv.ui.common.appinfo.AppDefType
;
import
jp.agentec.abook.abv.ui.common.constant.ErrorCode
;
import
jp.agentec.abook.abv.ui.common.constant.ErrorMessage
;
import
jp.agentec.abook.abv.ui.common.dialog.ABookAlertDialog
;
import
jp.agentec.abook.abv.ui.common.util.ABVToastUtil
;
import
jp.agentec.abook.abv.ui.common.util.AlertDialogUtil
;
import
jp.agentec.abook.abv.ui.common.view.ABVPopupListWindow
;
import
jp.agentec.abook.abv.ui.home.helper.ActivityHandlingHelper
;
import
jp.agentec.abook.abv.ui.home.helper.PanoViewHelper
;
import
jp.agentec.adf.util.DateTimeFormat
;
import
jp.agentec.adf.util.DateTimeUtil
;
import
jp.agentec.adf.util.FileUtil
;
/**
* Created by leej on 2018/04/17.
...
...
@@ -341,7 +331,7 @@ public class HTMLXWalkWebViewActivity extends ParentWebViewActivity {
public
boolean
shouldOverrideUrlLoading
(
XWalkView
view
,
String
url
)
{
Logger
.
d
(
TAG
,
"shouldOverrideUrlLoading: %s"
,
url
);
if
(
url
.
startsWith
(
PanoServer
.
ABOOK
))
{
if
(
url
.
startsWith
(
ABookKeys
.
ABOOK
))
{
final
Uri
uri
=
Uri
.
parse
(
url
);
if
(
isStreaming
)
{
if
(
url
.
startsWith
(
"abooksendlog://"
))
{
// ログ送信完了
...
...
@@ -368,7 +358,7 @@ public class HTMLXWalkWebViewActivity extends ParentWebViewActivity {
}
else
{
// AndroidOSが5以下のPANO_SERVER処理のため、置き換える必要がある。
url
=
"/"
+
url
;
if
(
url
.
startsWith
(
PanoServer
.
SEND_CUSTOM_LOG
))
{
if
(
url
.
startsWith
(
ABookKeys
.
SEND_CUSTOM_LOG
))
{
CommonExecutor
.
execute
(
new
Runnable
()
{
@Override
public
void
run
()
{
...
...
@@ -386,15 +376,15 @@ public class HTMLXWalkWebViewActivity extends ParentWebViewActivity {
}
});
}
else
if
(
url
.
startsWith
(
PanoServer
.
MOVEPAGE
)
||
url
.
startsWith
(
PanoServer
.
CONTENTLINK
)
||
url
.
startsWith
(
PanoServer
.
DETAILLOG
)){
else
if
(
url
.
startsWith
(
ABookKeys
.
MOVEPAGE
)
||
url
.
startsWith
(
ABookKeys
.
CONTENTLINK
)
||
url
.
startsWith
(
ABookKeys
.
DETAILLOG
)){
Map
<
String
,
String
>
param
=
new
HashMap
<
String
,
String
>();
for
(
String
key
:
uri
.
getQueryParameterNames
())
{
param
.
put
(
key
,
uri
.
getQueryParameter
(
key
));
}
param
.
put
(
PanoServer
.
URI
,
url
);
param
.
put
(
ABookKeys
.
URI
,
url
);
// プロジェクト関連資料なのかをチェック
if
(
url
.
startsWith
(
PanoServer
.
CONTENTLINK
)
&&
ABVEnvironment
.
getInstance
().
isABookCheck
())
{
if
(
url
.
startsWith
(
ABookKeys
.
CONTENTLINK
)
&&
ABVEnvironment
.
getInstance
().
isABookCheck
())
{
Long
dstContentId
=
Long
.
valueOf
(
param
.
get
(
"contentId"
));
if
(
ActivityHandlingHelper
.
getInstance
().
isExistCommonContent
(
contentId
))
{
if
(!
ActivityHandlingHelper
.
getInstance
().
isExistCommonContent
(
dstContentId
))
{
...
...
@@ -409,33 +399,33 @@ public class HTMLXWalkWebViewActivity extends ParentWebViewActivity {
}
}
String
ret
=
PanoViewHelper
.
getInstance
().
doParameter
(
param
,
getApplicationContext
(),
contentId
,
lastPageNo
,
readingLogId
,
lastPageStartDate
,
new
Callback
()
{
String
ret
=
doParameter
(
param
,
getApplicationContext
(),
contentId
,
lastPageNo
,
readingLogId
,
lastPageStartDate
,
new
Callback
()
{
@Override
public
Object
callback
(
Object
ret
)
{
Map
<
String
,
Object
>
map
=
(
Map
<
String
,
Object
>)
ret
;
if
(
map
.
containsKey
(
PanoServer
.
PARAM_LAST_PAGE_NUMBER
))
{
lastPageNo
=
(
int
)
map
.
get
(
PanoServer
.
PARAM_LAST_PAGE_NUMBER
);
if
(
map
.
containsKey
(
ABookKeys
.
PARAM_LAST_PAGE_NUMBER
))
{
lastPageNo
=
(
int
)
map
.
get
(
ABookKeys
.
PARAM_LAST_PAGE_NUMBER
);
}
if
(
map
.
containsKey
(
PanoServer
.
PARAM_LAST_PAGE_START_DATE
))
{
lastPageStartDate
=
(
Date
)
map
.
get
(
PanoServer
.
PARAM_LAST_PAGE_START_DATE
);
if
(
map
.
containsKey
(
ABookKeys
.
PARAM_LAST_PAGE_START_DATE
))
{
lastPageStartDate
=
(
Date
)
map
.
get
(
ABookKeys
.
PARAM_LAST_PAGE_START_DATE
);
}
if
(
map
.
containsKey
(
PanoServer
.
PARAM_READING_LOG_ID
))
{
readingLogId
=
(
Integer
)
map
.
get
(
PanoServer
.
PARAM_READING_LOG_ID
);
if
(
map
.
containsKey
(
ABookKeys
.
PARAM_READING_LOG_ID
))
{
readingLogId
=
(
Integer
)
map
.
get
(
ABookKeys
.
PARAM_READING_LOG_ID
);
}
return
null
;
}
});
if
(
ret
!=
null
&&
!
ret
.
startsWith
(
PanoServer
.
OK
))
{
if
(
ret
!=
null
&&
!
ret
.
startsWith
(
ABookKeys
.
OK
))
{
showSimpleAlertDialog
(
getRString
(
R
.
string
.
error
),
ret
);
}
}
else
if
(
url
.
startsWith
(
PanoServer
.
GETITS_OPEN_SHARE
))
{
}
else
if
(
url
.
startsWith
(
ABookKeys
.
GETITS_OPEN_SHARE
))
{
Map
<
String
,
String
>
param
=
new
HashMap
<
String
,
String
>();
for
(
String
key
:
uri
.
getQueryParameterNames
())
{
param
.
put
(
key
,
uri
.
getQueryParameter
(
key
));
}
String
shareUrl
=
null
;
if
(
param
.
containsKey
(
PanoServer
.
PARAM_SHARE_URL
))
{
shareUrl
=
(
String
)
param
.
get
(
PanoServer
.
PARAM_SHARE_URL
);
if
(
param
.
containsKey
(
ABookKeys
.
PARAM_SHARE_URL
))
{
shareUrl
=
(
String
)
param
.
get
(
ABookKeys
.
PARAM_SHARE_URL
);
}
if
(
beaconDialog
!=
null
&&
beaconDialog
.
isShowing
())
{
Logger
.
d
(
TAG
,
"Already Open Beacon Dialog"
);
...
...
@@ -449,7 +439,7 @@ public class HTMLXWalkWebViewActivity extends ParentWebViewActivity {
beaconDialog
.
setNegativeButton
(
R
.
string
.
cancel
,
new
DialogInterface
.
OnClickListener
()
{
@Override
public
void
onClick
(
DialogInterface
dialog
,
int
whichButton
)
{
javaScriptSignageCmd
(
PanoServer
.
CMD_GETITS_CLOSE_SHARE
,
webView
);
javaScriptSignageCmd
(
ABookKeys
.
CMD_GETITS_CLOSE_SHARE
,
webView
);
dialog
.
dismiss
();
}
});
...
...
@@ -459,7 +449,7 @@ public class HTMLXWalkWebViewActivity extends ParentWebViewActivity {
}
}
return
true
;
}
else
if
(
url
.
startsWith
(
PanoServer
.
PING
))
{
}
else
if
(
url
.
startsWith
(
ABookKeys
.
PING
))
{
return
true
;
}
return
false
;
...
...
ABVJE_UI_Android/src/jp/agentec/abook/abv/ui/viewer/activity/PanoViewActivity.java
deleted
100644 → 0
View file @
32ec4e3a
package
jp
.
agentec
.
abook
.
abv
.
ui
.
viewer
.
activity
;
import
android.content.ActivityNotFoundException
;
import
android.content.DialogInterface
;
import
android.os.Build
;
import
android.os.Bundle
;
import
android.widget.TextView
;
import
jp.agentec.abook.abv.bl.common.log.Logger
;
import
jp.agentec.abook.abv.launcher.android.R
;
import
jp.agentec.abook.abv.ui.common.dialog.ABookAlertDialog
;
import
jp.agentec.abook.abv.ui.common.util.AlertDialogUtil
;
import
jp.agentec.abook.abv.ui.home.helper.PanoViewHelper
;
/**
* 360度コンテンツを表示する画面
* 内部サーバーを作成して起動させる
* Created by jang on 2016/03/07.
*/
public
class
PanoViewActivity
extends
NoPdfViewActivity
{
private
static
final
String
TAG
=
PanoViewActivity
.
class
.
getSimpleName
();
@Override
protected
void
onCreate
(
Bundle
savedInstanceState
)
{
super
.
onCreate
(
savedInstanceState
);
if
(
Build
.
VERSION
.
SDK_INT
<
Build
.
VERSION_CODES
.
JELLY_BEAN_MR1
)
{
// 4.2.2
showAlertMessage
(
R
.
string
.
msg_require_ver422
);
return
;
}
try
{
PanoViewHelper
.
getInstance
().
startPanoContent
(
this
,
path
,
contentId
);
}
catch
(
ActivityNotFoundException
e
)
{
showAlertMessage
(
R
.
string
.
msg_require_chrome
);
return
;
}
Logger
.
d
(
TAG
,
"[startPanoContent]"
);
TextView
message
=
(
TextView
)
findViewById
(
R
.
id
.
txt_message
);
message
.
setText
(
getString
(
R
.
string
.
msg_pano_viewer
));
}
private
void
showAlertMessage
(
int
messageId
)
{
final
ABookAlertDialog
alertDialog
=
AlertDialogUtil
.
createAlertDialog
(
this
,
getString
(
R
.
string
.
confirm
),
getString
(
messageId
));
alertDialog
.
setPositiveButton
(
R
.
string
.
ok
,
new
DialogInterface
.
OnClickListener
()
{
@Override
public
void
onClick
(
DialogInterface
dialog
,
int
which
)
{
finishActivity
();
}
});
showAlertDialog
(
alertDialog
);
}
}
ABVJE_UI_Android/src/jp/agentec/abook/abv/ui/viewer/activity/ParentWebViewActivity.java
View file @
3e307bda
package
jp
.
agentec
.
abook
.
abv
.
ui
.
viewer
.
activity
;
import
android.app.Activity
;
import
android.content.Context
;
import
android.content.DialogInterface
;
import
android.net.Uri
;
import
android.view.View
;
...
...
@@ -12,15 +14,22 @@ import android.widget.RelativeLayout;
import
android.widget.TextView
;
import
java.io.File
;
import
java.util.Date
;
import
java.util.HashMap
;
import
java.util.Map
;
import
jp.agentec.abook.abv.bl.acms.type.ProjectType
;
import
jp.agentec.abook.abv.bl.common.ABVEnvironment
;
import
jp.agentec.abook.abv.bl.common.Callback
;
import
jp.agentec.abook.abv.bl.common.CommonExecutor
;
import
jp.agentec.abook.abv.bl.common.Constant
;
import
jp.agentec.abook.abv.bl.common.constant.ABookKeys
;
import
jp.agentec.abook.abv.bl.common.log.Logger
;
import
jp.agentec.abook.abv.bl.logic.AbstractLogic
;
import
jp.agentec.abook.abv.bl.logic.ContentObjectLogLogic
;
import
jp.agentec.abook.abv.bl.logic.ProjectLogic
;
import
jp.agentec.abook.abv.cl.util.ContentLogUtil
;
import
jp.agentec.abook.abv.cl.util.PreferenceUtil
;
import
jp.agentec.abook.abv.launcher.android.R
;
import
jp.agentec.abook.abv.ui.common.activity.ABVContentViewActivity
;
import
jp.agentec.abook.abv.ui.common.activity.ABVUIActivity
;
...
...
@@ -30,6 +39,10 @@ import jp.agentec.abook.abv.ui.common.constant.ErrorMessage;
import
jp.agentec.abook.abv.ui.common.dialog.ABookAlertDialog
;
import
jp.agentec.abook.abv.ui.common.util.AlertDialogUtil
;
import
jp.agentec.abook.abv.ui.home.helper.ABookCheckWebViewHelper
;
import
jp.agentec.abook.abv.ui.home.helper.ActivityHandlingHelper
;
import
jp.agentec.abook.abv.ui.home.helper.ContentViewHelper
;
import
jp.agentec.adf.util.DateTimeFormat
;
import
jp.agentec.adf.util.DateTimeUtil
;
import
jp.agentec.adf.util.FileUtil
;
public
class
ParentWebViewActivity
extends
ABVContentViewActivity
{
...
...
@@ -330,4 +343,75 @@ public class ParentWebViewActivity extends ABVContentViewActivity {
return
mProjectId
;
}
public
String
doParameter
(
Map
<
String
,
String
>
param
,
Context
context
,
long
contentId
,
Integer
lastPageNo
,
Integer
readingLogId
,
Date
lastPageStartDate
,
Callback
callback
)
{
String
uri
=
param
.
get
(
ABookKeys
.
URI
);
Long
dstContentId
=
Long
.
valueOf
(
param
.
get
(
"contentId"
));
Integer
pageNo
=
param
.
containsKey
(
"pageNo"
)?
Integer
.
valueOf
(
param
.
get
(
"pageNo"
))
-
1
:
0
;
// 1スタートを0スタート
if
(
uri
.
startsWith
(
ABookKeys
.
CONTENTLINK
))
{
int
result
=
ContentViewHelper
.
getInstance
().
linkDownloadChecked
(
dstContentId
,
pageNo
);
Logger
.
d
(
TAG
,
"linkDownloadChecked result=%s"
,
result
);
if
(
result
==
ContentViewHelper
.
LinkContentStatus
.
NoExist
)
{
return
context
.
getString
(
R
.
string
.
msg_require_content_refresh
);
}
ContentLogUtil
.
getInstance
().
endContentPageReadLog
(
contentId
,
lastPageNo
,
readingLogId
);
if
(
result
==
ContentViewHelper
.
LinkContentStatus
.
DownloadedContent
)
{
Activity
currentActivity
=
ActivityHandlingHelper
.
getInstance
().
getContentViewActivity
();
// HTMLWebViewActivityの場合はfinish()を実施して、コンテンツを開く
if
(
currentActivity
instanceof
HTMLWebViewActivity
)
{
currentActivity
.
finish
();
}
ActivityHandlingHelper
.
getInstance
().
startContentActivity
(
dstContentId
,
pageNo
);
}
else
{
int
prePage
=
0
;
ABVContentViewActivity
viewActivity
=
ActivityHandlingHelper
.
getInstance
().
getContentViewActivity
();
if
(
viewActivity
!=
null
)
{
prePage
=
viewActivity
.
getCurrentPageNumber
();
}
if
(
ActivityHandlingHelper
.
getInstance
().
checkContent
(
dstContentId
,
prePage
))
{
ActivityHandlingHelper
.
getInstance
().
startContentActivity
(
dstContentId
,
prePage
);
}
return
null
;
}
}
else
if
(
uri
.
startsWith
(
ABookKeys
.
DETAILLOG
))
{
if
(
readingLogId
==
null
)
{
// 開始
readingLogId
=
ContentLogUtil
.
getInstance
().
startContentReadLog
(
context
,
contentId
,
PreferenceUtil
.
getUserPref
(
context
,
AppDefType
.
DefPrefKey
.
PERMISSION_ACCESS_LOCATION
,
false
));
}
AbstractLogic
.
getLogic
(
ContentObjectLogLogic
.
class
).
insertContentObjectLog
(
contentId
,
readingLogId
,
pageNo
,
param
);
}
else
if
(
uri
.
startsWith
(
ABookKeys
.
MOVEPAGE
))
{
// ブラウザから送られてきた時間は使わず、アプリの時間を用いる
if
(
readingLogId
==
null
)
{
// 開始ページ
readingLogId
=
ContentLogUtil
.
getInstance
().
startContentReadLog
(
context
,
contentId
,
PreferenceUtil
.
getUserPref
(
context
,
AppDefType
.
DefPrefKey
.
PERMISSION_ACCESS_LOCATION
,
false
));
ContentLogUtil
.
getInstance
().
startContentPageReadLog
(
contentId
,
readingLogId
,
pageNo
);
}
else
{
if
(
param
.
get
(
"readingEndDate"
)
!=
null
)
{
// 終了時刻有
ContentLogUtil
.
getInstance
().
endContentPageReadLog
(
contentId
,
pageNo
,
readingLogId
);
}
else
{
ContentLogUtil
.
getInstance
().
endContentPageReadLog
(
contentId
,
lastPageNo
,
readingLogId
);
// crosswalkのときもjsではローカルサーバに送るが受取がないためここで終了を呼び出す。ただしローカルサーバを使う場合2重に処理が走る。
ContentLogUtil
.
getInstance
().
startContentPageReadLog
(
contentId
,
readingLogId
,
pageNo
);
}
}
String
[]
readingStartDate
=
param
.
get
(
"readingStartDate"
).
split
(
","
);
Date
pageStartDate
=
DateTimeUtil
.
toDate
(
readingStartDate
[
0
],
readingStartDate
[
1
],
DateTimeFormat
.
yyyyMMddHHmmss_hyphen
);
if
(
lastPageStartDate
==
null
||
lastPageStartDate
.
before
(
pageStartDate
))
{
lastPageStartDate
=
pageStartDate
;
lastPageNo
=
pageNo
;
}
}
Map
<
String
,
Object
>
ret
=
new
HashMap
<
String
,
Object
>();
if
(
lastPageStartDate
!=
null
)
{
ret
.
put
(
"lastPageStartDate"
,
lastPageStartDate
);
}
if
(
lastPageNo
!=
null
)
{
ret
.
put
(
"lastPageNo"
,
lastPageNo
);
}
if
(
readingLogId
!=
null
)
{
ret
.
put
(
"readingLogId"
,
readingLogId
);
}
callback
.
callback
(
ret
);
return
null
;
}
}
ABVJE_UI_Android/src/jp/agentec/abook/abv/ui/viewer/adapter/PDFIndexDialog.java
View file @
3e307bda
...
...
@@ -23,7 +23,7 @@ import android.widget.TextView;
public
class
PDFIndexDialog
{
//
private static final String TAG = "PDFIndexDialog";
private
static
final
String
TAG
=
"PDFIndexDialog"
;
private
final
int
ROOT_ID
=
0
;
// ルートID
private
List
<
ContentPDFIndexDto
>
dataList
;
// データリスト
private
ContentViewActivity
activity
;
// 呼出元アクティビティ
...
...
gradle.properties
View file @
3e307bda
...
...
@@ -84,8 +84,6 @@ follow_service_option=true
is_check_invalid_passward_limit
=
true
#リピート再生のデフォルト値
repeat_default
=
true
#360°コンテンツ用のWebサーバポート
pano_web_server_port
=
28080
#Setting Info(設定画面のABookについての設定情報)
version_name
=
1.9.401
...
...
@@ -105,9 +103,6 @@ app_log_retention=7
hprof
=
false
repository_fqdn
=
s.abook.bz
default_content_key
=
0000
Beacon_UUID
=
beacon_scan_interval
=
3000
# abvFunctionOptions.xml
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment